#%TITLE% PI_E712 $Revision: 1.2 $
#%NAME%
# Macros to control a piezo PI controller connected via serial line or
# ethernet.
#
#%DESCRIPTION%
# This macro file allows to connect a piezo to a macro motor in SPEC.
#
# %BR%Controllers currently supported are:
#%DL%
#%DT%PI E-712 (SERIAL)%DD%
# ID01
#%DT%PI E-712 (ETHERNET)%DD%
# ID13
# ID16
#%XDL%
#
#
#%END%
#
#%SETUP%
#%DL%
#%DT%Configuring macro motors %DD%
# %DL%
# %DT% 1)
# You must have a "MOTORS" defined with:
# %BR%
# %DL%
# %DT% DEVICE
# set to "pi_e712"
# %DT% TYPE
# set to "Macro Motor"
# %DT% ADDR
# set to the address of the controller, examples:
# %DL%
# %DT% for SERIAL: "1"
# %DT% for ETHERNET: "id13e712"
# %XDL%
#
# %DT% NUM
# must be set also to at least 6
# %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 the piezo axis of the controller
# starting from 1 for the first channel
# %XDL%
# %XDL%
#
#%DT%Extra motor_par() parameters %DD%
# %DL%
# %DT% motor_par(motor,"servo")%DD%
# Returns non zero if the piezo closed loop is active
# %DT% motor_par(motor,"servo",1|0)%DD%
# Activates or open the piezo closed loop
# %XDL%
#
#
#%XDL%
#
#%END%
#
#%HISTORY%
#$Log: pi_e712.mac,v $
#Revision 1.2 2013/07/17 09:38:16 guilloud
#*changed error code file from 712 to gcs common one.
#
#Revision 1.1 2012/05/24 14:35:28 perez
#Add error code handling + motor_par("servo")
#
#Revision 1.0 2012/05/22 14:40:02 perez
#Initial release, tested only with socket interface
#
#
#%END%
#
constant PI_E712_HEAD "PI E712"
need pi_gcs_errcode.mac
global PI_E712[]
#%UU% [personal msg]
#%MDESC%
# Switch on or off the print of debug messages
#
def piezogcsdebug '{
global PI_E712[]
if(PI_E712["debug"]) {
rdef pi_e712__debug \'#\$#\'
piezogvs_prn("debug mode is OFF")
PI_E712["debug"]=0
} else {
rdef pi_e712__debug \'print "PIEZO GCS:","$*"\'
piezogvs_prn("debug mode is ON")
PI_E712["debug"]=1
}
}'
# No debug by default
def pi_e712__debug \'#\$#\'
#%IU%
#%MDESC%
def pi_e712_perr(msg) '{
tty_cntl("md")
printf("%s: ERROR: ",PI_E712_HEAD)
tty_cntl("me")
printf("%s\n", msg)
}'
#%IU%
#%MDESC%
def pi_e712_prn(msg) '{
tty_cntl("md")
printf("%s: ",PI_E712_HEAD)
tty_cntl("me")
printf("%s\n", msg)
}'
#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec after reading the config file
#
def pi_e712_config(num,type,p1,p2,p3) '{
global PI_E712[]
local i
local dev itf
# p1==controller p2==number of motors supported
if(type=="ctrl") {
# erase any previous configuration
if(p1 == 0) { for(i in PI_E712) { delete PI_E712[i] } }
# try to guess the interface to use
dev = pi_e712_ADDR
if(int(pi_e712_ADDR)!=pi_e712_ADDR) {
# the port to use is optional
if(!index(pi_e712_ADDR,":")) {
dev = dev":50000"
}
if(!sock_par(dev,"connect")) {
pi_e712_perr("controller not on ethernet")
return ".error."
}
itf="SOCKET"
sock_par(dev, "timeout", 0.2)
} else {
# serial interface by default
if(ser_par(dev,"device_id") == -1) {
pi_e712_perr("wrong serial line for controller")
return ".error."
}
itf="SERIAL"
}
# keep a record of the full interface
PI_E712[pi_e712_ADDR]["itf"] = itf
PI_E712[pi_e712_ADDR]["dev"] = dev
# at this point, we should be able to work
PI_E712[pi_e712_ADDR]["on"] = 1
# but check that is true
if((ans = pi_e712_putget(dev, itf, "IDN?")) == ".error.") {
pi_e712_perr("no answer from controller")
return ".error."
}
pi_e712_prn(sprintf("found %s controller",itf))
print ans
}
# p1==unit p2==module p3==channel
if(type=="mot") {
local mne
# keep a record of the full interface
motor_par(num,"itf", PI_E712[pi_e712_ADDR]["itf"], "add")
motor_par(num,"dev", PI_E712[pi_e712_ADDR]["dev"], "add")
# minimum check
mne = motor_mne(num)
if(motor_par(num,"channel")<1) {
pi_e712_perr(sprintf("invalid channel for motor: %s", mne))
return ".error."
}
if(motor_par(num,"module")) {
pi_e712_perr(sprintf("invalid module for motor: %s", mne))
return ".error."
}
}
}'
#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec on motor operation.
#
def pi_e712_cmd(num,key,p1,p2) '{
local mne
local ans
local cha
local cmd
if(num == "..") { return }
mne = motor_mne(num)
cha = motor_par(num, "channel")
#
# return the current motor position in mm or deg
#
if (key == "position") {
local pos
cmd = sprintf("POS? %d",cha)
if((ans = pi_e712_motputget(num, cmd)) == ".error.") { return(0) }
if(sscanf(ans,"%d=%f", cha, pos) != 2) {
pi_e712_perr(sprintf("unable to get postion for motor: %s", mne))
return ".error."
}
return(pos)
}
#
# start a motion (p1==abs pos, p2==rel pos, with pos in mm or deg)
#
if (key == "start_one") {
local err
# request the motion (valid only if servo is on)
cmd = sprintf("MOV %d %f", cha, p1)
pi_e712_motput(num, cmd)
# check for errors
if((ans = pi_e712_motputget(num, "ERR?")) == ".error.") {
return ".error."
}
if(sscanf(ans,"%d",err) != 1) {
pi_e712_perr(sprintf("unable to get last error for motor: %s", mne))
return ".error."
}
if(err != 0) {
pi_e712_perr(sprintf("for motor: %s\n%s\n", mne, pi_gcs_get_error(err)))
return ".error."
}
# optional parameter, should not be needed for E712
if((t=motor_par(num,"deadtime")) != 0) {
sleep(t)
}
}
#
#
#
if (key == "get_status") {
# get the bitmask string
ans = pi_e712_motputget(num, sprintf("%c",5))
if(ans == ".error.") { return(ans) }
# get the bitmask
if(sscanf(ans,"%d",mask) != 1) {
pi_e712_perr(sprintf("unable to get status for motor: %s", mne))
return ".error."
}
# moving
if(mask & (1<<(cha-1))) {
return(0x02)
}
# alles klarr
return(0)
}
#
# stop a single motor
#
if (key == "abort_one") {
# in fact, stop all motions
pi_e712_motput(num, sprintf("%c",24))
}
}'
#%IU%
#%MDESC%
# MACRO MOTOR:
# Called by spec on motor operation.
#
def pi_e712_par(num,key,todo,p1) '{
local mne
local ans
local cha
local cmd
# return new motor_par() argins handled
if (key == "?" && todo == "get") {
return("servo")
}
mne = motor_mne(num)
cha = motor_par(num, "channel")
# handle the piezo closed loop
if (key == "servo") {
local srv
if (todo == "set") {
cmd = sprintf("SVO %d %d",cha,(p1?1:0))
pi_e712_motput(num, cmd)
}
cmd = sprintf("SVO? %d",cha)
if((ans = pi_e712_motputget(num, cmd)) == ".error.") { return(0) }
if(sscanf(ans,"%d=%f", cha, srv) != 2) {
pi_e712_perr(sprintf("unable to get servo for motor: %s", mne))
return ".error."
}
return(srv)
}
}'
#%IU%(motor_num, cmd)
#%MDESC%
# Send a string command to the controller using the
# interface configured for the motor specified
# and waits for the controller answer.
# Returns an empty string if no error, ".error." otherwise.
#
def pi_e712_motputget(num, cmd) '{
local ans
ans = pi_e712_motput(num, cmd)
if(ans == ".error.") { return(ans) }
ans = pi_e712_motget(num)
return(ans)
}'
#%IU%(dev, interface, cmd)
#%MDESC%
# Send a string command to the controller using the
# interface specified
# and waits for the controller answer.
# Returns an empty string if no error, ".error." otherwise.
#
def pi_e712_putget(dev, itf, cmd) '{
local ans
ans = pi_e712_put(dev, itf, cmd)
if(ans == ".error.") { return(ans) }
ans = pi_e712_get(dev, itf)
return(ans)
}'
#%IU%(motor_num, cmd)
#%MDESC%
# Send a string command to the controller using the
# interface configured for the motor specified.
# Returns an empty string if no error, ".error." otherwise.
#
def pi_e712_motput(num, cmd) '{
local dev itf
local msg
# no, I am not paranoid
if(!index(motor_par(num,"device_id"),"e712")) {
pi_e712_perr("motor not a PI E712")
return ".error."
}
# retrieve information on controller acces
dev = motor_par(num,"dev")
itf = motor_par(num,"itf")
# chaud devant
ans = pi_e712_put(dev, itf, cmd)
# normal end
return(ans)
}'
#%IU%(dev, interface, cmd)
#%MDESC%
# Send a string command to the controller using the
# interface specificied.
# Returns an empty string if no error, ".error." otherwise.
#
def pi_e712_put(dev, itf, cmd) '{
local msg
# the command terminator is optional
msg = cmd
if(!index(msg,"\n")) {
msg = msg"\n"
}
# chaud devant
if(itf == "SOCKET") {
sock_par(dev,"flush")
sock_put(dev,msg)
} else if(itf == "SERIAL") {
ser_par(dev,"flush")
ser_put(dev,msg)
} else {
pi_e712_perr("wrong interface, hint use \"SOCKET\" or \"SERIAL\"")
return ".error."
}
# normal end
return ""
}'
#%IU%(motor_num)
#%MDESC%
# Waits for a valid string answer from controller using the
# interface configured for the motor specified.
# Returns the string ".error." in case of problem.
#
def pi_e712_motget(num) '{
local dev itf
local ans
# no, I am not paranoid
if(!index(motor_par(num,"device_id"),"e712")) {
pi_e712_perr("motor not a PI E712")
return ".error."
}
# retrieve information on controller acces
dev = motor_par(num,"dev")
itf = motor_par(num,"itf")
# allo?
ans = pi_e712_get(dev,itf)
# normal end
return(ans)
}'
#%IU%(dev, interface)
#%MDESC%
# Waits for a valid string answer from controller using the
# interface specified.
# Returns the string ".error." in case of problem.
#
def pi_e712_get(dev, itf) '{
local ans
# ask for a report
HDW_ERR=0
# allo?
if(itf == "SOCKET") {
ans = sock_get(dev,"\n")
} else if(itf == "SERIAL") {
ans = ser_get(dev,"\n")
} else {
pi_e712_perr("wrong interface, hint use \"SOCKET\" or \"SERIAL\"")
return ".error."
}
# check if timeout
if(HDW_ERR == 3) {
pi_e712_perr("timeout waiting for answer")
return ".error."
}
# normal end
return(ans)
}'
#
#%MACROS%
#%IMACROS%
#%AUTHOR% BLISS MP+RH 2012
#%TOC%
|