Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Bliss
bliss
Commits
2cd10321
Commit
2cd10321
authored
Jun 21, 2021
by
Cyril Guilloud
Browse files
communication of PI E727 + HW tests + comments + ignore error on STP
parent
7fd531b0
Pipeline
#49328
passed with stages
in 154 minutes and 48 seconds
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
bliss/common/motor_group.py
View file @
2cd10321
...
@@ -126,6 +126,9 @@ class _Group(object):
...
@@ -126,6 +126,9 @@ class _Group(object):
@
property
@
property
def
position_with_reals
(
self
):
def
position_with_reals
(
self
):
"""
???
"""
return
self
.
_dial_or_position
(
"position"
,
with_reals
=
True
)
return
self
.
_dial_or_position
(
"position"
,
with_reals
=
True
)
@
property
@
property
...
@@ -133,6 +136,9 @@ class _Group(object):
...
@@ -133,6 +136,9 @@ class _Group(object):
return
self
.
_dial_or_position
(
"dial"
,
with_reals
=
True
)
return
self
.
_dial_or_position
(
"dial"
,
with_reals
=
True
)
def
_dial_or_position
(
self
,
attr
,
with_reals
=
False
):
def
_dial_or_position
(
self
,
attr
,
with_reals
=
False
):
"""
???
"""
positions_dict
=
dict
()
positions_dict
=
dict
()
if
with_reals
:
if
with_reals
:
...
...
bliss/controllers/motors/pi_e51x.py
View file @
2cd10321
...
@@ -41,7 +41,8 @@ responses to them are).
...
@@ -41,7 +41,8 @@ responses to them are).
class
PI_E51X
(
pi_gcs
.
Communication
,
pi_gcs
.
Recorder
,
Controller
):
class
PI_E51X
(
pi_gcs
.
Communication
,
pi_gcs
.
Recorder
,
Controller
):
""" Base class for E517 and E518
"""
Base class for E517 and E518
"""
"""
CHAN_LETTER
=
{
1
:
"A"
,
2
:
"B"
,
3
:
"C"
}
CHAN_LETTER
=
{
1
:
"A"
,
2
:
"B"
,
3
:
"C"
}
...
@@ -96,6 +97,9 @@ class PI_E51X(pi_gcs.Communication, pi_gcs.Recorder, Controller):
...
@@ -96,6 +97,9 @@ class PI_E51X(pi_gcs.Communication, pi_gcs.Recorder, Controller):
# acceleration is not mandatory in config
# acceleration is not mandatory in config
self
.
axis_settings
.
config_setting
[
"acceleration"
]
=
False
self
.
axis_settings
.
config_setting
[
"acceleration"
]
=
False
# should have been set at init of inherited classes.
log_debug
(
self
,
"model=%s"
,
self
.
model
)
def
close
(
self
):
def
close
(
self
):
"""
"""
Called at session exit. 6 times ???
Called at session exit. 6 times ???
...
@@ -106,7 +110,7 @@ class PI_E51X(pi_gcs.Communication, pi_gcs.Recorder, Controller):
...
@@ -106,7 +110,7 @@ class PI_E51X(pi_gcs.Communication, pi_gcs.Recorder, Controller):
def
initialize_hardware
(
self
):
def
initialize_hardware
(
self
):
"""
"""
Called once per controller at first
axis use
.
Called once per controller at first
use of any of the axes
.
"""
"""
# Initialize socket communication.
# Initialize socket communication.
self
.
com_initialize
()
self
.
com_initialize
()
...
@@ -119,6 +123,8 @@ class PI_E51X(pi_gcs.Communication, pi_gcs.Recorder, Controller):
...
@@ -119,6 +123,8 @@ class PI_E51X(pi_gcs.Communication, pi_gcs.Recorder, Controller):
def
initialize_axis
(
self
,
axis
):
def
initialize_axis
(
self
,
axis
):
"""
"""
Called at first access to <axis> (eg: __info__())
- Reads specific config
- Reads specific config
- Adds specific methods
- Adds specific methods
- Switches piezo to ONLINE mode so that axis motion can be caused
- Switches piezo to ONLINE mode so that axis motion can be caused
...
...
bliss/controllers/motors/pi_e727.py
View file @
2cd10321
...
@@ -6,72 +6,82 @@
...
@@ -6,72 +6,82 @@
# Distributed under the GNU LGPLv3. See LICENSE for more info.
# Distributed under the GNU LGPLv3. See LICENSE for more info.
from
bliss.controllers.motor
import
Controller
from
bliss.controllers.motor
import
Controller
from
bliss.common.utils
import
object_method
from
bliss.common.utils
import
object_attribute_get
,
object_attribute_set
,
object_method
from
bliss.common.axis
import
AxisState
from
bliss.common.axis
import
AxisState
from
bliss.common.logtools
import
log_debug
,
log_error
from
bliss.common.logtools
import
log_debug
,
log_error
,
log_info
from
bliss
import
global_map
from
bliss
import
global_map
from
.
import
pi_gcs
from
.
import
pi_gcs
from
bliss.comm.util
import
TCP
"""
class
PI_E727
(
pi_gcs
.
Communication
,
pi_gcs
.
Recorder
,
Controller
):
Bliss controller for ethernet PI E727 piezo controller.
"""
"""
Bliss controller for ethernet PI E727 piezo controller.
"""
model
=
None
class
PI_E727
(
Controller
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
# Called at session startup
# No hardware access
pi_gcs
.
Communication
.
__init__
(
self
)
pi_gcs
.
Recorder
.
__init__
(
self
)
Controller
.
__init__
(
self
,
*
args
,
**
kwargs
)
Controller
.
__init__
(
self
,
*
args
,
**
kwargs
)
self
.
cname
=
"E727"
# Init of controller.
# Init of controller.
def
initialize
(
self
):
def
initialize
(
self
):
"""
"""
Controller intialization : open a single socket for all 3 axes.
Controller intialization.
Called at session startup.
Called Only once per controller even if more than
one axis is declared in config.
"""
"""
# acceleration is not mandatory in config
# acceleration is not mandatory in config
self
.
axis_settings
.
config_setting
[
"acceleration"
]
=
False
self
.
axis_settings
.
config_setting
[
"acceleration"
]
=
False
self
.
trace
(
"controller initialize"
)
# model of the controller.
self
.
host
=
self
.
config
.
get
(
"host"
)
self
.
model
=
"E727"
self
.
trace
(
"opening socket"
)
log_debug
(
self
,
"model=%s"
,
self
.
model
)
self
.
sock
=
pi_gcs
.
get_pi_comm
(
self
.
config
,
TCP
)
global_map
.
register
(
self
,
children_list
=
[
self
.
sock
])
def
finaliz
e
(
self
):
def
clos
e
(
self
):
"""
"""
C
lose the controller socket.
C
alled at session exit. many times ???
"""
"""
# not called at end of device server ??? :(
self
.
com_close
()
# called on a new axis creation ???
self
.
trace
(
"controller finalize"
)
def
initialize_hardware
(
self
):
try
:
"""
self
.
trace
(
"closing socket"
)
Called once per controller at first use of any of the axes.
self
.
sock
.
close
()
except
:
NB: not initialized if accessing to the controller before the axis:
pass
ex: LILAB [1]: napix.controller.command("CCL 1 advanced")
!!! === AttributeError: 'NoneType' object has no attribute 'lock' === !!!
def
trace
(
self
,
str
):
"""
log_debug
(
self
,
"{s:{c}<{n}}"
.
format
(
s
=
str
,
n
=
80
,
c
=
"-"
))
# Initialize socket communication.
self
.
com_initialize
()
# Init of each axis.
def
initialize_axis
(
self
,
axis
):
def
initialize_hardware_axis
(
self
,
axis
):
self
.
trace
(
"axis initialization"
)
"""
Called once per axis at first use of the axis
"""
pass
def
initialize_axis
(
self
,
axis
):
"""
Called at first access to <axis> (eg: __info__())
"""
axis
.
channel
=
axis
.
config
.
get
(
"channel"
,
int
)
axis
.
channel
=
axis
.
config
.
get
(
"channel"
,
int
)
# check communication
# check communication
try
:
_ans
=
self
.
get_identifier
(
axis
)
_ans
=
self
.
get_identifier
(
axis
,
0.1
)
except
Exception
as
ex
:
_str
=
'%r
\n
ERROR on "%s": switch on the controller'
%
(
ex
,
self
.
host
)
# by default, an exception will be raised
log_error
(
self
,
_str
)
# Enables the closed-loop.
# Enables the closed-loop.
# To be imporved.
self
.
_set_closed_loop
(
axis
,
True
)
self
.
_set_closed_loop
(
axis
,
True
)
# supposed that we are on target on init
axis
.
_last_on_target
=
True
def
initialize_encoder
(
self
,
encoder
):
def
initialize_encoder
(
self
,
encoder
):
pass
pass
...
@@ -85,17 +95,31 @@ class PI_E727(Controller):
...
@@ -85,17 +95,31 @@ class PI_E727(Controller):
def
set_off
(
self
,
axis
):
def
set_off
(
self
,
axis
):
pass
pass
"""
POSITION
"""
def
read_position
(
self
,
axis
):
def
read_position
(
self
,
axis
):
_ans
=
self
.
_get_target_pos
(
axis
)
"""
log_debug
(
self
,
"read_position = %f"
%
_ans
)
Return position of the axis.
return
_ans
After movement is finished, return the target position.
"""
if
axis
.
_last_on_target
:
_pos
=
self
.
_get_target_pos
(
axis
)
log_debug
(
self
,
"position read : %g"
%
_pos
)
else
:
# if moving return real position
_pos
=
self
.
_get_pos
(
axis
)
return
_pos
def
read_encoder
(
self
,
encoder
):
def
read_encoder
(
self
,
encoder
):
_ans
=
self
.
_get_pos
(
axis
)
_ans
=
self
.
_get_pos
(
encoder
.
axis
)
log_debug
(
self
,
"read_position measured = %f"
%
_ans
)
log_debug
(
self
,
"read_position measured = %f"
%
_ans
)
return
_ans
return
_ans
""" VELOCITY """
"""
VELOCITY
"""
def
read_velocity
(
self
,
axis
):
def
read_velocity
(
self
,
axis
):
return
self
.
_get_velocity
(
axis
)
return
self
.
_get_velocity
(
axis
)
...
@@ -103,15 +127,16 @@ class PI_E727(Controller):
...
@@ -103,15 +127,16 @@ class PI_E727(Controller):
def
set_velocity
(
self
,
axis
,
new_velocity
):
def
set_velocity
(
self
,
axis
,
new_velocity
):
log_debug
(
self
,
"set_velocity new_velocity = %f"
%
new_velocity
)
log_debug
(
self
,
"set_velocity new_velocity = %f"
%
new_velocity
)
_cmd
=
"VEL %s %f"
%
(
axis
.
channel
,
new_velocity
)
_cmd
=
"VEL %s %f"
%
(
axis
.
channel
,
new_velocity
)
self
.
send_no_ans
(
_cmd
)
self
.
command
(
_cmd
)
self
.
check_error
(
_cmd
)
return
self
.
read_velocity
(
axis
)
return
self
.
read_velocity
(
axis
)
""" STATE """
"""
STATE
"""
def
state
(
self
,
axis
):
def
state
(
self
,
axis
):
self
.
trace
(
"axis state"
)
#
self.trace("axis state")
if
self
.
_get_closed_loop_status
(
axis
):
if
self
.
_get_closed_loop_status
(
axis
):
if
self
.
_get_on_target_status
(
axis
):
if
self
.
_get_on_target_status
(
axis
):
return
AxisState
(
"READY"
)
return
AxisState
(
"READY"
)
...
@@ -120,7 +145,9 @@ class PI_E727(Controller):
...
@@ -120,7 +145,9 @@ class PI_E727(Controller):
else
:
else
:
raise
RuntimeError
(
"closed loop disabled"
)
raise
RuntimeError
(
"closed loop disabled"
)
""" MOVEMENTS """
"""
MOVEMENTS
"""
def
prepare_move
(
self
,
motion
):
def
prepare_move
(
self
,
motion
):
pass
pass
...
@@ -128,106 +155,53 @@ class PI_E727(Controller):
...
@@ -128,106 +155,53 @@ class PI_E727(Controller):
def
start_one
(
self
,
motion
):
def
start_one
(
self
,
motion
):
log_debug
(
self
,
"start_one target_pos = %f"
%
motion
.
target_pos
)
log_debug
(
self
,
"start_one target_pos = %f"
%
motion
.
target_pos
)
# the controller latches the previous error
self
.
clear_error
()
axis
=
motion
.
axis
axis
=
motion
.
axis
_cmd
=
"MOV %s %g"
%
(
axis
.
channel
,
motion
.
target_pos
)
_cmd
=
f
"MOV
{
axis
.
channel
}
{
motion
.
target_pos
}
"
self
.
send_no_ans
(
_cmd
)
self
.
command
(
_cmd
)
self
.
check_error
(
_cmd
)
def
stop
(
self
,
axis
):
def
stop
(
self
,
axis
):
log_debug
(
self
,
"stop requested"
)
"""
self
.
send_no_ans
(
"STP %s"
%
(
axis
.
channel
))
* STP -> stop asap
* 24 -> stop asap
""" COMMUNICATIONS"""
* HLT -> stop smoothly
* Copy of current position into target position at stop
def
send
(
self
,
cmd
,
timeout
=
None
):
* all 3 commands generate (by default) a 'Disable Error 10'.
_cmd
=
self
.
_append_eoc
(
cmd
)
(This can be disabled via parameter 0x0E000301)
_ans
=
self
.
sock
.
write_readline
(
_cmd
.
encode
(),
timeout
=
timeout
).
decode
()
"""
_ans
=
self
.
_remove_eoc
(
_ans
)
log_debug
(
self
,
"stop (HLT) requested"
)
return
_ans
self
.
command
(
"HLT %s"
%
(
axis
.
channel
))
def
clear_error
(
self
):
self
.
_get_error
()
def
check_error
(
self
,
cmd
):
# Check error code
(
_err_nb
,
_err_str
)
=
self
.
_get_error
()
if
_err_nb
!=
0
:
_str
=
'ERROR on cmd "%s": #%d(%s)'
%
(
cmd
,
_err_nb
,
_err_str
)
# by default, an exception will be raised
log_error
(
self
,
_str
)
raise
RuntimeError
(
_str
)
def
send_no_ans
(
self
,
cmd
):
_cmd
=
self
.
_append_eoc
(
cmd
)
self
.
sock
.
write
(
_cmd
.
encode
())
@
object_method
(
types_info
=
(
"None"
,
"None"
))
def
raw_flush
(
self
,
axis
):
self
.
sock
.
flush
()
""" RAW COMMANDS """
def
raw_write
(
self
,
cmd
):
_cmd
=
self
.
_append_eoc
(
cmd
)
self
.
sock
.
write
(
_cmd
.
encode
())
def
raw_write_read
(
self
,
cmd
):
_cmd
=
self
.
_append_eoc
(
cmd
)
return
self
.
sock
.
write_readline
(
_cmd
.
encode
()).
decode
()
def
raw_write_readlines
(
self
,
cmd
,
lines
):
_cmd
=
self
.
_append_eoc
(
cmd
)
ans
=
"
\n
"
.
join
(
[
r
.
decode
().
strip
()
for
r
in
self
.
sock
.
write_readlines
(
_cmd
.
encode
(),
lines
)
]
)
_ans
=
self
.
_remove_eoc
(
ans
)
return
_ans
def
_append_eoc
(
self
,
cmd
):
_cmd
=
cmd
.
strip
()
if
not
_cmd
.
endswith
(
"
\n
"
):
_cmd
=
cmd
+
"
\n
"
log_debug
(
self
,
">>>> %s"
%
(
_cmd
.
strip
(
"
\n
"
)))
return
_cmd
def
_remove_eoc
(
self
,
ans
):
_ans
=
ans
.
strip
()
log_debug
(
self
,
"<<<< %s"
%
_ans
)
return
_ans
"""
"""
E727 specific
E727 specific
"""
"""
@
object_method
(
types_info
=
(
"None"
,
"str"
))
@
object_method
(
types_info
=
(
"None"
,
"str"
))
def
get_identifier
(
self
,
axis
,
timeout
=
None
):
def
get_identifier
(
self
,
axis
):
return
self
.
se
nd
(
"IDN?"
,
timeout
)
return
self
.
comma
nd
(
"IDN?"
)
@
object_method
(
types_info
=
(
"None"
,
"float"
))
def
get_voltage
(
self
,
axis
):
def
get_voltage
(
self
,
axis
):
""" Return voltage read from controller."""
""" Return voltage read from controller."""
_ans
=
self
.
se
nd
(
"SVA?"
)
_ans
=
self
.
comma
nd
(
f
"SVA?
{
axis
.
channel
}
"
)
_voltage
=
float
(
_ans
.
split
(
"="
)[
1
]
)
_voltage
=
float
(
_ans
)
return
_voltage
return
_voltage
@
object_method
(
types_info
=
(
"None"
,
"float"
))
def
get_output_voltage
(
self
,
axis
):
""" Return output voltage read from controller. """
return
float
(
self
.
command
(
f
"VOL?
{
axis
.
channel
}
"
))
def
set_voltage
(
self
,
axis
,
new_voltage
):
def
set_voltage
(
self
,
axis
,
new_voltage
):
""" Set Voltage to the controller."""
""" Set Voltage to the controller."""
_cmd
=
"SVA %s %g"
%
(
axis
.
channel
,
new_voltage
)
_cmd
=
"SVA %s %g"
%
(
axis
.
channel
,
new_voltage
)
self
.
send_no_ans
(
_cmd
)
self
.
command
(
_cmd
)
self
.
check_error
(
_cmd
)
def
_get_velocity
(
self
,
axis
):
def
_get_velocity
(
self
,
axis
):
"""
"""
Return velocity taken from controller.
Return velocity taken from controller.
"""
"""
_ans
=
self
.
se
nd
(
"VEL?
%s"
%
(
axis
.
channel
)
)
_ans
=
self
.
comma
nd
(
f
"VEL?
{
axis
.
channel
}
"
)
_velocity
=
float
(
_ans
.
split
(
"="
)[
1
]
)
_velocity
=
float
(
_ans
)
return
_velocity
return
_velocity
...
@@ -235,57 +209,50 @@ class PI_E727(Controller):
...
@@ -235,57 +209,50 @@ class PI_E727(Controller):
"""
"""
Return real position read by capacitive sensor.
Return real position read by capacitive sensor.
"""
"""
_ans
=
self
.
se
nd
(
"POS?
%s"
%
(
axis
.
channel
)
)
_ans
=
self
.
comma
nd
(
f
"POS?
{
axis
.
channel
}
"
)
_pos
=
float
(
_ans
.
split
(
"="
)[
1
]
)
_pos
=
float
(
_ans
)
return
_pos
return
_pos
""" ON TARGET """
"""
CLOSED LOOP
"""
def
_get_target_pos
(
self
,
axis
):
def
_get_target_pos
(
self
,
axis
):
"""
"""
Return last target position (setpoint value).
Return last target position (setpoint value).
"""
"""
_ans
=
self
.
send
(
"MOV? %s"
%
(
axis
.
channel
))
_ans
=
self
.
command
(
f
"MOV?
{
axis
.
channel
}
"
)
# _ans should looks like "1=-8.45709419e+01"
_pos
=
float
(
_ans
)
_pos
=
float
(
_ans
.
split
(
"="
)[
1
])
return
_pos
return
_pos
def
_get_on_target_status
(
self
,
axis
):
def
_get_on_target_status
(
self
,
axis
):
_ans
=
self
.
send
(
"ONT? %s"
%
(
axis
.
channel
))
"""
Return 'On-target status' (ONT? command) indicating
_status
=
_ans
.
split
(
"="
)[
1
]
if movement is finished and measured position is within
on-target window.
if
_status
==
"1"
:
"""
return
True
last_on_target
=
bool
(
int
(
self
.
command
(
f
"ONT?
{
axis
.
channel
}
"
)))
elif
_status
==
"0"
:
axis
.
_last_on_target
=
last_on_target
return
False
return
last_on_target
else
:
log_error
(
self
,
"ERROR on _get_on_target_status, _ans=%r"
%
_ans
)
return
-
1
""" CLOSED LOOP"""
def
_get_closed_loop_status
(
self
,
axis
):
def
_get_closed_loop_status
(
self
,
axis
):
_ans
=
self
.
send
(
"SVO? %s"
%
(
axis
.
channel
))
_status
=
self
.
command
(
f
"SVO?
{
axis
.
channel
}
"
)
_status
=
_ans
.
split
(
"="
)[
1
]
if
_status
==
"1"
:
if
_status
==
"1"
:
return
True
return
True
elif
_status
==
"0"
:
if
_status
==
"0"
:
return
False
return
False
else
:
log_error
(
self
,
"ERROR on _get_closed_loop_status, _
an
s=%r"
%
_
an
s
)
log_error
(
self
,
"ERROR on _get_closed_loop_status, _
statu
s=%r"
%
_
statu
s
)
return
-
1
return
-
1
def
_set_closed_loop
(
self
,
axis
,
state
):
def
_set_closed_loop
(
self
,
axis
,
state
):
if
state
:
if
state
:
_cmd
=
"SVO
%s 1"
%
(
axis
.
channel
)
_cmd
=
f
"SVO
{
axis
.
channel
}
1"
else
:
else
:
_cmd
=
"SVO %s 0"
%
(
axis
.
channel
)
_cmd
=
f
"SVO
{
axis
.
channel
}
0"
self
.
send_no_ans
(
_cmd
)
self
.
command
(
_cmd
)
self
.
check_error
(
_cmd
)
@
object_method
(
types_info
=
(
"None"
,
"None"
))
@
object_method
(
types_info
=
(
"None"
,
"None"
))
def
open_loop
(
self
,
axis
):
def
open_loop
(
self
,
axis
):
...
@@ -295,45 +262,49 @@ class PI_E727(Controller):
...
@@ -295,45 +262,49 @@ class PI_E727(Controller):
def
close_loop
(
self
,
axis
):
def
close_loop
(
self
,
axis
):
self
.
_set_closed_loop
(
axis
,
True
)
self
.
_set_closed_loop
(
axis
,
True
)
def
_get_error
(
self
):
@
object_attribute_get
(
type_info
=
"bool"
)
# Does not use send() to be able to call _get_error in send().
def
get_closed_loop
(
self
,
axis
):
_error_number
=
int
(
self
.
raw_write_read
(
"ERR?"
))
return
self
.
_get_closed_loop_status
(
axis
)
_error_str
=
pi_gcs
.
get_error_str
(
int
(
_error_number
))
return
(
_error_number
,
_error_str
)
"""
INFO
"""
def
__info__
(
self
):
@
object_attribute_get
(
type_info
=
"str"
)
_tab
=
30
def
get_model
(
self
,
axis
):
return
self
.
model
(
_err_nb
,
_err_str
)
=
self
.
_get_error
()
def
get_id
(
self
,
axis
):
_txt
=
"%*s: %d (%s)
\n
"
%
(
_tab
,
"Last Error"
,
_err_nb
,
_err_str
)
"""
Return controller identifier.
"""
return
self
.
command
(
"*IDN?"
)
_txt
=
_txt
+
"%*s:
\n
%s
\n
"
%
(
def
get_axis_info
(
self
,
axis
):
_tab
,
"""
"Communication parameters"
,
Return Controller specific info about <axis> for user.