#%TITLE% PI_861.MAC
#%NAME% PI_861.MAC - Macros to control the Physik Instrumente NEXACT Motor Controller E-861 alternatively in
# open- and closed-loop mode. %BR%
#$Revision: $
#%DESCRIPTION%
# To define a macro motor controller you must define
# a pi861 controller in config, ADDR is the serial line index number defined
# in spec:
#
#\0\0\0MOTORS\0\0\0\0\0\0\0DEVICE\0\0\0\0ADDR\0\0\0<>MODE\0\0\0\0\0\0NUM\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<>TYPE
#\0\0\0\0\0\0YES\0\0\0\0\0\0\0pi861\0\0\0\0\04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\01\0\0\0\0\0\0\0\0\0Macro\0Motors
#
# Then declare a motor with that controller.
#%SETUP%
# The default serial line speed is 38.4 kB.
#%ATTENTION%
# When being used in open-loop operation, in the so-called "servo-off state". All
# movements are in steps, which, documentation says, are about 10
# micro-meters, depending on the load!
#%END%
# leave those macros alone, if they`re already defined.
if (!(whatis("__pi861debug") & 2)) rdef __pi861debug \'#$*\'
def __pi861_io(sline, send) '{
if (!__PI861["simu"]) { # if NOT simulating
local str
__pi861debug "* Command pi861:", send
str = send "\n"
if (ser_put(sline, str) == -1) {
eprint "PI861 communication error!"
return(".error.")
}
if (index( send, "?") ) { # is there an answer requested ?
return(ser_get(sline, "\n"))
}
else {
return(0)
}
}
else {
local aux[], x
if (index( send, "?") ) { # is there an answer requested ?
x = split(send, aux)
__pi861debug "SIMU:", send
if (aux[0] == "ERR?" ) { answer = 0 }
else if (aux[0] == "ONT?" ) { answer = "1=1" }
else if (aux[0] == "*IDN?" ) { answer = "(c)2008 Physik Instrumente(PI) Karlsruhe,E-861 SIMULATION!!!!!" }
else {
x = split(send, aux, "?")
answer = "1=" __PI861simu[aux[0]]
}
__pi861debug "SIMU:", send, "answer", answer
return(answer)
}
else {
x = split(send, aux)
if (x > 2) {
__pi861debug "SIMU:", send
__PI861simu[aux[0]] = aux[2]
}
}
}
}
'
def pi861_sim '{
__PI861["simu"] = (__PI861["simu"] == 0)
if (!__PI861["simu"]) {
unglobal __PI861simu
}
else {
global __PI861simu[]
__PI861simu["MOV"] = A[pi1]
}
}
'
global __PI861[]
#%UU%
#%MDESC% toggle debug mode for the present macros.
def pi861_debug '{
if ((whatis("__pi861debug")>>16) <= 2) { # just a # sign -> off
rdef __pi861debug "eprint"
print "PI861 debug is ON"
} else {
rdef __pi861debug \'#$*\'
print "PI861 debug is OFF"
}
}
'
def pi861_config(mne, type, unit, module, channel) '{
__pi861debug "* Configuring PI861", mne, type, unit, module, channel
local addr
addr = pi861_ADDR
if (type == "ctrl") {
local answer
local IDstr
IDstr = "(c)2008 Physik Instrumente(PI) Karlsruhe,E-861"
answer = __pi861_io(sline, "*IDN?")
if (index(answer, IDstr)) {
eprint "PI E861 used as macro motor controller"
eprint "Be aware that the position of this kind of motor is relative only!"
eprint "The position in place might not be what you expect!"
} else {
return ".error."
}
}
if (type == "mot") {
local bla[], str, x
x = motor_par(mne, "velocity")
pi861_par(mne, "velocity", "set", x)
x = motor_par(mne, "step_size")
pi861_par(mne, "step_size", "set", x)
__PI861[mne]["axis"] = motor_par(mne,"channel")+1
motor_par(mne, "mode") # sets our variable __PI861[mne]["mode"]
}
}
'
def pi861_par(mne, cmd, p1, p2) '{
if ( mne == ".." ) {
return
}
local sline
sline = motor_par(mne, "address")
__pi861debug "Parameters PI861",mne, cmd, p1, p2
if (cmd == "velocity" && p1 == "set") {
local str
str = "OVL " channel + 1 " " p2
return(__pi861_io(sline, str))
}
else if (cmd == "torque" && p1 == "set") {
local str
str = "SSA " channel + 1 " " p2
return(__pi861_io(sline, str))
}
else if (cmd == "mode") {
local str, answer, loopmode
if (p1 == "get") {
str = "SVO? " __PI861[mne]["axis"] # answers axis=1|0\n - 1 for servo on!
if ((answer = __pi861_io(sline, str)) == ".error.") {
return(".error.")
}
loopmode = int(substr(answer, 3, 1))
__PI861[mne]["mode"] = loopmode
__PI861[mne]["mtimestamp"] = time()
return (loopmode)
}
else if (p1 == "set") {
str = "SVO " __PI861[mne]["axis"] " " (p2!=0)
# set position
if (p2) { # switch servo on
__PI861[mne]["position"] = A[mne] = pi861_cmd(mne, "position")
}
else {
__PI861[mne]["position"] = A[mne] = 0
}
__PI861[mne]["mode"] = (p2!=0)
return(__pi861_io(sline, str))
}
}
}
'
def pi861_cmd(mne, cmd, p1, p2) '{
if ( mne == ".." ) {
return
}
__pi861debug "Command PI861",mne, cmd, p1, p2
# some house keeping for the open/closed-loop mode. If the last check for the mode was more
# than 24 H ago, do it again.
__pi861debug "Command PI861", time() - __PI861[mne]["mtimestamp"]
if ((time() - __PI861[mne]["mtimestamp"]) > 86400) { #seconds are 24H
motor_par(mne, "mode") # sets our variable __PI861[mne]["mode"]
}
# from hereon, the variable __PI861[mne]["mode"] will be used to distinguish between open-
# and closed-loop mode. 1 is closed-loop / servo on!
local sline
sline = motor_par(mne, "address")
if ( cmd == "get_status" ) {
# __pi861_geterr(sline)
local str, answer
str = "ONT? " __PI861[mne]["axis"] # answers axis=1|0\n - 1 for on target!
if ((answer = __pi861_io(sline, str)) == ".error.") {
return(".error.")
}
# this will be ok for both open- and closed-loop
if (substr(x, 3, 1)) {
return 0x02
}
return(0)
}
else if ( cmd == "start_one") {
local str
if (__PI861[mne]["mode"]) { # servo on
str = "MOV " __PI861[mne]["axis"] " " p1
}
else {
# we need to do relative moves only, use p2 instead of p1!
str = "OSM " __PI861[mne]["axis"] " " p2
}
__PI861[mne]["position"] = p1
return(__pi861_io(sline, str))
}
else if ( cmd == "position") {
local str
if (__PI861[mne]["mode"]) { # servo on
str = "MOV? " __PI861[mne]["axis"]
x = __pi861_io(sline, str)
__PI861[mne]["position"] = substr(x, 3)
__pi861debug "position", __PI861[mne]["position"]
return(__PI861[mne]["position"])
}
else {
# in open-loop mode we can`t get a position. We have to rely
# on spec to do the house keeping.
return __PI861[mne]["position"]
}
}
else if ( cmd == "set_position") {
__PI861[mne]["position"] = p1
}
else if ( cmd == "abort_one") {
# __pi861_io("STP")
return(__pi861_io(sline, "\030")) # ascii 24 to prefer over STP, says manual
}
}
'
#%IU%
#%MDESC% Returns identification message from the controller.
def __pi861_version() '{
return __pi861_io(sline, "*IDN?")
}'
#%IU%
#%MDESC% Returns identification message from the controller.
def __pi861_geterr(sline) '{
local err
err = __pi861_io(sline, "ERR?")
if (err == ".error.") return(err)
if (err != 0) eprint __PI861["error"][err]
return err
}'
# there are about 600 error messages, which I didn`t think necessary to list
# here.
__PI861["error"][ 0] = "No error"
__PI861["error"][ 1] = "Parameter syntax error"
__PI861["error"][ 2] = "Unknown command"
__PI861["error"][ 3] = "Command length out of limits or command buffer overrun"
__PI861["error"][ 4] = "Error while scanning"
__PI861["error"][ 5] = "Unallowable move attempted on unreferenced axis, or move attempted with serv off"
__PI861["error"][ 6] = "Parameter for SGA not valid"
__PI861["error"][ 7] = "Position out of limits"
__PI861["error"][ 8] = "Velocity out of limits"
__PI861["error"][ 9] = "Attempt to set pivot point while U,V and W not all 0"
__PI861["error"][10] = "Controller was stopped by command"
__PI861["error"][11] = "Parameter for SST or for one of the embedded scan algorithms out of range"
__PI861["error"][12] = "Invalid axis combination for fast scan"
__PI861["error"][13] = "Parameter for NAV out of range"
__PI861["error"][14] = "Invalid analog channel"
__PI861["error"][15] = "Invalid axis identifier"
__PI861["error"][16] = "Unknown stage name"
__PI861["error"][17] = "Parameter out of range"
__PI861["error"][18] = "Invalid macro name"
__PI861["error"][29] = "Error while recording macro"
__PI861["error"][20] = "Macro not found"
__PI861["error"][21] = "Axis has no brake"
__PI861["error"][22] = "Axis identifier specified more than once"
__PI861["error"][23] = "Illegal axis"
__PI861["error"][24] = "Incorrect number of parameters"
__PI861["error"][25] = "Invalid floating point number"
__PI861["error"][26] = "Parameter missing"
__PI861["error"][27] = "Soft limit out of range"
__PI861["error"][28] = "No manual pad found"
__PI861["error"][29] = "No more step-response values"
__PI861["error"][30] = "No step-response values recorded"
__PI861["error"][31] = "Axis has no reference sensor"
__PI861["error"][32] = "Axis has no limit switch"
__PI861["error"][33] = "No relay card installed"
__PI861["error"][34] = "Command not allowed for selected stage(s)"
__PI861["error"][35] = "No digital input installed"
__PI861["error"][36] = "No digital output configured"
__PI861["error"][37] = "No more MCM responses"
__PI861["error"][38] = "No MCM values recorded"
__PI861["error"][39] = "Controller number invalid"
__PI861["error"][40] = "No joystick configured"
__PI861["error"][41] = "Invalid axis for electronic gearing, axis can not be slave"
__PI861["error"][42] = "Position of slave axis is out of range"
__PI861["error"][43] = "Slave axis cannot be commanded directly when electronic gearing is enabled"
__PI861["error"][44] = "Calibration of joystick failed"
__PI861["error"][45] = "Referencing failed"
__PI861["error"][46] = "OPM (Optical Power Meter) missing"
__PI861["error"][47] = "OPM (Optical Power Meter) not initialized or cannot be initialized"
__PI861["error"][48] = "OPM (Optical Power Meter) Communication Error"
__PI861["error"][49] = "Move to limit switch failed"
#-----------------------------------------------------------
#%UU% motor [open/close]
#%MDESC% changes the controller from open- to closed-loop mode and vice versa
def pi861_mode '{
local mode, newmode, Usage
Usage = "$0: bad argument: use motor_mne [open|closed]"
if ($# == 0) {
eprint Usage
exit
}
if (motor_num("$1") == -1) {
eprint "No such motor \"$1\""
exit
}
mode = motor_par("$1", "mode")
print "Controller is in", mode ? "closed" : "open", "loop mode"
if ($# == 2) {
if ("$2" == "open") {
newmode = 0
}
else if ("$2" == "closed" || "$2" == "close") {
newmode = 1
}
else {
eprint Usage
exit
}
if (newmode != mode) {
motor_par("$1", "mode", newmode)
print "change to", newmode ? "closed" : "open", "loop mode"
}
else {
print "No change"
}
}
}' # Ends macro pi861_mode
#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
# stlocal.mac, pseudo.mac
#%END%
#%BUGS% Bugs ? What bugs ??
#%AUTHOR%
#Holger (BLISS) for ID18.
#%TOC%
|