#%TITLE% pi_e753.mac $Revision: 1.14 $
#%NAME%
# Macros to control a piezo PI E753 controller connected via TCP/IP.
#
#%DESCRIPTION%
# the PI E-753 is a single channel controller for piezo actuator.
#
#
# For debug purpose mainly, it is also possible to configure a macro
# counter that will read the position of a piezo axis. But to avoid
# duplicating parameters, the counter has no parameter and takes them
# from its corresponding macro motor. In order to guess the motor
# to use, the name of the counter must be the same as the motor with
# %B%\"_c\"%B% added at the end.
# For instance: %B%\"nnn_x_c\"%B% for %B%\"nnn_x\"%B%
#
#%END%
#
#%SETUP%
# In order to configure a macro motor:
# %DL%
# %DT% 1)
# You must have a "MOTORS" defined with:
# %BR%
# %DL%
# %DT% DEVICE
# set to "pi_e753"
# %DT% TYPE
# set to "Macro Motor"
# %DT% ADDR
# set to the TCP Address of the controller
# %DT% NUM
# must be set to 1
# %XDL%
# %DT% 2)
# Per piezo axis you must define a motor with:
# %BR%
# %DL%
# %DT% Controller
# set to "MAC_MOT"
# %DT% Unit
# field must be set to the "MOTOR" entry.
# %DT% Chan
# field must be set to 0 the piezo axis of the controller
# %XDL%
# %XDL%
#
# In order to configure a macro counter:
# %DL%
# %DT% 1)
# You must have a "SCALERS" defined with:
# %BR%
# %DL%
# %DT% DEVICE
# set to "pi_e753_c"
# %DT% TYPE
# set to "Macro Counter"
# %DT% NUM
# must be set also
# %XDL%
# %DT% 2)
# Per piezo axis you must define a counter with:
# %BR%
# %DL%
# %DT% Device
# set to "MAC_CNT"
# %DT% Mnemonic
# must the motor mne plus "_c"
# %DT% Unit
# do not mind
# %DT% Chan
# do not mind
# %XDL%
#
# %XDL%
#%END%
#
#%HISTORY%
#$Log: pi_e753.mac,v $
#Revision 1.14 2020/02/28 09:26:11 witsch
#function pi_e753_get_model finding the substring E-753 in the IDN string,
#was done with substr. That failed, when the controller changed the return
#string. Now, it is using index(), which will find it, if it there.
#..
#
#Revision 1.13 2018/09/27 09:25:40 mauro
#Correct the message connection with the address during the reconfig
#In the info macro TMX and TMN were inverted during the print screen - Corrected
#
#Revision 1.12 2017/03/23 10:17:51 perez
#Add waveform generation macros
#
#Revision 1.11 2017/03/20 14:57:38 guilloud
#fix bug in argument testing in info fuinction
#
#Revision 1.10 2014/10/24 14:47:46 guilloud
#error number for TAD command (broken cable ???)
#
#Revision 1.9 2014/02/13 16:50:51 guilloud
#some debugs...
#
#Revision 1.8 2014/02/04 09:29:07 guilloud
#*added traces for tcp_put calls
#*+pi_e753_get_real_pos(mot_num) position given by the capacitive captor
#*+i_e753_set_open_loop_pos(mot_num, position) ends "SVA 1 <position>"
#*Fixed "pz1" hardcoded bug in pi_e753_stop(mot_num)
#*more parameters in info
#*+ set velocity according to spec config value
#*open loop mode available
#
#Revision 1.7 2013/09/25 08:08:01 guilloud
#*need hg
#*err test on sock_put
#*fix if (pi_e753_get_closed_loop_status(mot_num) == 1){
#*refine config message
#*add closed loop status display in config
#
#Revision 1.6 2013/09/11 14:16:57 guilloud
#change messages for HG.mac
#simplify some messages
#removed PI_E753[idx]["model"]
#
#Revision 1.5 2013/08/30 16:57:58 homsrego
#fix macro counter
#
#Revision 1.4 2013/08/29 12:10:40 homsrego
#fix print error
#
#Revision 1.3 2013/07/11 14:36:53 guilloud
#* removed sleeps
#* use setpoint rather than real position in "get_pos"
#* status test ONT only in closed loop mode now
#* infos macro improved for useful parameters display (and descriptions)
#* Auto zero calibration procedure removed (useless if controller is well configured)
#
#Revision 1.2 2012/07/26 14:05:20 guilloud
#error codes
#
#Revision 1.1 2012/07/26 13:59:07 guilloud
#Initial revision
#
#
#%END%
#
need hg
need spec_utils
need pi_gcs_errorcodes
global PI_E753[]
######################################################################
########################### ###########################
########################### DEBUG & INFO ###########################
########################### ###########################
######################################################################
hg_config_style("pi_e753", 0, 0, 0)
hg_config_indent("pi_e753", 0, 0, 1)
hg_config_headers("pi_e753", "PI_E753", "PI_E753", "PI_E753")
hg_generate("pi_e753")
######################################################################
########################### ##########################
########################### COMMUNICATION ##########################
########################### ##########################
######################################################################
#%IU%(<tcp_dev>, <cmd>)
#%MDESC%
# Sends <cmd> to a tcp device.
# Adds \n at end of <cmd>
# Uses tcp/ip device : <tcp_dev>.
def pi_e753_tcp_put(tcp_dev, cmd, from) '{
local _ans
local _cmd _cmd_woec
# Purges <cmd>.
# woec : without ending char...
_cmd_woec = removeEndingChar(cmd, "\n")
_cmd_woec = removeEndingChar(_cmd_woec, "\r")
# Adds terminators.
_cmd = sprintf("%s\n", _cmd_woec)
# Flush ?
#sock_par(tcp_dev, "flush")
#sock_par(tcp_dev, "timeout", 3)
pi_e753_dbg(sprintf("tcp_put():\ntcp_dev=%s\ncmd=\"%s\"\nfrom=%s", \
tcp_dev, _cmd_woec, from))
if(sock_put(tcp_dev, _cmd) == -1){
pi_e753_err(sprintf("sock_put error in pi_e753_tcp_put(tcp_dev=%s, _cmd=%s) from=%s", \
tcp_dev, _cmd, from))
}
}'
#%IU%(<tcp_dev>)
#%MDESC%
# Returns ???
def pi_e753_tcp_get(tcp_dev) '{
local _ans
_ans = sock_get(tcp_dev)
return(_ans)
}'
#%IU%(<mot_num>, <cmd>)
#%MDESC%
# Send <cmd> to controller of motor <mot_num> and returns the answer.
# <mot_num> : SPEC motor number.
# <cmd> : String with or without terminator.
def pi_e753_send(mot_num, cmd, from) '{
local _tcp_dev
_tcp_dev = motor_par(mot_num, "tcp_dev")
# re printed in pi_e753_tcp_put pi_e753_dbg(sprintf("_tcp_dev = %s", _tcp_dev))
if(_tcp_dev == "0"){
pi_e753_err( " pi_e753_send() : bad motor name or undefined motor (_tcp_dev == \"0\")")
return( -1)
}
sock_par(_tcp_dev, "flush")
pi_e753_dbg(sprintf("SEND \"%s\" to %s (from=%s)",cmd, _tcp_dev, from))
if(pi_e753_tcp_put(_tcp_dev, cmd, 214) == -1){
return( -1)
}
if ((_ans = pi_e753_tcp_get(_tcp_dev)) == -1){
return( -1)
}
else{
local _ans_woec
_ans_woec = removeEndingChar(_ans, "\n")
_ans_woec = removeEndingChar(_ans_woec, "\r")
pi_e753_dbg(sprintf("GET \"%s\" from %s ", _ans_woec, _tcp_dev))
_ans = removeEndingChar(_ans, "\n")
return(_ans)
}
}'
#%IU%(<mot_num>, <cmd>)
#%MDESC%
# Sends <cmd> to controller corresponding to motor <mot_num> do not
# wait for an answer.
def pi_e753_send_no_ans(mot_num, cmd, from) '{
local _tcp_dev
_tcp_dev = motor_par(mot_num, "tcp_dev")
pi_e753_dbg(sprintf("_tcp_dev = %s", _tcp_dev))
sock_par(_tcp_dev, "flush")
pi_e753_dbg(sprintf("SEND %s to %s (from=%s)", cmd, _tcp_dev, from))
if(pi_e753_tcp_put(_tcp_dev, cmd, 246) == -1){
return( -1)
}
}'
#######################################################################
####################### #######################
####################### CONTROLLER MANAGEMENT #######################
####################### #######################
#######################################################################
#%IU%(<mot_num>)
#%MDESC%
# Returns the setpoint read from the controller.
#
def pi_e753_get_pos(mot_num) '{
local _ans _pos _cmd _mne
_mne = motor_mne(mot_num)
# _cmd = sprintf("POS?") <--- position read by sensor
# We prefer to read the set point value.
_cmd = sprintf("MOV?")
_ans = pi_e753_send(mot_num, _cmd)
# _ans should looks like "1=-8.45709419e+01\n"
_ans = removeEndingChar(_ans , "\n")
_pos = substr(_ans, 3) + 0.0
pi_e753_dbg( sprintf("in pi_e753_get_pos _ans=%s _pos=%s", _ans, _pos))
return (_pos)
}'
#%IU%(<mot_num>)
#%MDESC%
# Returns the position given by the capacitive captor.
#
def pi_e753_get_real_pos(mot_num) '{
local _ans _pos _cmd _mne
_mne = motor_mne(mot_num)
# position read by sensor
_cmd = sprintf("POS?")
_ans = pi_e753_send(mot_num, _cmd)
# _ans should looks like "1=-8.45709419e+01\n"
_ans = removeEndingChar(_ans , "\n")
_pos = substr(_ans, 3) + 0.0
pi_e753_dbg( sprintf("in pi_e753_get_real_pos _ans=%s _pos=%s", _ans, _pos))
return (_pos)
}'
#%IU%(<mot_num>, <position>)
#%MDESC%
# Sends to controller of axis corresponding to <mot_num> a
# move to <position> command.
# Sends "MOV 1 <position>"
def pi_e753_set_pos(mot_num, position) '{
local _mne _cmd
pi_e753_dbg( sprintf("in pi_e753_set_pos mot_num=%s position=%s ", mot_num, position))
_cmd = sprintf("MOV 1 %g", position)
pi_e753_send_no_ans(mot_num, _cmd)
# return( ?)
}'
#%IU%(<mot_num>, <position>)
#%MDESC%
# Sends to controller of axis corresponding to <mot_num> a
# move to <position> command.
# Sends "SVA 1 <position>"
def pi_e753_set_open_loop_pos(mot_num, position) '{
local _mne _cmd
pi_e753_dbg( sprintf("in pi_e753_set_open_loop_pos mot_num=%s position=%s ", mot_num, position))
_cmd = sprintf("SVA 1 %g", position)
pi_e753_send_no_ans(mot_num, _cmd)
# return( ?)
}'
#
#
#
def test_status '{
local ii
printf("MOTION STATUS | ONT STATUS")
for (ii=0 ; ii<30; ii++){
printf("%s | %s ", \
pi_e753_get_motion_status(pz), \
pi_e753_get_ont_status(pz) \
)
print ""
sleep(0.01)
}
}'
#%IU%(<mot_num>)
#%MDESC%
# Returns the error code read from the controller.
# ERR? command clean the last error code seen.
#
def pi_e753_get_err(mot_num) '{
local _ans _cmd _mne _error _error_str
pi_e753_dbg( sprintf("in pi_e753_get_err mot : %s(%s)", \
motor_mne(mot_num), mot_num))
_mne = motor_mne(mot_num)
_cmd = sprintf("ERR?")
_ans = pi_e753_send(mot_num, _cmd)
_error = removeEndingChar(_ans , "\n")
_error_str = pi_gcs_get_error(_error)
pi_e753_dbg( sprintf("in pi_e753_get_err _error=%s", _error))
pi_e753_dbg( sprintf("in pi_e753_get_err _error_str =%s", _error_str))
return (_error)
}'
######################################################################
############################## ##############################
############################## STATUS ##############################
############################## ##############################
######################################################################
#%IU%(<mot_num>)
#%MDESC%
#
#
def pi_e753_get_status(mot_num) '{
local _ans _pos _status
pi_e753_dbg(sprintf( "in pi_e753_get_status mot_num=%s ", mot_num))
# First, checks if closed-loop is active.
if (pi_e753_get_closed_loop_status(mot_num) == 1){
pi_e753_dbg( "closed loop active")
# get ON TARGET status : only usable in closed loop mode.
_ans = pi_e753_get_ont_status(mot_num)
}
else{
# not in closed loop => ON_TARGET status not usable.
pi_e753_dbg( "closed loop disabled")
return(1)
}
return(_status)
}'
#%IU%(mot_num)
#%MDESC%
# Returns 1 if closed loop is active
# Returns 0 if closed loop is NOT active
# Returns -1 otherwise
def pi_e753_get_closed_loop_status(mot_num) '{
local _ans
pi_e753_dbg(sprintf("in pi_e753_get_closed_loop_status mot_num=%s", mot_num))
_ans = removeEndingChar(pi_e753_send(mot_num, "SVO?"))
if ( _ans == "1=1" ){
# closed loop active
return(1)
}
else if(_ans == "1=0"){
# closed loop NOT active
return(0)
}
else{
print "ERROR in pi_e753_get_closed_loop_status"
return(-1)
}
}'
#%IU%(<mot_num>)
#%MDESC%
# Returns the individual "on-target status" of axis corresponding
# to motor <mot_num>
# Sends "ONT?
def pi_e753_get_ont_status(mot_num) '{
local _ans _pos _status
pi_e753_dbg( "in pi_e753_get_ont_status ")
_ans = pi_e753_send(mot_num, "ONT?")
_ans = removeEndingChar(_ans , "\n")
pi_e753_dbg(sprintf( "in pi_e753_get_status _ans=%s", _ans))
_chan = substr(_ans, 1, 1)
_status = substr(_ans, 3, 1)
return(_status)
}'
#%IU%(<mot_num>)
#%MDESC%
# Returns the "motion status" of axis corresponding
# to motor <mot_num>
# Sends "#5"
def pi_e753_get_motion_status(mot_num) '{
local _ans _pos _status
pi_e753_dbg( "in pi_e753_get_motion_status " )
_ans = pi_e753_send(mot_num, "#5")
_ans = removeEndingChar(_ans , "\n")
pi_e753_dbg( sprintf("in pi_e753_get_motion_status _ans=%s", _ans))
#_chan = substr(_ans, 1, 1)
_status = _ans
return(_status)
}'
#%IU%(<mot_num>)
#%MDESC%
# Sends to controller of motor <mot_num> a stop command.
# Sends "STP" (no HLT in e-753...)
#
def pi_e753_stop(mot_num) '{
pi_e753_dbg( "in pi_e753_stop " )
pi_e753_send_no_ans(mot_num, "STP")
# return( ?)
}'
# ERROR CODES SEEN :
#
# 1 : Syntax error
# 2 : Unknown command
# 5 : Unallowable move attempted on unreferenced axis,
# or move attempted with servo off
# 7 : position out of limits
# 10 : controller was stopped by command
# 17 : parameter out of range
# 24 : wrong number of parameters
# 88 : ??? not found in manual...
#%UU% <mot_num>
#%MDESC%
#
def pi_e753_infos '{
local _mot_num
local _sys_ans
local _tmp_arr[]
local _ip_addr[]
local _err
if ($# == 0){
print "pi_e753_infos : please give a motor number"
exit
}
_mot_num = motor_num("$1")
pi_e753_dbg(sprintf("_mot_num=%s", _mot_num))
print date()
printf(" %25s IDN?: %s\n", "Controller Identification", pi_e753_send(_mot_num, "IDN?"))
printf(" %25s IFC?: %s\n", "Communication parameters", removeChars(pi_e753_send(_mot_num, "IFC?"), "\n"))
printf(" %25s ERR?: %s\n", "Error code", _err = pi_e753_send(_mot_num, "ERR?"))
printf(" %25s : %s\n", "Error string", pi_gcs_get_error(_err))
# Parsing of IFC answer to get ip address and hostname
split(pi_e753_send(_mot_num, "IFC?"), _tmp_arr, "\n")
split( substr(_tmp_arr[1], 7), _ip_addr, ":")
printf(" %25s : %s\n", "ip address", _ip_addr[0])
unix (sprintf("host %s | cut -d\" \" -f5", _ip_addr[0]), _hostname)
printf(" %25s : %s","hostname", _hostname)
printf(" %25s CCL?: %s\n", "command level", pi_e753_send(_mot_num, "CCL?"))
printf(" %25s POS?: %s\n", "Real Position", removeChars(pi_e753_send(_mot_num, "POS?"), "\n"))
printf(" %25s MOV?: %s\n", "Setpoint Position", removeChars(pi_e753_send(_mot_num, "MOV?"), "\n") )
printf(" %25s POS?-MOV?: %s\n", "SP RP diff", pi_e753_get_real_pos(_mot_num) - pi_e753_get_pos(_mot_num) )
printf(" %25s TMN?: %s\n", "Position low limit", pi_e753_send(_mot_num, "SPA? 1 0x07000000"))
printf(" %25s TMX?: %s\n", "Position High limit", pi_e753_send(_mot_num, "SPA? 1 0x07000001"))
printf(" %25s TAD?: %s\n", "ADC value of analog input", removeChars(pi_e753_send(_mot_num, "TAD?"), "\n"))
#### TAD[1]==131071 => broken cable ??
# 131071 = pow(2,17)-1
printf(" %25s VEL?: %s\n", "Velocity?", removeChars(pi_e753_send(_mot_num, "VEL?"), "\n"))
printf(" %25s ONT?: %s\n", "On target", removeChars(pi_e753_send(_mot_num, "ONT?"), "\n"))
printf(" %25s : %s\n", "target tolerance", pi_e753_send(_mot_num, "SPA? 1 0X07000900"))
printf(" %25s : %s\n", "settling time", pi_e753_send(_mot_num, "SPA? 1 0X07000901"))
printf(" %25s : %s\n", "Sensor Offset", pi_e753_send(_mot_num, "SPA? 1 0x02000200"))
printf(" %25s : %s\n", "Sensor Gain", pi_e753_send(_mot_num, "SPA? 1 0x02000300"))
printf(" %25s #5: %s\n", "Motion status", removeChars(pi_e753_send(_mot_num, "#5"), "\n"))
printf(" %25s SVO?: %s\n", "Closed loop status", removeChars(pi_e753_send(_mot_num, "SVO?"), "\n"))
printf(" %25s SVA?: %s\n", "Open loop setpoint", removeChars(pi_e753_send(_mot_num, "SVA?"), "\n"))
printf(" %25s TSP?: %s\n", "Analog Setpoints", removeChars(pi_e753_send(_mot_num, "TSP?"), "\n"))
printf(" %25s AOS?: %s\n", "Analog Input Offset", removeChars(pi_e753_send(_mot_num, "AOS?"), "\n"))
printf(" %25s ATZ?: %s\n", "Auto Zero Calibration ?", removeChars(pi_e753_send(_mot_num, "ATZ?"), "\n"))
printf(" %25s : %s\n", "Low Voltage Limit", removeChars(pi_e753_send(_mot_num, "SPA? 1 0x07000A00"), "\n"))
printf(" %25s : %s\n", "High Voltage Limit", removeChars(pi_e753_send(_mot_num, "SPA? 1 0x07000A01"), "\n"))
}'
#%UU%(<tcp_dev>)
#%MDESC%
# Returns the controller model name (should be E-753)
def pi_e753_get_model(tcp_dev) '{
local _model _idn _ans
sock_par(tcp_dev, "flush")
_ans = pi_e753_tcp_put(tcp_dev, "IDN?\n", 589)
_idn = pi_e753_tcp_get(tcp_dev)
pi_e753_dbg( sprintf("IDN=%s",_idn))
_model = index(_idn, "E-753")
if (_model) {
return("E-753")
}
else {
return("UNKNOWN")
}
}'
#%IU%
#%MDESC%
# Checks if controller is responding
# Sends "IDN?"
def pi_e753_check_ctrl(mot_num) '{
local _tcp_dev
_tcp_dev = motor_par(mot_num, "tcp_dev")
if(pi_e753_tcp_put(_tcp_dev, "IDN?", 614) == -1){
return (-1)
}
if ((_ans = pi_e753_tcp_get(_tcp_dev)) == -1){
return (-1)
}
else{
print _ans
}
return (1)
}'
######################################################################
############################ ###########################
############################ MACRO MOTOR ###########################
############################ ###########################
######################################################################
#%IU%()
#%MDESC%
# Called by spec after reading the config file
#
def pi_e753_config(mot_num, type, p1, p2, p3) '{
local _msg
if(type=="ctrl") {
local _tcp_dev _model
# p1==controller number (0..N)
# p2==number of motors supported (1..M) (should be 1 for e753)
if (p2 != 1){
pi_e753_err("Wrong number of motors in config (must be 1)")
}
# Gets address from SPEC config.
_tcp_dev = sprintf("%s:50000", pi_e753_ADDR)
pi_e753_dbg( sprintf("pi_e753_config(%s, %s, %s) _tcp_dev = %s", \
mot_num, type, p1, _tcp_dev))
# Opens a socket to the specified host and port : _tcp_dev
# Returns true (1) for success and false (0) for failure.
sock_par(_tcp_dev, "close")
if (sock_par(_tcp_dev, "connect") == 1){
_model = pi_e753_get_model(_tcp_dev)
# Just checks if controller is really a 753.
if (_model == "E-753"){
printf("[PI_E753] Using controller piezo PI ")
cprint(_model, 4, 8)
printf(" address = %s\n", pi_e753_ADDR)
}
else{
pi_e753_err( sprintf("WRONG MODEL : %s ", _model))
return ".error."
}
}
else{
local _cmd
_cmd = sprintf("Controller piezo E753 on address %s is not responding", \
_tcp_dev)
pi_e753_err(_cmd)
# -> will not configure motors attached to this controller.
return (".error.")
}
}
else if(type=="mot") {
# p1==unit p2==module p3==channel
local _tcp_dev
local _mot_mne
local _velocity
# print "-------------------ctrl-------------------------"
# print pi_e753_CONPAR
# print "addr= " pi_e753_ADDR
# print "--------------------------------------------"
_tcp_dev = sprintf("%s:50000", pi_e753_ADDR)
_mot_mne = motor_mne(mot_num)
pi_e753_dbg(sprintf("pi_e753_config(),_tcp_dev=%s ",_tcp_dev))
# Saves tcp dev in a custom parameter.
pi_e753_dbg(sprintf("_tcp_dev saved in custom param : %s", _tcp_dev))
motor_par(mot_num, "tcp_dev", _tcp_dev, "add")
if (_err = pi_e753_get_err(mot_num) != 0 ) {
print ""
pi_e753_err(sprintf("ERR : %s", _err))
print ""
}
# pi_e753_infos mot_num
# _ans = pi_e753_send(mot_num, "ATZ?")
# print ""
# sleep(0.1)
# if (_ans == "1=0"){
# print "auto zero calibration not done"
# ### no need to do an Auto zero calibration if the controller is well configured.
# }
# Enables SERVO (Closed-loop) mode:
pi_e753_send_no_ans(mot_num, "SVO 1 1")
# Displays status of closed loop.
printf("[PI_E753] piezo motor \"%s\" : closed loop is ",_mot_mne)
cprint_on_off( pi_e753_get_closed_loop_status(mot_num))
print ""
# Set velocity
_velocity = motor_par(mot_num, "velocity")
printf("[PI_E753] piezo motor \"%s\" : velocity set to %d\n", \
_mot_mne, _velocity)
pi_e753_send_no_ans(mot_num, sprintf("VEL 1 %s", _velocity))
}
else {
pi_e753_err(sprintf("pi_e753_config() : unknown type : %s ", type ))
}
}'
#%IU%()
#%MDESC%
# Called by spec on motor operation.
def pi_e753_par(mot_num, key, todo, p1) '{
local _srv _cmd _ans _mne
# Returns new motor_par() argins handled
if (key == "?" && todo == "get") {
return("servo")
}
_mne = motor_mne(mot_num)
# Handles the piezo closed loop activation.
if (key == "servo") {
local _srv
if (todo == "set") {
_cmd = sprintf("SVO 1 %d",(p1?1:0))
pi_e753_send_no_ans(mot_num, _cmd)
}
# Checks if CL well enabled.
# ??? pk ca pourrai valoir ".error." ????
if ((_ans = pi_e753_get_closed_loop_status(mot_num)) == ".error."){
return(0)
}
else{
return(_ans)
}
}
}'
#%IU%()
#%MDESC%
# MACRO MOTOR:
# Called by spec on motor operation.
#
def pi_e753_cmd(mot_num, key, p1, p2) '{
local _mne
if(mot_num == "..") {
return
}
_mne = motor_mne(mot_num)
_tcp_dev = motor_par(mot_num, "tcp_dev")
# Returns the current motor position in mm or deg
if (key == "position") {
local pos
pos = pi_e753_get_pos(mot_num)
pi_e753_dbg( sprintf("position() : pos : %s micron", pos))
return(pos)
}
# Starts a motion (p1==abs pos, p2==rel pos, with pos in mm or deg)
if (key == "start_one") {
local aux
pi_e753_dbg(sprintf( "start_one(): pos : %s micron", p1))
if (pi_e753_get_closed_loop_status(mot_num)){
pi_e753_set_pos(mot_num, p1)
}
else{
pi_e753_set_open_loop_pos(mot_num, p1)
}
# ???
if((t=motor_par(mot_num, "deadtime")) != 0) {
pi_e753_dbg( sprintf("start_one(): sleeping: %s seconds", t))
sleep(t)
}
}
# Status
if (key == "get_status") {
# First check if closed-loop is active.
if (pi_e753_get_closed_loop_status(mot_num)){
_pos = pi_e753_get_real_pos(mot_num)
pi_e753_dbg(sprintf("_pos in get_status (mne=%s) :%s \n",_mne, _pos))
# ON TARGET status : only usable in closed loop mode.
_status = pi_e753_get_ont_status(mot_num)
}
else{
if (pi_e753_get_motion_status(mot_num) == 0){
# no motion
_status = 1
}
}
if (_status == 0) {
# moving.
return (0x02)
}
else {
# on-target or movement finished.
return(0)
}
}
# Stops a single motor.
if (key == "abort_one") {
pi_e753_dbg( "pi_e753_cmd abort_one()")
pi_e753_stop(mot_num)
return 1
}
}'
######################################################################
########################### ##########################
########################### MACRO COUNTER ##########################
########################### ##########################
######################################################################
#%IU%()
#%MDESC%
# Called by spec after reading the config file
#
def pi_e753_c_config(num,type,p1,p2,p3) '{
#
if(type=="ctrl") {
# ?
}
#
if(type=="cnt") {
local mot_mne mot_num cmne suffix, l, mmne
cmne = cnt_mne(num)
l = length(cmne)
suffix = substr(cmne, l-1)
if(suffix != "_c") {
pi_e753_err(sprintf("\nE753 ERROR invalid counter [%s] (bad suffix [%s])\n", \
cmne, suffix))
return ".error."
}
mmne = substr(cmne, 1, l-2)
mot_num = motor_num(mmne)
if(mot_num == -1) {
pi_e753_err(sprintf("\nE753 ERROR invalid counter [%s] (invalid motor [%s])\n", \
cmne, mmne))
return ".error."
}
#_msg = "motor num = " mot_num
#cprint(_msg , 1)
PI_E753[num]["cnt/mot_num"]= mot_num
}
}'
#%IU%()
#%MDESC%
# Called by spec on counter operation.
#
def pi_e753_c_cmd(num,key,p1,p2) '{
if (key == "counts") {
local pos
local mot_num
local mne
mne = cnt_mne(num)
mot_num = PI_E753[num]["cnt/mot_num"]
# print " " mot_num
# pos = pi_e753_get_pos(mot_num)
pos = pi_e753_get_real_pos(mot_num) # <--- we want the real position
return(pos)
}
}'
######################################################################
########################### ##########################
########################### WAVEFORM ##########################
########################### ##########################
######################################################################
#%UU% <motor> <hz> <amplitude>
#%MDESC%
# Start waveform generation on given motor.
#%BR%<motor> : SPEC motor.
#%BR%<hz> : frequency of the wave in Hz.
#%BR%<ampl> : wave amplitude in microns.
#
def pi_e753_wav_start '{
local mot_num
local hz
local ampl
if($# < 3) {
print "Usage: $0 motor hz amplitude"
exit
}
if((mot_num = motor_num("$1")) == -1) {
exit
}
hz = $2
ampl = $3
_pi_e753_wav_start(mot_num, hz, ampl)
pi_e753_wav_status $1
}'
#%IU%(<mot_num>, <hz>, <ampl>)
#%MDESC%
# Start waveform generation on motor <mot_num>.
#%BR%<mot_num>: SPEC motor number.
#%BR%<hz> : frequency of the wave in Hz.
#%BR%<ampl> : wave amplitude in microns.
#
def _pi_e753_wav_start(mot_num, hz, ampl) '{
local _cmd
local _ans
local _tt[]
local _stime _wtr _npts
# minimum checks
if(!index(motor_par(mot_num, "device_id"), "e753")) {
pi_e753_err("Not a PI E753 macro motor")
return(-1)
}
# TODO: add some limits on values
if(hz == 0) {
pi_e753_err("Wrong frequency in Hz")
return(-1)
}
# TODO: add some limits on values
if(ampl == 0) {
pi_e753_err("Wrong amplitude in microns")
return(-1)
}
# get the servo update time
_ans = removeEndingChar(pi_e753_send(mot_num, "SPA? 1 0x0e000200"))
if(split(_ans, _tt, "=") != 2) {
pi_e753_err("Unable to get servo update time")
return(-1)
}
if(sscanf(_tt[1], "%f", _stime) != 1) {
pi_e753_err("Unable to parse servo update time")
return(-1)
}
pi_e753_dbg(sprintf("Servo update time: %fusec", _stime*1e6))
# get wave table rate
_ans = removeEndingChar(pi_e753_send(mot_num, "SPA? 1 0x13000109"))
if(split(_ans, _tt, "=") != 2) {
pi_e753_err("Unable to get WTR")
return(-1)
}
if(sscanf(_tt[1], "%d", _wtr) != 1) {
pi_e753_err("Unable to parse WTR")
return(-1)
}
pi_e753_dbg(sprintf("Wave table rate : %d", _wtr))
# calculate the number of points to get the wanted period
_npts = int(1 / (_wtr * _stime * hz))
# TODO: add some limits on values
pi_e753_dbg(sprintf("Wave total points: %d", _npts))
# use first wave table and overwrite it
_cmd = sprintf("WAV 1 X")
# generate an inverted cosine curve
_cmd = sprintf("%s SIN_P", _cmd)
# wave length in points
_cmd = sprintf("%s %d", _cmd, _npts)
# wave amplitude
_cmd = sprintf("%s %d", _cmd, ampl)
# wave offset
_cmd = sprintf("%s 0", _cmd)
# wave length
_cmd = sprintf("%s %d", _cmd, _npts)
# wave start point
_cmd = sprintf("%s 0", _cmd)
# wave center
_cmd = sprintf("%s %d", _cmd, int(_npts/2))
pi_e753_dbg(sprintf("Waveform command : %s\n", _cmd))
pi_e753_send_no_ans(mot_num, _cmd)
if (_err = pi_e753_get_err(mot_num) != 0 ) {
pi_e753_err(sprintf("ERR : %s", _err))
return(-1)
}
# connect wave table #1 to wave generator #1
pi_e753_send_no_ans(mot_num, "WSL 1 1")
# launch wave generation
_pi_e753_wav_action(mot_num, 1)
}'
#%UU% <motor>
#%MDESC%
# Print out the waveform status for given motor.
#
def pi_e753_wav_stop '{
if($# != 1) {
print "Usage: $0 motor"
exit
}
_pi_e753_wav_stop(motor_num("$1"))
pi_e753_wav_status $1
}'
#%IU%(<mot_num>)
#%MDESC%
# Stop waveform generation on motor <mot_num>.
# Returns the state of waveform generator.
#
def _pi_e753_wav_stop(mot_num) '{
local _ret
_ret = _pi_e753_wav_action(mot_num, 0)
# position discrepancies between spec and the motor hardware will
#be silently resolved in favor of the hardware
read_motors(0x06)
return(_ret)
}'
#%IU%(<mot_num>, <action>)
#%MDESC%
# Starts or stop waveform generation on motor <mot_num>.
# Returns the state of waveform generator.
#
def _pi_e753_wav_action(mot_num, todo) '{
# NOTE: the E753 has only one waveform generator
pi_e753_send_no_ans(mot_num, sprintf("WGO 1 %d", (todo!=0)?1:0))
return(_pi_e753_wav_status(mot_num))
}'
#%UU% <motor>
#%MDESC%
# Print out the waveform status for given motor.
#
def pi_e753_wav_status '{
if($# != 1) {
print "Usage: $0 motor"
exit
}
printf("Motor \"%s\" waveform generator is: %s\n", \
"$1", \
_pi_e753_wav_status(motor_num("$1"))?"ON":"OFF")
}'
#%IU%(<mot_num>)
#%MDESC%
# Returns non null if a waveform is beeing generated on motor <mot_num>.
#
def _pi_e753_wav_status(mot_num) '{
local ans
_ans = removeEndingChar(pi_e753_send(mot_num, "WGO?"))
return(!(_ans == "1=0"))
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% BLISS 2006
#%BR%$Revision: 1.14 $ / $Date: 2020/02/28 09:26:11 $
#%BR%$RCSfile: pi_e753.mac,v $
#%TOC%
|