#%TITLE% VAT_PM5.MAC
#%NAME%
# Macros for controlling VAT Adaptive Pressure Controller
# through a serial line. The current macros have been tested with
# model PM5 but should work with model PM3.
#
#%DESCRIPTION%
#%DL%
# %DT% - Configure the serial line connected to the controler.
# The default serial line configuration is 4800bauds/7bits/even
#
# %DT% - Configure a macro motor:
# The motor will control the valve in position or in pressure.
# The channel field is used to select the mode (1 for position,
# 2 for pressure)
# %B%"device"%B%field set to string "vat_pm5"
# %B%"addr"%B%field set to the serial line entry
# %B%"num"%B%field set to 4
# %B%"type"%B%field set to "Macro Motors"
#
# %DT% - Configure a macro counter (optional):
# %B%"device"%B%field set to string "vat_pm5"
# %B%"addr"%B%field set to the serial line entry
# %B%"num"%B%field set to 4
# %B%"type"%B%field set to "Macro Counter"
#
# %DT% - Some macros are also available
#%XDL%
#
global VAT_PM5_ERR[]
VAT_PM5_ERR["000001"] = "Parity Error"
VAT_PM5_ERR["000002"] = "CR or LF is missing"
VAT_PM5_ERR["000003"] = "Semicolon is missing"
VAT_PM5_ERR["000004"] = "Wrong letter code"
VAT_PM5_ERR["000005"] = "Numerical value not given is 6 digits"
VAT_PM5_ERR["000006"] = "Numerical value larger than 1000"
VAT_PM5_ERR["000007"] = "Missing sensor, check connection"
VAT_PM5_ERR["000008"] = "Instruction given in operating mode LOCAL"
VAT_PM5_ERR["000101"] = "Error with LEARN command"
VAT_PM5_ERR["000200"] = "Error with ZERO command"
global VAT_PM5_DEV[]
#%IU%(action, [controller])
#%MDESC%
# Open (action == 1) or close (action == 2) the valve
#
def _vataction(act, args) '{
local dev
local ctl
local val
local tgt
local silent
# Minimum check
if(whatis("VAT_PM5_DEV") & 0x08000000) {
_vat_pm5_err
print "missing at least one macro motor configuration for the VAT"
return
}
# Retrieve serial line to use from macro motor configuration
if(args != "") { ctl = sscanf(args, "%d") }
dev = VAT_PM5_DEV[ctl]
silent = 1
# Action
printf("%s valve... ", (act==1)?"Opening":"Closing")
if( _vat_pm5_query(dev, (act==1)?"O:":"C:", silent) == "") {
_vat_pm5_err
printf("unable to %s valve\n", (act==1)?"open":"close")
return
}
# Waits for the end of the valve motion
for(tgt = ((act==1)?1000:0);;sleep(0.1)) {
# Get current and target valve positions
val = _vat_pm5_getpos(dev, "position")
# consider that the valve is still moving
if(fabs(tgt-val) <= 1) { break }
}
print "done"
# Update current motor positions
read_motors(0x06)
}'
#%UU% [controller]
#%MDESC%
# Open the valve
#
def vatopen '{
_vataction(1, "$*")
}'
#%UU% [controller]
#%MDESC%
# Close the valve
#
def vatclose '{
_vataction(2, "$*")
}'
#%IU%
#%MDESC%
# Called by spec after reading the config file
#
def vat_pm5_config(num,type,p1,p2,p3) '{
local silent
local mne
silent = 1
# p1 is the controller number
# p2 is the number of channels
if(type=="ctrl") {
# Get the serial line
dev = vat_pm5_ADDR
if(ser_par(dev, "responsive") == -1) {
_vat_pm5_err
print "wrong serial line, update ADDR field"
return ".error."
}
# Check that the controller is usable
if( _vat_pm5_query(dev, "v:", silent) == "") {
_vat_pm5_err
print "unusable controller"
return ".error."
}
# Switch on remote mode
if( _vat_pm5_query(dev, "U:01", silent) == "") {
_vat_pm5_err
print "unable to switch controller to remote mode"
return ".error."
}
# Remove any previous global resource
if(p1 == 0) {
local i
for(i in VAT_PM5_DEV) {
delete VAT_PM5_DEV[i]
}
}
# Keep a record of the serial line for direct access commands
VAT_PM5_DEV[p1] = dev
}
# p1 == unit
# p2 == module
# p3 == channel
if(type == "mot") {
# get the motor mnemonic string
mne=motor_mne(num)
# check limits
if(motor_par(num, "high_limit") != 1000) {
_vat_pm5_warn
print "motor \""mne"\": changing high limit to 1000"
motor_par(num, "high_limit", 1000)
}
# check limits
if(motor_par(num, "low_limit") != 0) {
_vat_pm5_warn
print "motor \""mne"\": changing low limit to 0"
motor_par(num, "low_limit", 0)
}
# remove any configured backlash
if(motor_par(num, "backlash") != 0) {
_vat_pm5_warn
print "motor \""mne"\": removing backlash"
motor_par(num, "backlash", 0)
}
# check motor type
if(p2 != 0) {
_vat_pm5_err
print "motor \""mne"\": invalid module value, must be 0"
return ".error."
}
if((p3 != 1) && (p3 != 2)) {
_vat_pm5_err
print "motor \""mne"\": invalid channel, must be 1(pos) or 2(press)"
return ".error."
}
if(p3 == 1) {
motor_par(num, "type", "position", "add")
} else {
motor_par(num, "type", "pressure", "add")
}
typ = motor_par(num, "type")
print "motor \""mne"\": moving VAT valve in \""typ"\""
# needed to emulate moving status
val = _vat_pm5_getpos(dev, typ)
motor_par(num, "target", val, "add")
}
# p1 == unit
# p2 == always 0
# p3 == channel
if(type == "cnt") {
# get the counter mnemonic string
mne=cnt_mne(num)
if(p3 == 1) {
counter_par(num, "type", "position", "add")
} else {
counter_par(num, "type", "curpress", "add")
}
typ = counter_par(num, "type")
print "counter \""mne"\": reading VAT valve \""typ"\""
}
}'
#%IU%
#%MDESC%
# Called by spec on motor operations
#
def vat_pm5_cmd(num,key,p1,p2) '{
local mne
local dev
local typ
local cmd
# Handle actions at controller level
if(num == "..") {
return
}
# try to guess if the action if for the motor or the counter
if((mne = motor_mne(num)) != "?") {
dev = motor_par(num, "address")
typ = motor_par(num, "type")
} else {
mne = cnt_mne(num)
dev = counter_par(num, "address")
typ = counter_par(num, "type")
}
# return the current pressure
if (key == "counts") {
return(_vat_pm5_getpos(dev, typ))
}
# return the current motor position in mm or deg
if (key == "position") {
local val
if((val = _vat_pm5_getpos(dev, typ)) == -1) { return ".error." }
return(val)
}
# start a motion (p1==abs pos, p2==rel pos, with pos in mm or deg)
# Note: the "start_one" is called for the macro counters also
# but with a null p2 value which is the relative motion
if((key == "start_one") && (p2!=0)) {
if(typ == "position") { cmd = "R:" } else { cmd = "S:" }
if((ans = _vat_pm5_query(dev, sprintf("%s%06d", cmd, p1), silent)) == "") {
_vat_pm5_err
print "unable to set valve position"
return ""
}
motor_par(num, "target", p1, "add")
}
# return the current motor status
if (key == "get_status") {
local val
local tgt
# get current and target valve positions
if((val = _vat_pm5_getpos(dev, typ)) == -1) { return(0) }
tgt = motor_par(num, "target")
# considere that the valve is still moving
if(fabs(tgt-val) > 1) { return(2) }
# not moving
return(0)
}
}'
#%IU%(dev, cmd, silent)
#%MDESC%
# Returns current valve position/pressure setppint/current pressure
# or -1 if error.
def _vat_pm5_getpos(dev, typ) '{
local cmd
local val
if(typ == "position") { cmd = "A:" }
if(typ == "pressure") { cmd = "W:" }
if(typ == "curpress") { cmd = "P:" }
if((ans = _vat_pm5_query(dev, cmd)) == "") {
_vat_pm5_err
print "unable to read valve position"
return -1
}
if(sscanf(substr(ans, 3), "%d", val) != 1) {
_vat_pm5_err
print "unable to understand valve position"
return -1
}
return(val)
}'
#%IU%(dev, cmd, silent)
#%MDESC%
# Send command to controler and returns its answer.
#
def _vat_pm5_query(dev, cmd, silent) '{
local use_spec
# Append the protocol terminators
if(substr(cmd,length(cmd)-1) != "\r\n") { cmd = cmd"\r\n" }
# Issue if several SPEC sessions are talking to the VAT controller
if(use_spec) {
# Send the command
ser_par(dev, "flush")
ser_put(dev, cmd)
# Wait for the answer
ans = ser_get(dev, "\n")
} else {
# Atomic send and read to support multi clients
ans = esrf_io(ser_par(dev, "device_id"), "DevSerWriteReadString", cmd)
}
# Handle timeout
if((ans == "") && !silent) {
_vat_pm5_err
print "timeout waiting for answer"
return ""
}
# Remove protocol terminators
if(substr(ans,length(ans)-1) == "\r\n") { ans=substr(ans,1,length(ans)-2) }
# Check for errors
if(substr(ans, 0, 2) == "E:") {
local err
err = substr(ans, 3)
_vat_pm5_err
if(err in VAT_PM5_ERR) {
print VAT_PM5_ERR[err]
} else {
print "unknown controller error"
}
return ""
}
# Returns the comamnd answer or the command echo
return ans
}'
#%IU%
#%MDESC%
# Cosmetics message
#
def _vat_pm5_err '{
tty_cntl("md")
printf("VAT PM5 ERROR: ")
tty_cntl("me")
}'
#%IU%
#%MDESC%
# Cosmetics message
#
def _vat_pm5_warn '{
tty_cntl("md")
printf("VAT PM5 WARNING: ")
tty_cntl("me")
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% MP BLISS (Original Jun/2015).
# %BR%$Revision: 1.2 $ / $Date: 2016/07/21 05:51:52 $
#%TOC%
|