#%TITLE% PMB.MAC
#%NAME%
#%B%PMB.MAC%B% - Pneumatic Mirror Bender set of macros
#%DESCRIPTION% The Pneumatic Mirror Bender is used to bend a mirror, using
#a proportional pressure control valve to set the radius of the curvature.
#%SETUP% The pressure switch (PS) is automatically open if the pressure in the
#system is less than 8bars - Relay (Wago 750-402). There is a pneumatic valve
#(PV1) for additional security - Relay (Wago 750-502). Three way valve (TW -
#DAC :Wago 750-554) or pressure controller (PACE5000) sets the pressure.
#We may read a pneumatic valve (PV2) which closes automatically if the
#pressure is more that 2.2 Bars - Relay (Wago 750-502). The gauge (PT - ADC:
#Wago 750-492) or pressure controller (PACE5000) reads the pressure. Security
#read channel, if existing, - ADC (Wago 750-492) confirms the threeway valve
#output.
#%EXAMPLE%
#To define the PMB macro motor, you must define it as follows:
#%B%MAC_MOT%B%, 100000 %B%steps/mm%B%, %B%limits%B% -0.1 to 2.1,
#%B%readback%B%%B%slop%B% 10000, %B%hardware%B%%B%read%B%%B%mode%B% AL+NQ.
#%PRE%
#Example of configuration:
#MOTORS DEVICE ADDR <>MODE NUM <>TYPE
#YES pmb 1 Macro Motors
#Example of the spec config file:
# If wago setup:
# MOTPAR:dactype = wago
# MOTPAR:dacdev = id29/wcid29d/wc
# MOTPAR:dacname = setp
# MOTPAR:dacstep = 0.25
# MOTPAR:adctype = wago
# MOTPAR:adcdev = id29/wcid29d/wc
# MOTPAR:adcname = readp
# MOTPAR:adcconv = 5
# MOTPAR:valtype = wago
# MOTPAR:valdev = id29/wcid29d/wc
# MOTPAR:valname = mvopen
# MOTPAR:pvtype = wago
# MOTPAR:pvdev = id29/wcid29d/wc
# MOTPAR:pvroot = mirv
#%B%*name%B% is the wago channel logical name (as in the resources),
#%B%*dev%B% is the appropriate device server name,
#%B%dacstep%B% is the ramping step for setting the pressure,
#%B%adcch%B% is the channel to be read on the ADC.
#%B%adcconv%B% is the factor to conver the ADC current to pressure (pres=curr/adcconv),
#%END%
#%IU% (mne,type,unit,module,chan)
#%MDESC% The command is executed when spec does (re)config, where %mne% could be .. (if %B%type%B% controller) or the motor number, if motor.
def pmb_config(mne,type,unit,module,chan) '{
global PMB_old
global PMB_DEBUG HDBdacsetval
if (PMB_DEBUG != 0) {
tty_cntl("md");printf ("pmb_config %s\n", type);tty_cntl("me")
}
if (type == "ctrl")
return
printf ("%s\n", mne)
if (motor_par(mne,"device_id") != "pmb")
return ".error."
if (pmb_getprops(mne) == -1)
return ".error."
}'
#%IU% (mot)
#%MDESC% Get and set different properties at the initialisation if the
#motor %B%mot%B%.
def pmb_getprops(mot) '{
local type dev nam ret dd lcmd
if (PMB_DEBUG != 0)
printf ("pmb_getprops %s\n", mot)
#set pressure (DAC)
type = motor_par(mot,"dactype")
dev = motor_par(mot,"dacdev")
if (type == "wago") {
nam = motor_par(mot,"dacname")
ret = esrf_io(dev,"DevName2Key",nam)
if (ret == -1)
return(-1)
motor_par(mot,"dackey",ret,"add")
motor_par(mot,"adca0",4,"add")
motor_par(mot,"adca1",8,"add")
} else if (type == "pace") {
split(dev, dd,":")
lcmd = sprintf ("ping %s -c 1", dd[0])
if (unix(lcmd) != 0) {
eprintf ("Controller %s not responding, disabling the motors %s\n", \
dd[0], mot)
return(-1)
} else {
motor_par(mot,"adca0",0,"add")
motor_par(mot,"adca1",1,"add")
}
}
if (PMB_DEBUG != 0) {
tty_cntl("md");printf ("pmb_getprops \n");tty_cntl("me")
}
#read pressure (ADC)
type = motor_par(mot,"adctype")
if (type == "wago") {
dev = motor_par(mot,"adcdev")
nam = motor_par(mot,"adcname")
ret = esrf_io(dev,"DevName2Key",nam)
if (ret == -1)
return(-1)
motor_par(mot,"adckey",ret,"add")
}
#open if compressed air (Relay)
if (type = motor_par(mot,"valtype")) {
if (type == "wago") {
dev = motor_par(mot,"valdev")
nam = motor_par(mot,"valname")
ret = esrf_io(dev,"DevName2Key",nam)
if (ret == -1)
return(-1)
motor_par(mot,"valkey",ret,"add")
}
}
#two security valves (Relay)
if (type = motor_par(mot,"pvtype")) {
if (type == "wago") {
dev = motor_par(mot,"pvdev")
nam = motor_par(mot,"pvroot")
for (i=1; i<=2; i++) {
ret = esrf_io (dev,"DevName2Key", sprintf("%s%d",nam,i))
if (ret == -1)
return(-1)
motor_par(mot,sprintf("pv%dkey",i),ret,"add")
}
}
}
return(0)
}'
#%IU% (mot, key, p1, p2)
#%MDESC%Executed by spec, when reading or moving (depends on the %B%key%B%)
#the motor %B%mot%B%
def pmb_cmd(mot, key, p1, p2) '{
global PMB_new[] PMB_old[]
if (PMB_DEBUG != 0) {
tty_cntl("md");printf ("pmb_cmd %s (%s)\n", mot,key);tty_cntl("me")
printf("p1=%f, old pmb_m value=%f", p1, PMB_old[mot])
}
if (key=="magnitude") {
PMB_new[mot]=PMB_old[mot]+p1
if (PMB_DEBUG)
printf("setting new motor pos. to be %f", PMB_new[mot])
} else if ((key == "start_one") || (key == "set_position")) {
if (PMB_DEBUG)
printf("motor should move to %f", PMB_new[mot])
if (_pmbset(mot, PMB_new[mot]) == -1)
return(-1)
PMB_old[mot] = PMB_new[mot]
} else if (key == "position") {
pos = _pmbread(mot)
return(pos)
}
}'
#%IU% (mot)
#%MDESC% Return the bender pressure - read the ADC and convert the value
#in pressure [Bar].
def _pmbread(mot) '{
local conv
conv = _adcread(mot)
if (motor_par(mot,"adctype") != "pace")
conv = 0.15625*(conv) - 0.625
PMB_old[mot] = conv
return(conv)
}'
#%IU% (mot)
#%MDESC% Return the reading on the ADC [mA] if wago, pressure [Bar] if PACE .
def _adcread(mot) '{
local type dev ch key
local adc_curr[] ret
type = motor_par(mot,"adctype")
dev = motor_par(mot, "adcdev")
if (type == "wago") {
key = motor_par(mot, "adckey")
ret = esrf_io(dev, "DevReadNoCachePhys", key, adc_cur)
if (ret != -1) {
ret = adc_cur[0]
if (PMB_DEBUG != 0) {
printf ("pmb_cmd: device %s - pos %f\n", dev, ret)
}
}
return(ret)
} else if (type == "pace") {
ret = _pace_readpres(dev)
return(ret)
} else {
#other types
ret = A[mot]
return(ret)
}
}'
#%IU% (mot, press)
#%MDESC% Set the bender to a pressure %B%pres%B% [Bar]. Do it in steps.
def _pmbset(mot,pres) '{
local cur_pres new_pres sec_step
local val a0 a1
if (PMB_DEBUG)
printf("------------>setting the pressure to %f\n", pres)
if ((pres < 0) || (pres > 2))
return (-1)
if (motor_par(mot,"valtype")) {
if (_valstate(mot) != 1)
return(-1)
}
cur_pres = _pmbread(mot)
if (cur_pres < 0)
return (-1)
if (cur_pres < 0)
cur_pres = 0
if (fabs(pres - cur_pres) < 0.01)
return (0)
sec_step = motor_par(mot,"dacstep")
a0 = motor_par(mot,"adca0")
a1 = motor_par(mot,"adca1")
if (pres > cur_pres) {
new_pres = pres - cur_pres
} else {
sec_step *= -1.
new_pres = cur_pres - pres
}
while (1) {
if (new_pres <= fabs(sec_step)) {
val = a0 + a1 * pres
if (_dacset(mot, val) < 0)
return (-1)
sleep(0.5)
if (_pmbread(mot) < 0)
return (-1)
return(0)
} else {
cur_pres += sec_step
val = a0 + a1 * pres
if (_dacset(mot, val) < 0)
return (-1)
sleep(3)
cur_pres = _pmbread(mot)
if (cur_pres < 0)
return(-1)
if (pres == cur_pres)
return(0)
if (pres > cur_pres)
new_pres = pres - cur_pres
else
new_pres = cur_pres - pres
}
sleep(0.5)
}
}'
#%IU% (mot, val)
#%MDESC% Send the DAC the %B%val%B% . In case of wago (3 way valve) the
#value is in mA, Bar in case of PACE.
def _dacset(mot,val) '{
global HDBdacsetval
local type dev ret vals
type = motor_par(mot,"dactype")
if (type == "wago") {
dev = motor_par(mot,"dacdev")
key = motor_par(mot, "dackey")
vals[0] = key
vals[1] = 0
vals[2] = val
ret = esrf_io(dev,"DevWritePhys", vals)
} else if (type == "pace") {
dev = motor_par(mot,"dacdev")
ret = _pace_setpres(dev,val)
} else {
#other types
ret = A[mot]
}
# set the new value to trigger a read in the hdb database
if (ret != -1)
ret = val
HDBdacsetval = val
if (PMB_DEBUG != 0) {
printf ("pmb_cmd: device %s - ret %g\n", dev, ret)
}
return(ret)
}'
#%IU% (mot)
#%MDESC% Return the state of the pressure swith (PS valve). Open PV1 and PV2.
def _valstate(mot) '{
local ret
ret = _valread(mot)
if (ret == 0) {
_pvopen(mot)
}
return(ret)
}'
#%IU% (mot)
#%MDESC% Read the state of the PS valve. Return 0 if open, 1 if closed,
#-1 if error.
def _valread(mot) '{
local type ret val
type = motor_par(mot,"valtype")
if (type == "wago") {
#temporarily change PS to PV1
#dev = motor_par(mot,"valdev")
#key = motor_par(mot, "valkey")
dev = motor_par(mot,"pvdev")
key = motor_par(mot, "pv1key")
ret = esrf_io(dev,"DevReadNoCachePhys", key,val)
if (ret != -1)
ret = val[0]
return(ret)
}
return(1)
}'
def _pvopen(mot) '{
local type ret dev i val
ret = 0
type = motor_par(mot,"pvtype")
if (type == "wago") {
val[1] = 0
val[2] = 1
dev = motor_par(mot,"pvdev")
valr = motor_par(mot,"pvroot")
for (i=1; i<=2; i++) {
val[0] = motor_par(mot, sprintf("pv%dkey",i))
if (esrf_io(dev,"DevWriteDigi", val) < 0)
ret = -1
}
return(ret)
}
return(0)
}'
def _pvclose(mot) '{
local type ret dev i val
ret = 0
type = motor_par(mot,"pvtype")
if (type == "wago") {
val[1] = 0
val[2] = 0
dev = motor_par(mot,"pvdev")
valr = motor_par(mot,"pvroot")
for (i=1; i<=2; i++) {
val[0] = motor_par(mot, sprintf("pv%dkey",i))
if (esrf_io(dev,"DevWriteDigi", val) < 0)
ret = -1
}
return(ret)
}
return(0)
}'
#%IU% (mot, pres)
#%MDESC% Set the pressure %B%pres%B%. Wait until value set. Return the value
#read from the PACE.
def _pace_setpres(dev,pres) '{
local rasw asw val
#turn controller on
sock_put(dev,":OUTP 1\r")
sock_put(dev, sprintf(":SOUR %f\r",pres))
sock_put(dev,":SENS:PRES?\r")
rasw = sock_get(dev,"\r")
split(rasw, asw)
val = asw[1]*1
while(fabs(val - pres) > 0.002) {
val = _pace_readpres(dev)
}
#turn controller off
##sock_put(dev,":OUTP 0\r")
return(val)
}'
#%IU% (mot)
#%MDESC% Return the pressure from the PACE.
def _pace_readpres(dev) '{
local rasw asw val
#read pressure
sock_put(dev,":SENS:PRES?\r")
rasw = sock_get(dev,"\r")
split(rasw, asw)
val = asw[1]*1
return(val)
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% A.Beteva/BLISS%BR%
#$Revision: 2.0 $, $Date: 2013/03/20 17:00:46 $
#%TOC%
#%END%
#%LOG%
#$Log: pmb_mm.mac,v $
#Revision 2.0 2013/03/20 17:00:46 beteva
#Removed the VME part. Added the control of the valves to be optional.
#Adde possibility to read/set the pressure only with a pressure controller.
#
#Revision 1.3 2011/11/02 14:28:58 beteva
#changes to cope with the new wago module
#changes to use the pace5000 pressure generator instead of a 3way valve
#
#Revision 1.2 2008/07/29 11:21:24 guijarro
#version with all changes from ID29 + fix in logic in valread macro
#
#Revision 1.1 2006/06/21 14:24:43 beteva
#Initial revision
#
|