#%TITLE% syrpump.mac
#%NAME%
# Control of Harvard apparatus Syringe Pump Pico Plus through serial line %BR%
# $Revision: 1.3 $
#%DESCRIPTION%
#%BR% Use %B%syrconfig%B% to configure syringe parameters
#%BR% Use %B%syrshow%B% to display current settings
#%BR% Use %B%syrstart%B%, %B%syrstop%B% to start/stop infuse
#%BR% A counter can be used to get the current accumulated volume infused.
# At each start command, this volume is reset to zero.
#%BR% To close remote connection and enable keyboard interaction, use %B%syrclose%B%.
#%SETUP%
#%BR% An ESRF device server for serial line has to be used (configuration of
# 2 stop bits), and configured in SPEC as raw:9600. Setup done using macro
# %B%syrsetup%B%
#%END%
#%IU%
def _syrpump_initarr '{
global SYRPUMP_UNIT[]
SYRPUMP_UNIT[0]["rate"]= "??/??"
SYRPUMP_UNIT[0]["cmd"]= ""
SYRPUMP_UNIT[0]["vol"]= "??"
SYRPUMP_UNIT[1]["rate"]= "ML/HR"
SYRPUMP_UNIT[1]["cmd"]= "MLH"
SYRPUMP_UNIT[1]["vol"]= "ML"
SYRPUMP_UNIT[2]["rate"]= "ML/MN"
SYRPUMP_UNIT[2]["cmd"]= "MLM"
SYRPUMP_UNIT[2]["vol"]= "ML"
SYRPUMP_UNIT[3]["rate"]= "UL/HR"
SYRPUMP_UNIT[3]["cmd"]= "ULH"
SYRPUMP_UNIT[3]["vol"]= "UL"
SYRPUMP_UNIT[4]["rate"]= "UL/MN"
SYRPUMP_UNIT[4]["cmd"]= "ULM"
SYRPUMP_UNIT[4]["vol"]= "UL"
SYRPUMP_UNIT[5]["rate"]= "NL/HR"
SYRPUMP_UNIT[5]["cmd"]= "NLH"
SYRPUMP_UNIT[5]["vol"]= "NL"
SYRPUMP_UNIT[6]["rate"]= "NL/MN"
SYRPUMP_UNIT[6]["cmd"]= "NLM"
SYRPUMP_UNIT[6]["vol"]= "NL"
SYRPUMP_UNIT[7]["rate"]= "PL/HR"
SYRPUMP_UNIT[7]["cmd"]= "PLH"
SYRPUMP_UNIT[7]["vol"]= "PL"
SYRPUMP_UNIT[8]["rate"]= "PL/MN"
SYRPUMP_UNIT[8]["cmd"]= "PLM"
SYRPUMP_UNIT[8]["vol"]= "PL"
global SYRPUMP_MODEL[]
SYRPUMP_MODEL[0]["name"]= "Pico Plus"
SYRPUMP_MODEL[0]["nrate"]= 8
SYRPUMP_MODEL[1]["name"]= "11 Plus"
SYRPUMP_MODEL[1]["nrate"]= 4
}'
#%UU% <sernum> <address> <volume_mne> <model_11>
#%MDESC%
# setup of the syringe pump:
# %BR%<sernum> : spec serial line unit. It has to be a device server as we need to configure 2 stop bits
# %BR%<address> : address of the pump as configured on the controller
# %BR%<volume_mne> : counter mnemonic to hold volume infused value
#
def syrsetup '{
global SYRPUMP[]
if (($#!=3)&&($#!=4)) {
eprint "$0 <sernum> <address> <volume_mne> [<model_11>]"
return
}
SYRPUMP["serial"]= int($1)
SYRPUMP["addr"]= int($2)
SYRPUMP["mne"]= cnt_num("$3")
SYRPUMP["model"]= int($4)
_syrpump_initarr
_syrpump_initserial
_syrpump_getpar
syron
setup_tail("syr")
}'
#%UU%
#%MDESC%
# Activate volume infused counter on each count
def syron '{
if (SYRPUMP["mne"]!=-1)
cdef("user_getcounts", "_syrpump_getcounts;\n", cnt_mne(SYRPUMP["mne"]), 0x02)
else
print "SYRPUMP WARNING> Invalid mnemonic for volume counter"
}'
#%UU%
#%MDESC%
# De-activate volume infused counter. resets to 0.
def syroff '{
if (SYRPUMP["mne"]!=-1) {
cdef("", "", cnt_mne(SYRPUMP["mne"]), "delete")
S[SYRPUMP["mne"]]= 0.
}
}'
#%IU%
#%MDESC%
# setup cleanup
def syrunsetup '{
syroff
unglobal SYRPUMP SYRPUMP_UNIT
}'
#%IU%
def _syrpump_getcounts '{
S[SYRPUMP["mne"]]= _syrpump_getvolume()
}'
#%IU%
def _syrpump_getvolume() '{
local ans
ans= _syrpump_io("VOL", -1, 1)
if (ans!=-1)
return (SYRPUMP["way"]*ans)
else
return (0.)
}'
#%IU%
def _syrpump_initserial '{
local dev serarr[]
dev= ser_par(SYRPUMP["serial"], "device_id")
esrf_io(dev, "tcp")
# baudrate
serarr[0] = 7
serarr[1] = 9600
# charlength
serarr[2] = 5
serarr[3] = 0
# parity
serarr[4] = 4
serarr[5] = 0
# stopbits
serarr[6] = 6
serarr[7] = 2
# newline
serarr[8] = 8
serarr[9] = 10
# timeout
serarr[10] = 3
serarr[11] = 64
esrf_io(dev, "DevSerSetLongParameter", serarr)
ser_par(SYRPUMP["serial"], "timeout", 0.1)
}'
#%IU%
def _syrpump_io(cmd, inval, outval) '{
local str ans npar pars[] nb
if (inval>0)
ser_put(SYRPUMP["serial"], sprintf("%02d%s%f\r", SYRPUMP["addr"], cmd, inval))
else
ser_put(SYRPUMP["serial"], sprintf("%02d%s\r", SYRPUMP["addr"], cmd))
for (nb=0; nb<10 && (length(str= ser_get(SYRPUMP["serial"]))==0); nb++)
printf(".")
for (nb=0; nb<10 && (length(ans= ser_get(SYRPUMP["serial"]))>0); nb++) {
printf(".")
str= str ans
}
printf("\r")
npar= split(str, pars, "\r\n")
# --- check unknown command, out-of-range
if (index(str, "?")>0) {
print "SYRPUMP ERROR> Unrecognized command", cmd
syrflush
return (-1)
}
if (index(str, "OOR")>0) {
print "SYRPUMP ERROR> Parameter out-of-range", cmd, inval
syrflush
return (-1)
}
# --- parse address, state
if (sscanf(pars[npar-1], "%d%[:<>*]c", addr, state)!=2) {
print "SYRPUMP> Cannot parse reply to", cmd, ":", str
syrflush
return (-1)
}
if (int(addr)!=SYRPUMP["addr"]) {
print "SYRPUMP> Oops, wrong reply address"
syrflush
return (-1)
}
if (state==":")
SYRPUMP["state"]= "Stopped"
else if (state==">") {
SYRPUMP["state"]= "Running forward"
SYRPUMP["way"]= 1
}
else if (state=="<") {
SYRPUMP["state"]= "Running backward"
SYRPUMP["way"]= -1
}
else if (state=="*")
SYRPUMP["state"]= "Stalled"
# --- parse value if needed
if (outval>0) {
return (pars[npar-2])
}
return (1)
}'
#%IU%
def _syrpump_getpar '{
local ans ii nrate
ans= _syrpump_io("DIA", -1, 1)
if (ans!=-1) SYRPUMP["diameter"]= ans + 0.
ans= _syrpump_io("RAT", -1, 1)
if (ans!=-1) SYRPUMP["rate"]= ans + 0.
ans= _syrpump_io("TAR", -1, 1)
if (ans!=-1) SYRPUMP["target"]= ans + 0.
ans= _syrpump_io("RNG", -1, 1)
SYRPUMP["unit"]= 0
nrate= SYRPUMP_MODEL[SYRPUMP["model"]]["nrate"]
for (ii=0; ii<=nrate; ii++) {
if (ans==SYRPUMP_UNIT[ii]["rate"])
SYRPUMP["unit"]= ii
}
}'
#%UU%
#%MDESC%
# Shows current syringe configuration
def syrshow '{
_syrpump_getpar
printf("\n< SYRPUMP CONFIG >\n")
printf("- Diameter : %g MM\n", SYRPUMP["diameter"])
printf("- Rate : %g %s\n", SYRPUMP["rate"], SYRPUMP_UNIT[SYRPUMP["unit"]]["rate"])
printf("\n< SYRPUMP STATUS >\n")
printf("- Status : %s\n", SYRPUMP["state"])
printf("- Target : %g %s\n", SYRPUMP["target"], SYRPUMP_UNIT[SYRPUMP["unit"]]["vol"])
printf("- Current Infused Volume : %g %s\n", _syrpump_getvolume(), SYRPUMP_UNIT[SYRPUMP["unit"]]["vol"])
printf("\n")
}'
#%UU%
#%MDESC%
# Display current syringwe pump model as cofnigured in syrsetup
def syrmodel '{
printf("\n< SYRPUMP MODEL > ");
tty_cntl("md")
printf("%s", SYRPUMP_MODEL[SYRPUMP["model"]]["name"])
tty_cntl("me")
print
}'
#%UU%
#%MDESC%
# Close remote connection to the controller and allow keyboard interaction
def syrclose '{
_syrpump_io("KEY", -1, 0)
}'
#%UU%
#%MDESC%
# Stops the pump
#
def syrstop '{
_syrpump_io("STP", -1, 0)
}'
#%UU% <target_volume>
#%MDESC%
# Start the pump up to <target_volume> infused. Units is as set in syrconfig.
#
def syrstart '{
local tgt
if ($#!=1) {
eprint "Usage: $0 <target_volume>"
return
}
tgt= $1
# warm if it is already moving
_syrpump_getpar
if (SYRPUMP["state"] != "Stopped") {
tty_cntl("md")
print "Warning: syringe is already running, please stop it before !!"
tty_cntl("me")
exit
}
_syrpump_io("CLV", -1, 0)
if (SYRPUMP["model"]==1)
_syrpump_io("MLT", fabs(tgt), 0)
else _syrpump_io("TGT", fabs(tgt), 0)
if (tgt*SYRPUMP["way"]<0.)
_syrpump_io("REV", -1, 0)
_syrpump_io("RUN", -1, 0)
}'
#%IU%
def syrflush '{
ser_par(SYRPUMP["serial"], "flush")
}'
#%IU%
def _syrpump_config(diameter, rate, unit) '{
if (_syrpump_set_unit(unit)) {
_syrpump_set_diameter(diameter)
_syrpump_set_rate(rate)
}
}'
#%UU% [<diameter> <rate> <unit>]
#%MDESC%
# Configure syringe pump parameters:
# %BR%<diameter> : syringe diameter in mm.
# %BR%<rate> : pump flow rate
# %BR%<unit> : rate unit
#
def syrconfig '{
local diam rate unit ii nrate
if ($#==3) {
diam= $1
rate= $2
unit= $3
}
else {
diam= getval("- Syringe diameter in mm.", SYRPUMP["diameter"])
print "- Rate units:"
nrate= SYRPUMP_MODEL[SYRPUMP["model"]]["nrate"]
for (ii=1; ii<=nrate; ii++) {
printf(" %d: %s", ii, SYRPUMP_UNIT[ii]["rate"])
if (!(ii%4)) printf("\n")
}
unit= getval(" Unit used", SYRPUMP_UNIT[SYRPUMP["unit"]]["rate"])
if (!_syrpump_set_unit(unit)) return
rate= getval(sprintf("- Flow rate in %s", SYRPUMP_UNIT[SYRPUMP["unit"]]["rate"]), SYRPUMP["rate"])
}
_syrpump_config(diam, rate, unit)
}'
#%IU%
def _syrpump_set_unit(value) '{
local ii val nrate
nrate= SYRPUMP_MODEL[SYRPUMP["model"]]["nrate"]
if (value!=value+0) {
for (ii=1; ii<=nrate; ii++)
if (SYRPUMP_UNIT[ii]["rate"]==value)
val= ii
}
else {
val= int(value)
}
if ((val<1)||(val>nrate)) {
print "SYRPUMP ERROR> Invalid unit", value
return (0)
}
SYRPUMP["unit"]= val
return (1)
}'
#%IU%
def _syrpump_set_rate(value) '{
if (_syrpump_io(SYRPUMP_UNIT[SYRPUMP["unit"]]["cmd"], value, 0)!=-1)
SYRPUMP["rate"]= value
}'
#%IU%
def _syrpump_set_diameter(value) '{
if (_syrpump_io("MMD", value, 0)!=-1)
SYRPUMP["diameter"]= value
}'
#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% E.Papillon
|