#%TITLE% NATT.MAC
#%NAME%
#%B%natt.mac%B% - move the new attenuators
#
#%CATEGORY% Positioning
#
#%DESCRIPTION%
# This macros control the standard ESRF filters. This attenuator consists of
# a motor controlled directly from SPEC, associated limit switches, and a
# home switch for every filter position. All the home switches are connected
# together to use the single home switch entry on the motor controller card.
# %BR%
# The macros attmv, attref, and attshow are the macros to operate these
# attenuators:
# %UL%
# %LI% attmv to move it from the command line
# %LI% attref to recover if ever the position of the motor is lost.
# %LI% attshow to use the macros with a simple text menu
# %LI% A graphical user interface which can be installed seperately
# %XUL%
# There is also a set of macros which help in setting up the attenuators:
# %UL%
# %LI% attdiag, attsetup, attsavesetup, attref, attlimits, attsetpos,
# attrefall, att_getxml, att_writexml.
# %XUL%
# These macros are used as follows:
# %UL%
# %LI% Call "attdiag <mne>" in order to have a complete and precise map
# (steps between filters, position and length of switches, backlash -
# direction and values) of the %B%mne%B% axis. The macro is not compulsory
# when configure an axis but is highly recommended to use if controlling
# the axis for the first time or in case of an abnormal behaviour. The
# execution might take 10-20 minutes.
# %LI% Call "attsetup [<filename>]" to define motor mnemonics, filter name,
# attenuators type and security, The filter name is a string with no
# spaces. With no parameters you will answer to questions. With the
# %B%filemane%B% (full path) parameter, all the setup information will be
# retrieved from it. The file should be by default in the
# /users/blissadm/local/spec/userconf directory.
# %LI% Call "attsavesetup <filename>" to save your current attenuator
# configuration so it can be used by attsetup. You should by default save
# the file to the /users/blissadm/local/spec/userconf directory
# (e.g. attsavesetup /users/blissadm/local/spec/userconf/att.save).
# %LI% Call "attref <mne> [calibration_step [sign]]" if you have lost the
# filter positions of the axis. The motor will move to a hardware limit
# switch and then try to find the first filter position with the help of
# the home switches. The precision of the search and the direction can be
# specified. If not the macro will use the default values which are
# positive direction and 0.004 mm precision.
# %LI% Call "attrefall <mne> [calibration_step [sign]]" if you have lost the
# filter positions of the axis and you have unequal distances between the
# fiters. The motor will move to a hardware limit switch and then try to
# find all the filter position with the help of the home switches. At the
# end the motor is moved to the second filter. The precision of the
# search and the direction can be specified. If not the macro will use
# the dafault values which are positive direction and 0.004 mm precision.
# %LI% Call "attlimits <mne>" to get the positions of hardware limits and set
# them as software limits. Any subsequent move of the axis will make the
# software move the motor an ATT_DELTAMV mm before the limits, only if the
# difference between the position asked and the corrected position is
# below a certain value (ATT_DELTAMAX). Otherwise, the normal limits
# reached message will appear.
# %LI% Use the standard SPEC set command - "set <mne> pos" when there is an
# offset between the home switches and the desired beam position. You can
# simply move the center of a filter in the beam and set this position to
# your new filter number. For example, if your second filter is currently
# in the center of thebeam, just type "set att1 2". This will result in
# an offset between your dial and user position. All other filters will
# shift automatically too. If you need to shift individual filter position
# (normally should not be necessary if everything works fine!), use the
# attsetpos macro for every filter position.
# %LI% Use "attmv <mne> pos .. <mne> pos" to move the attenuators to the filter
# pos. The advantage over moving the motor with the normal mv command is
# a check if the motor really moved and if the home switches are active.
# You can also use the filter name (i.e. 0.18mm_Al) as a position.
# %LI% Use "attshow" to see position of any axis and to move them
# %LI% Use "_attmv(nb, mne[], pos[])" if you want to move your axis from a
# macro
# nb: Number of axis to move
# mne[]: Associative array containing the mnemonic of axis to move
# pos[]: Associative array containing the position where to move axis
# %LI% Use "attsetpos <mne> <filter name> <pos>" to set position of a
# particular filter. There is a value associated with every filter
# name.This position is set by default to the position of the filter
# (e.g. 1 2 3 4 5 or 6). If after a scan, one filter position is not
# exactly 1, 2..., you can use this macro to set a new position for
# this filter. Afterwards, using filter name in attmv will move the
# axis to the new position. Filter values are used in attshow to move
# axis and saved with attsavesetup.
#
# %XUL%
#
#%END%
#%UU%
#%MDESC% Initialise the table of parameters for the existing attenuator
#types.
def _attinittable '{
global ATTTABLE ATTNBTABLE
ATTNBTABLE = 11
ATTTABLE[1]["nbfilt"] = 4
ATTTABLE[1]["step_size"] = 10560
ATTTABLE[1]["filter_distance_mm"] = 33
ATTTABLE[1]["name"] = "Oxford 4 filter positions"
ATTTABLE[1]["mne"] = "oxford4"
ATTTABLE[2]["nbfilt"] = 5
ATTTABLE[2]["step_size"] = 7840
ATTTABLE[2]["filter_distance_mm"] = 24.5
ATTTABLE[2]["name"] = "Oxford 5 filter positions"
ATTTABLE[2]["mne"] = "oxford5"
ATTTABLE[3]["nbfilt"] = 4
ATTTABLE[3]["step_size"] = 10560
ATTTABLE[3]["filter_distance_mm"] = 33
ATTTABLE[3]["name"] = "Rial 4 filter positions"
ATTTABLE[3]["mne"] = "rial4"
ATTTABLE[4]["nbfilt"] = 5
ATTTABLE[4]["step_size"] = 12250
ATTTABLE[4]["filter_distance_mm"] = 24.5
ATTTABLE[4]["name"] = "Rial 5 filter positions"
ATTTABLE[4]["mne"] = "rial5"
ATTTABLE[5]["nbfilt"] = 4
ATTTABLE[5]["step_size"] = 15000
ATTTABLE[5]["filter_distance_mm"] = 30
ATTTABLE[5]["name"] = "Rial 4 filter positions 30 mm"
ATTTABLE[5]["mne"] = "rial4_30"
ATTTABLE[6]["nbfilt"] = 4
ATTTABLE[6]["step_size"] = 11200
ATTTABLE[6]["filter_distance_mm"] = 35
ATTTABLE[6]["name"] = "Oxford 4 filter positions 35 mm"
ATTTABLE[6]["mne"] = "oxford4_35"
ATTTABLE[7]["nbfilt"] = 4
ATTTABLE[7]["step_size"] = 9600
ATTTABLE[7]["filter_distance_mm"] = 30
ATTTABLE[7]["name"] = "Spline filter positions 30 mm"
ATTTABLE[7]["mne"] = "spline_30"
ATTTABLE[8]["nbfilt"] = 4
ATTTABLE[8]["step_size"] = 16500
ATTTABLE[8]["filter_distance_mm"] = 30
ATTTABLE[8]["name"] = "ID14 attenuators"
ATTTABLE[8]["mne"] = "id14att"
ATTTABLE[9]["nbfilt"] = 4
ATTTABLE[9]["step_size"] = -1
ATTTABLE[9]["filter_distance_mm"] = -1
ATTTABLE[9]["name"] = "No switch filters"
ATTTABLE[9]["mne"] = "NoSwitch"
ATTTABLE[10]["nbfilt"] = 4
ATTTABLE[10]["step_size"] = 4000*35
ATTTABLE[10]["filter_distance_mm"] = 35
ATTTABLE[10]["name"] = "Oxford 4 filters Icepap attenuator 35 mm"
ATTTABLE[10]["mne"] = "id24att"
ATTTABLE[11]["nbfilt"] = 5
ATTTABLE[11]["step_size"] = 2500*24.5
ATTTABLE[11]["filter_distance_mm"] = 24.5
ATTTABLE[11]["name"] = "Rial 5 filter Icepap attenuator 24.5 mm"
ATTTABLE[11]["mne"] = "rial5ice"
}'
#%UU% [filename]
#%MDESC% Initialise the attenuator motor, answering questions or get the
#information from %B%filename%B%.
def attsetup '{
global ATTNUM[]
global ATTTYPE[]
global ATTSEC[]
global ATTFILTNAME[]
global ATTFILTPOS[]
global _CALIB_STEP _ATTMOT ATTNB ATT_DELTA ATTFIRSTTIME
global ATT_LOCKED_MSG
global ATT_DELTAMV ATT_DELTAMAX
global ATT_MOVED_ON ATT_MOVED_NB ATT_MOVED_MOT[] ATT_MOVED_POS[]
global ATT_HO[]
global ATT_CHECK
global ATT_MENU_TIMEOUT
local i s1 s2 str fname found
ATT_MENU_TIMEOUT = 0
ATT_MOVED_ON = 0
ATT_DELTAMV = 0.001
ATT_DELTAMAX = 0.03
ATT_DELTA = 0.1
_attinittable
if ($# == 0) {
# Axis Menmonic
_ATTMOT = getval("Attenuator motor mnemonic: ",_ATTMOT)
_check_mne(_ATTMOT)
# Axis Type
printf(" Attenuator types:\n")
for (i=1; i<= ATTNBTABLE; i++)
printf("%8d: %s (including empty filter)\n", i, ATTTABLE[i]["name"])
ATTTYPE[_ATTMOT] = getval("Attenuator type", ATTTYPE[_ATTMOT])
nbfilt = ATTTABLE[ATTTYPE[_ATTMOT]]["nbfilt"]
# Axis Security
str = sprintf("Security filter number [1-%d] :", nbfilt)
ATTSEC[_ATTMOT] = getval(str, ATTSEC[_ATTMOT])
# Filter Names & Pos
for (i=1;i<=nbfilt;i++) {
str = sprintf("Name for filter #%d :", i)
ATTFILTNAME[_ATTMOT][i] = getval(str, ATTFILTNAME[_ATTMOT][i])
if (ATTFILTNAME[_ATTMOT][i] == "")
ATTFILTNAME[_ATTMOT][i] = sprintf("filt%d", i)
if (ATTTYPE[_ATTMOT] != 9) {
ATTFILTPOS[_ATTMOT][i] = i
} else {
aux_str = sprintf("Filter \"%s\" position", ATTFILTNAME[_ATTMOT][i])
ATTFILTPOS[_ATTMOT][i] = getval(aux_str, ATTFILTPOS[_ATTMOT][i])+0
}
}
for (i=0,found=0;i<ATTNB;i++) {
if (ATTNUM[i] == _ATTMOT) {
found = 1
break
}
}
if (!found)
ATTNUM[ATTNB++] = _ATTMOT
if (ATT_CHECK) {
if (ATTTABLE[ATTTYPE[_ATTMOT]]["step_size"] != -1) {
if ((s1 = ATTTABLE[ATTTYPE[_ATTMOT]]["step_size"]) != \
(s2 = fabs(motor_par(motor_num(_ATTMOT),"step_size"))))
printf ("Warning: motor %s should have %d step/mm in config, but has %d\n",\
_ATTMOT, s1, s2)
}
}
} else if ($# >= 1) {
fn = "$1"
printf("***** Getting attenuator configuration from %s *****\n", fn)
if (open(fn) == -1) {
printf("Cannot open file \"%s\" for attenuator(s) setup, exit\n", fn)
exit
}
ATTFIRSTTIME = 1
for (;;) {
# look for a mnemonic
if ((str=_att_find_key(fn, "mne")) == "error") {
break
}
if (motor_mne(motor_num(str)) == str) {
_ATTMOT = str
} else {
printf("motor \"%s\" not configure, exit\n", str)
exit
}
printf("*** configure attenuator %d : \"%s\" \n", ATTNB+1, _ATTMOT)
# looking for axis type
if ((str=_att_find_key(fn, "type")) == "error") {
printf("configuration error, exit\n")
exit
}
if ((str!="1") && (str!="2") && (str!="3") && \
(str!="4") && (str!="5") && (str!="6") && \
(str!="7") && (str!="8") && (str!="9"))
str = 1
else
str = str + 0
ATTTYPE[_ATTMOT] = str
# looking for axis security
if ((str=_att_find_key(fn, "security")) == "error") {
printf("configuration error, exit\n")
exit
}
ATTSEC[_ATTMOT] = str
nbfilt = ATTTABLE[ATTTYPE[_ATTMOT]]["nbfilt"]
for (i=1;i<=nbfilt;i++) {
# filter name
if ((str=_att_find_key(fn, "name")) == "error") {
printf("configuration error, exit\n")
exit
}
# filter position
ATTFILTNAME[_ATTMOT][i] = str
if ((str=_att_find_key(fn, "pos")) == "error") {
printf("configuration error, exit\n")
exit
}
ATTFILTPOS[_ATTMOT][i] = str + 0
}
for (i=0,found=0;i<ATTNB;i++)
if (ATTNUM[i] == _ATTMOT) {
found = 1
break
}
if (!found)
ATTNUM[ATTNB++] = _ATTMOT
}
close(fn)
ATT_HO[_ATTMOT]["filename"] = "$2"
ATT_HO[_ATTMOT]["root"] = "$3"
ATT_HO[_ATTMOT]["name"] = "$4"
ATT_HO[_ATTMOT]["offset"] = "$5"
} else {
printf("Usage : attsetup <no parameter> ==> one axis configuration\n")
printf(" attsetup [filename] ==> axis setup from file\n")
}
if (whatis("user_att_locked") == 0)
eval("def user_att_locked\'{ }\'")
}'
#%UU% [filename]
#%MDESC% Write current attenuator configuration (all axis) in a %B%file%B%.
def attsavesetup '{
local i fn nbfilt j
if ($# != 1) {
printf ("Usage: attsavesetup [filename]\n")
exit
}
fn = "$1"
if (!unix(sprintf("test -w %s", fn))) {
str = sprintf("File \"%s\" allready exists, overwrite", fn)
if (yesno(str,0)) {
unix(sprintf("/bin/rm %s", fn))
sleep(1)
} else {
exit
}
}
open(fn)
for (i=0;i<ATTNB;i++) {
fprintf(fn, "mne = %s\n", ATTNUM[i])
fprintf(fn, "type = %d\n", ATTTYPE[ATTNUM[i]])
fprintf(fn, "security = %d\n", ATTSEC[ATTNUM[i]])
nbfilt = ATTTABLE[ATTTYPE[ATTNUM[i]]]["nbfilt"]
for (j=1;j<=nbfilt;j++) {
fprintf(fn, " filter %d\n", j)
fprintf(fn, " name = %s\n", ATTFILTNAME[ATTNUM[i]][j])
fprintf(fn, " pos = %g\n", ATTFILTPOS[ATTNUM[i]][j])
}
fprintf(fn, "\n")
}
close(fn)
}'
#%IU% (filename, key)
#%MDESC% Find a keyword %B%key%B% in the attenuator config file %B%filename%B%.
def _att_find_key(fn, key) '{
local str n
mytab[0] = 0
if (ATTFIRSTTIME) {
str = getline(fn, 0)
ATTFIRSTTIME = 0
} else {
str = getline(fn)
}
for (;(str!=-1) && (index(str,key)==0);str=getline(fn)) ;
if (str != -1) {
n = split(str, mytab)
str = mytab[n-1]
while (index(str, "\n") != 0) {
str = substr(str, 1, index(str, "\n")-1)
}
} else {
str = "error"
}
return(str)
}'
#%UU% <motor_mnemonic [calibration_step [sign]]>
#%MDESC% Find the "second filter". Set it as reference position (2) and step
#on it. The motor will move to a hardware limit switch and then try to find
#the second filter position with the help of the home switches. The direction
#of the movement %B%sign%B% is defined as 1 (from negative limit in positive
#direction) or -1 (positive limit in negative direction). The precision for
#the home switch search %B%calibration_step%B% [mm] could be defined - default
#value is 0.004 mm.
def attref '{
local mnum nbfilt
global _CALIB_STEP _SIGN _ATTDEBUG
if (_att_locked()) {
printf("%s\n", ATT_LOCKED_MSG)
exit
}
if ($# < 1) {
printf ("Usage: attref motor_mnemonic [ calib_step [direction]]\n")
_ATTMOT = getval("Attenuator motor mnemonic: ",_ATTMOT)
#_CALIB_STEP = fabs(getval("Attenuator calibration step [mm or step]: ", _CALIB_STEP))
#_SIGN = ("Direction to scan - 1(positive)/-1(negative)", _SIGN)
mnum =_check_mne(_ATTMOT)
} else {
_check0 "$1"
_ATTMOT ="$1"
mnum = $1
_CALIB_STEP = fabs($2)
_SIGN = $3
}
if (!_CALIB_STEP)
_CALIB_STEP = 0.004
if (!_SIGN)
_SIGN = 1
if (ATTTABLE[ATTTYPE[_ATTMOT]]["filter_distance_mm"] == -1) {
printf("Axis without switches! Cannot get reference, exit.\n")
exit
}
if (ATTTYPE[_ATTMOT] == 0 || \
(nbfilt = ATTTABLE[ATTTYPE[_ATTMOT]]["nbfilt"]) == 0) {
printf("Please, run attsetup first, exit\n")
exit
}
printf("**** Searching reference position of %s ****\n", _ATTMOT)
_attref (mnum)
}'
#%UU% <motor_mnemonic>
#%MDESC% Find both limit switches position and set them as software limits for
#the motor%BR%
#%B%attref%B% has to be called already. Otherwise the hardware limit position
#will not be correct.
def attlimits '{
local mnum tomm neg_limit pos_limit
if (_att_locked()) {
printf("%s\n", ATT_LOCKED_MSG)
exit
}
if ($# != 1) {
printf("Usage: attlimits att_mnemonic\n")
exit
}
mnum = $1
tomm = motor_par(mnum,"step_size")
printf("*** Moving to negative limit\n")
neg_limit =_att_gotolim(mnum, -1)
printf( "*** Moving to positive limit\n")
pos_limit = _att_gotolim(mnum, +1)
printf("*** Harware Limits found at [%g %g] (%d steps, %d steps)\n", \
neg_limit, pos_limit, int(neg_limit * tomm), int(pos_limit * tomm))
printf("*** Setting previous values as software limits\n")
set_lim(mnum, dial(mnum, neg_limit), dial(mnum, pos_limit))
}'
#%IU% (mnum)
#%MDESC% Internal function to find the "zero reference filter". The algorithm
#is based on the fact that the first home switch is passed when we move
#0.5 filter distances (i.e.33mm/2 = 16mm) from the limit. The %B%mnum%B% is
#the axis ordinal number in the motors list.
def _attref (mnum)'{
local a0 a1 dist step mid[] dist_mm
global ATTFILTPARS[]
a0 = _att_gotolim(mnum,-1* _SIGN)
printf ("Limit switch reacheat at position %.2f\n", a0)
step = _CALIB_STEP
sleep(.1)
dist_mm = ATTTABLE[ATTTYPE[motor_mne(mnum)]]["filter_distance_mm"]
#check if home switch active
if (_attswitchf (mnum, 0, 99) == 0) {
printf ("\t - both limit and home switches active\n")
a0 = A[mnum]
} else {
printf("\t - move until the home switch of the first filter reached...\n")
a0 = _attswitchf (mnum,step,4)
}
printf ("Home switch reached at position %.2f\n", a0)
printf("\t - move until the home switch of the first filter left...\n")
a1 = _attswitchf (mnum,step,0)
printf ("Home switch left at position %.2f\n", a1)
mid[0] = a1 - _SIGN * fabs(a1-a0)/2
printf ("Home switch size %.2f mm\n", fabs((a1-a0) * dist_mm))
printf ("\t - go to a position between first and second filter...\n")
waitmove ; get_angles
A[mnum] += 0.5 * _SIGN
move_em
_show_waitf()
printf("\t - move until the home switch of the second filter reached...\n")
a0 = _attswitchf (mnum,step,4)
printf ("Home switch reached at position %.2f\n", a0)
printf("\t - move until the home switch of the second filter left...\n")
a1 = _attswitchf (mnum,step,0)
printf ("Home switch left at position %.2f\n", a0)
mid[1] = a1 - _SIGN * fabs(a1-a0)/2
printf ("Home switch size %.2f mm\n", fabs(a1-a0))
dist = fabs(mid[1] - mid[0])
printf ("\t - Filter distance: %.2f mm. Filter (switch) size: %.2f mm\n", \
dist*dist_mm, fabs((a1-a0)*dist_mm))
printf ("Moving to the centre of the second filter (%.2f)\n", mid[1])
A[mnum] = mid[1]
move_all; waitmove
chg_dial(mnum,2)
ATTFILTPOS[motor_mne(mnum)][2] = 2
ATTFILTPOS[motor_mne(mnum)][1] = 2 - (dist*_SIGN)
ATTFILTPARS[motor_mne(mnum)]["filtpos2"] = 2
ATTFILTPARS[motor_mne(mnum)]["filtpos1"] = 2 - (dist*_SIGN)
}'
#%IU% (mnum, sign)
#%MDESC% Go to positive or negative limit (positive means same sign as the
#step_size (positive motor movement). Show some animation during the move.
#Return the current motor position.
def _att_gotolim(mnum, sign) '{
local stepsign way
stepsign = fabs(motor_par(mnum, "step_size")) / motor_par(mnum, "step_size")
if (stepsign * sign < 0) {
way = "negative"
chg_dial(mnum, "lim-")
} else {
way = "positive"
chg_dial(mnum, "lim+")
}
printf ("\t- go to %s limit, please wait...\n", way)
_show_waitf()
return(A[mnum])
}'
#%IU% ()
#%MDESC% Draw a bar while action goin on
def _show_waitf() '{
local m
printf(" ")
while(wait(0x21)){
printf("\b%s", substr("-\\|/", (m=++m%4)+1, 1))
sleep(.05)
}
printf("\b")
getangles
}'
#%IU% (motor_mnemonic, motor_steps, parameter)
#%MDESC% If par=99, return the home switch status (0-active, 4-nonactive).
#Otherwise check if home switch signal is active (par=0) or not (par=4) and
#move the motor untill the desired status reached. Retunt the current motor
#position.
def _attswitchf (mnum, mstep, par) '{
local chnum device pos
device = motor_par(mnum,"device_id")
if (device == "icepap") {
pos = _attswitchicepap(mnum, mstep, par)
} else {
pos = _attswitchmaxe(mnum, mstep, par)
}
return(pos)
}'
#%IU% (motor_number, sign)
#%MDESC% Return the limit switch status (0-nonactive, 1=-active). Check low or
#high limit switch according to the sign.
#position.
def _attlimitswitchf (mnum, sign) '{
local device ret
ret = 0
device = motor_par(mnum,"device_id")
if (device == "icepap") {
if (sign > 0) {
ret = motor_par(mnum,"high_lim_set")
} else {
ret = motor_par(mnum,"low_lim_set")
}
} else {
local chnum
chnum = motor_par(mnum,"channel")
ret = esrf_io(device, "DevReadSwitches", chnum)
if (ret == -1) {
eprintf("Cannot read limit switche status, exiting...\n")
exit
} else {
if (sign > 0) {
if (ret == 2)
return(1)
else
return(0)
} else {
if (ret == 1)
return(1)
else
return(0)
}
}
}
if (ret != 0)
ret = 1
return(ret)
}'
#%IU% (motor_number, motor_steps, parameter)
#%MDESC% If par=99, return the home switch status (0-active, 4-nonactive).
#Otherwise check if home switch signal is active (par=0) or not (par=4) and
#move the motor %B%motor_steps%B% untill the desired status reached.
#Retunt the current motor position.
def _attswitchicepap(mnum, mstep, par) '{
local stat ret cmd sign
if (par == 99) {
stat = motor_par(mnum,"home_active")
stat==0?(ret = 4 ):(ret = 0)
return(ret)
}
sign = 1
if (motor_par(mnum, "step_size") < 0)
sign = -1
(_SIGN*sign > 0) ? (cmd = sprintf ("motor_par(%d,\"high_lim_set\")",mnum)):\
(cmd = sprintf ("motor_par(%d,\"low_lim_set\")",mnum))
if (par == 0) {
while(motor_par(mnum,"home_active") != 0) {
stat = eval(cmd)
if (stat == 0) {
A[mnum] += mstep * _SIGN
move_all
_show_waitf()
} else {
return A[mnum]
}
}
} else {
while(motor_par(mnum,"home_active") == 0) {
stat = eval(cmd)
if (stat == 0) {
A[mnum] += mstep * _SIGN
move_all
_show_waitf()
} else {
return A[mnum]
}
}
}
return A[mnum]
}'
#%IU% (motor_number, motor_steps, parameter)
#%MDESC% If par=99, return the home switch status (0-active, 4-nonactive).
#Otherwise check if home switch signal is active (par=0) or not (par=4) and
#move the motor %B%motor_steps%B% untill the desired status reached.
#Retunt the current motor position.
def _attswitchmaxe(mnum, mstep, par)'{
local chnum device stat
device = motor_par(mnum,"device_id")
chnum = motor_par(mnum,"channel")
if (par == 99) {
return(esrf_io (device,"DevReadHardStatus", chnum) & 0x04)
}
while ((esrf_io (device,"DevReadHardStatus", chnum) & 0x04) == par) {
stat = _attlimitswitchf (mnum, _SIGN)
if (stat == 1)
break
getangles
A[mnum] += mstep * _SIGN
move_all
_show_waitf()
}
return A[mnum]
}'
#%IU% (motor_mnemonic)
#%MDESC% Check if the motor exists in the configuration.
def _check_mne (motor)'{
local mnum
mnum = motor_num(motor)
if (motor_mne(mnum) != motor) {
print "Invalid motor mnemonic: "motor
exit
}
return(mnum)
}'
#%IU% (mnum)
#%MDESC% Return the home switch signal value - activ (0) or not (4).
def _att_checkhomef (mnum) '{
return(_attswitchf(mnum, 0, 99))
}'
#%UU% [<motor_mnemonic>] [<filter position>/<filter name>] .....
#%MDESC% Move the axis <motor_mnemonic> to the given position <filter_number>
#Move to an intermediate position, check the switch, move to the final
#position and check again that the switch is on.
def attmv '{
local tmot[] tpos[]
local nbfilt i j mot_nb par_nb findmot findfilt
if (_att_locked()) {
printf("%s\n", ATT_LOCKED_MSG)
exit
}
npar = $#
if ((npar == 0) && (npar/2.0 != int(npar/2.0))) {
p "Usage: attmv motor_mnemonic filter_number [motor_mnemonic filter_number]"
p " OR"
p " attmv motor_mnemonic filter_name [motor_mnemonic filter_name]"
exit
}
par_nb = split ("$*",inp)
# first construct 2 associative array containing for the first one the
# mnemonic of the axis to move and for the second, the position where to move
for (i=0, mot_nb=0; i<par_nb ; i=i+2) {
if (motor_mne(motor_num(inp[i])) != inp[i]) {
printf("Motor \"%s\" does not exist\n", inp[i])
} else {
# inp[i] is a real motor, check if it is an attenuator
for (findmot=0,j=0;j<ATTNB;j++)
if (ATTNUM[j] == inp[i])
findmot = 1
if (findmot == 0) {
printf("Motor \"%s\" is not configured as an attenuator axis\n", \
inp[i])
} else {
tmot[mot_nb] = motor_num(inp[i])
# check if this a position or a filter name
nbfilt = ATTTABLE[ATTTYPE[inp[i]]]["nbfilt"]
for (j=1,findfilt=0;j<=nbfilt;j++)
if (ATTFILTNAME[inp[i]][j] == inp[i+1])
findfilt = j
if (findfilt == 0)
tpos[mot_nb++] = inp[i+1] + 0
else
tpos[mot_nb++] = ATTFILTPOS[inp[i]][findfilt]
}
}
}
_attmv(mot_nb, tmot, tpos)
}'
cdef("user_att_endmove")
#%IU% (<nb. motor>, <motor num array>, <motor pos array>)
#%MDESC%Function to test the limits, correct the position, send to
#intermediate and then to final postion the motors specified in the second
#parameter (an associative array). The first parameter is the number of motors
#to move. The third parameter is an associative array containing the final
#positions for the motors to move.
def _attmv(n, tmot, tpos) '{
local i dpos limpos limneg rpos nbmot backlash
local new_pos[] new_mot[] init_pos[] mid_pos[]
ATT_MOVED_ON = 1
ATT_MOVED_NB = n
ATT_MOVED_MOT = tmot
ATT_MOVED_POS = tpos
cdef("cleanup_once", "ATT_MOVED_ON = 0\n", "attmove")
if (_att_locked()) {
printf("%s\n", ATT_LOCKED_MSG)
exit
}
waitmove ; get_angles
# check limits
p "*** check axis limits"
for (i=0,nbmot=0 ; i<n ; i++) {
backlash = motor_par(tmot[i], "backlash")
dpos = dial(tmot[i], tpos[i])
toadd = 0
if (((backlash < 0) && (dial(tmot[i], A[tmot[i]]) > dpos)) || \
((backlash > 0) && (dial(tmot[i], A[tmot[i]]) < dpos)))
toadd = backlash / motor_par(tmot[i], "step_size")
dpos += toadd
limpos = get_lim(tmot[i], 1)
limneg = get_lim(tmot[i], -1)
if ((dpos < limneg) || (dpos > limpos) ) {
if (dpos < limneg)
rpos = user(tmot[i], get_lim(tmot[i], -1)) + ATT_DELTAMV - toadd
else
rpos = user(tmot[i], get_lim(tmot[i], 1)) - ATT_DELTAMV - toadd
if (fabs(rpos-tpos[i]) > ATT_DELTAMAX) {
printf("\"%s\": %g is outside soft. lim. and cannot be corrected\n",\
motor_mne(tmot[i]), tpos[i])
} else {
printf("\"%s\": %g is outside soft. lim., corrected in %g\n", \
motor_mne(tmot[i]), tpos[i], rpos)
new_mot[nbmot] = tmot[i]
new_pos[nbmot++] = rpos
}
} else {
new_mot[nbmot] = tmot[i]
new_pos[nbmot++] = tpos[i]
}
}
if (nbmot < 1)
exit
# calculate sign
for (i=0; i<nbmot; i++) {
init_pos[i] = A[new_mot[i]]
# calulate if we will move up (mv_sign == +1) or down (mv_sign = -1)
if (new_pos[i] == init_pos[i])
mv_sign[i] = 0
else if (new_pos[i] > init_pos[i])
mv_sign[i] = +1
else
mv_sign[i] = -1
}
# calculate intermediate position
for (aux_mot2move=0,i=0; i<nbmot; i++) {
if (ATTTABLE[ATTTYPE[motor_mne(new_mot[i])]]["step_size"] != -1) {
aux_mot2move += 1
nbfilt = ATTTABLE[ATTTYPE[motor_mne(new_mot[i])]]["nbfilt"]
# move to an intermed. position to see switch change (which is on the
# way to the filter but only if between the first and the last filter)
if (mv_sign[i]) {
new_filt[i] = int(dial(new_mot[i], new_pos[i])+0.5)
if (new_filt[i] <= 1) {
midpos[i] = user(new_mot[i], 1.5)
} else if (new_filt[i] >= nbfilt) {
midpos[i] = user(new_mot[i], nbfilt - 0.5)
} else {
midpos[i] = user(new_mot[i], new_pos[i] - mv_sign[i] * 0.5)
}
A[new_mot[i]] = midpos[i]
}
}
}
if (aux_mot2move != 0){
# move all the axis to intermediate position
p "*** Move axis to intermediate position"
move_em
waitmove ; get_angles
}
for (i=0; i<nbmot ; i++) {
if (mv_sign[i]) {
if (ATTTABLE[ATTTYPE[motor_mne(new_mot[i])]]["step_size"] != -1)
if (_att_checkhomef(new_mot[i]) == 0) {
p "WARNING: " motor_mne(new_mot[i]) " position switch not changing, check the hardware"
}
# set final position
A[new_mot[i]] = new_pos[i]
}
}
# move all the axis to final position
p "*** Move axis to final position"
move_em
waitmove; get_angles
for (i=0; i<nbmot; i++)
if (mv_sign[i])
if (ATTTABLE[ATTTYPE[motor_mne(new_mot[i])]]["step_size"] != -1)
if (_att_checkhomef(new_mot[i]) != 0)
p "WARNING: " motor_mne(new_mot[i])" position switch not reached"
user_att_endmove
ATT_MOVED_ON = 0
}'
#%UU% <axis mnemonic> <filter num> <pos>
#%MDESC% Set the position for filter #n of attenuator axis.
def attsetpos '{
local motmne filtname filtpos nbfilt i findfilt
if ($# != 3) {
printf ("Usage: attsetpos mne filter_name position\n")
exit
}
motmne ="$1"
filtname = "$2"
filtpos = $3
if (motmne in ATTTYPE) {
nbfilt = ATTTABLE[ATTTYPE[motmne]]["nbfilt"]
for (i=1,findfilt=0;i<=nbfilt;i++)
if (ATTFILTNAME[motmne][i] == filtname)
findfilt = i
if (findfilt != 0) {
ATTFILTPOS[motmne][findfilt] = filtpos
} else {
printf("Filter \"%s\" does not exist for attenuator \"%s\", exit !!\n", \
filtname, motmne)
}
} else {
printf("motor \"%s\" is not configured as attenuator, exit !!\n", motmne)
exit
}
}'
#%UU%
#%MDESC% Show selected filters on every axis.
def attwa '{
local i motmne
waitmove ; get_angles
for (i=0;i<ATTNB;i++) {
motmne = ATTNUM[i]
printf("%s\t--->\t%s\n", motmne, _attwm_f(motmne))
}
}'
#%IU% (motmne)
#%MDESC% Return the selected filter for motor %B%motmne%B%.
def _attwm_f(motmne) '{
local mnum j filtsel
mnum = motor_num(motmne)
nbfilt = ATTTABLE[ATTTYPE[motmne]]["nbfilt"]
for (filtsel="Unknown",j=1;j<=nbfilt;j++) {
if ((A[mnum] < (ATTFILTPOS[motmne][j]+ATT_DELTA)) && \
(A[mnum] > (ATTFILTPOS[motmne][j]-ATT_DELTA))) {
filtsel = ATTFILTNAME[motmne][j]
}
}
return filtsel
}'
def attshow '{
attshow_ascii
}'
#%IU%
#%MDESC% Start the interactive ASCII menu.
def attshow_ascii '{
local _atteopt
local _attemaxe _attemfilt
local attereading
ATTE_ERROR=""
for(;;) {
_attshowmenu
if (_att_locked()) {
printf("\n\n%s\n\n", ATT_LOCKED_MSG)
_atteopt = _getval_timeout("0 to exit", 0, ATT_MENU_TIMEOUT)
if (_atteopt == "0" ) break
} else {
printf("\n\n\n\n")
_atteopt = _getval_timeout("Choose filter number or 0 to exit", 0, ATT_MENU_TIMEOUT)
printf("\n\n")
if (_atteopt == "0" ) break
if (_atteopt in ATTAXISSEL) {
tmot[0] = ATTAXISSEL[_atteopt] + 0
tpos[0] = ATTFILTERSEL[_atteopt] + 0
_attmv(1, tmot, tpos)
}
}
}
}'
def _getval_timeout(msg, default, tout) '{
local _s _c _t0
if (!tout) {
return getval(msg, default)
}
printf("%s (%s)? ", msg, default)
_s= ""
_t0= time()
while (1) {
sleep(0.01)
_c= input(-1)
if (_c) {
_t0= time()
}
if (_c=="\n") {
break
} else if ((_c=="\b" || _c=="\177") && _s) {
_s= substr(_s, 0, length(_s)-1)
printf("\b \b")
} else if (_c>=" " && _c<="z") {
_s= _s _c
printf(_c)
}
if (_c) {
_t0= time()
} else if ((time()-_t0)>tout) {
break
}
}
if (!_s) return (default)
else return (_s)
}'
#%IU%
#%MDESC% Prepare and show the menu on the screen.
def _attshowmenu '{
global ATTAXISSEL[]
global ATTFILTERSEL[]
local xoff yoff attex attey axmax nfil str newstr
local att_active att_label att_axeperline i j
att_axeperline=ATTNB>3?3:ATTNB
if (ATTNB==2) {
xdist = 22
} else {
xdist = 30
}
axmax=0
yoff = 0
axis = 0
clscreen()
printf("\n *********** ")
tty_cntl("us")
printf(" Attenuator MENU " )
tty_cntl("ue")
printf(" ***********\n")
for (i=0;i<ATTNB;i++) {
motmne = ATTNUM[i]
axis++;
#
# Axis Header.
attey = 3 + yoff
xoff = 5
if (ATTNB>2) {
mul = axis - 2
} else if (ATTNB==2) {
if (axis==1) {
mul=-1
} else {
mul=1
}
} else {
mul = 0
}
attex = 40 + xdist*mul - xoff
if ((ATTTABLE[ATTTYPE[motmne]]["step_size"] != -1) && \
(_att_checkhomef (motor_num(motmne)) == 4)) {
newstr = sprintf("!!%s!!", motmne)
str= sprintf(" %-12s",newstr)
tty_cntl("md")
tty_move(attex,attey,str)
tty_cntl("me")
} else {
str= sprintf(" %-8s",motmne)
tty_cntl("us")
tty_move(attex,attey,str)
tty_cntl("ue")
}
#
# Filters
nfil = ATTTABLE[ATTTYPE[motmne]]["nbfilt"]
if (nfil>axmax) {
axmax=nfil
ATTE_Y= yoff + axmax + 5
}
waitmove ; get_angles
for (j=0;j<nfil;j++) {
att_label = sprintf("%s", ATTFILTNAME[motmne][j+1])
xoff=10
attey = 4 + yoff + j
attex = 40 + xdist*mul - xoff
str= sprintf("%s",100*(i+1)+j+1)
ATTAXISSEL[str] = motor_num(motmne)
ATTFILTERSEL[str] = ATTFILTPOS[motmne][j+1]+0
str= sprintf(" %s ",str)
tty_cntl("md")
tty_move(attex,attey,str)
str= sprintf("%s", att_label)
if ((A[motor_num(motmne)]<(ATTFILTPOS[motmne][j+1]+ATT_DELTAMAX)) && \
(A[motor_num(motmne)]>(ATTFILTPOS[motmne][j+1]-ATT_DELTAMAX))) {
tty_cntl("mr")
tty_move(attex+5,attey,str)
tty_cntl("me")
} else {
tty_cntl("me")
tty_move(attex+5,attey,str)
}
}
if (axis%att_axeperline==0) {
yoff += axmax + 2
axmax=0
axis=0
}
}
}'
#%IU% <motor_mnemonic>
#%MDESC% Calculate [steps] the size between the filters as well as the
#backlash. The procedure is: send the motor to a hardware limit, start moving
#(in fine steps) in the other direction to find all the home switches and
#store their positions. Repete the procedure in the oposite direction to
#estimate the backlash.
def attdiag '{
local motmne mnum stepsizeold stepsizenew course_neg course_pos
local backlashold limp limm i
local diffarr firstauxpos firstauxneg lastauxpos lastauxneg aux
global ATTDIAGPOS[]
global ATTDIAGNEG[]
local device
if ($# < 1) {
printf ("Usage: attdiag attmne [direction]\n")
exit
}
if (_att_locked()) {
printf("%s\n", ATT_LOCKED_MSG)
exit
}
motmne = "$1"
mnum = motor_num(motmne)
if (mnum == -1) {
printf("Motor %s is not configured, exit...\n", motmne)
exit
}
device = motor_par(mnum,"device_id")
# as we do not know the attenuator type, we work in steps
stepsizeold = motor_par(mnum, "step_size")
backlashold = motor_par(mnum, "backlash")
limp = get_lim(mnum, +1)
limm = get_lim(mnum, -1)
if (stepsizeold < 0)
stepsizenew = -1
else
stepsizenew = 1
printf("Change step size from %d to %d\n", stepsizeold, stepsizenew)
spec_par("modify_step_size", 1)
motor_par(mnum, "step_size", stepsizenew)
printf("Change backlash from %d to 0\n", backlashold)
motor_par(mnum, "backlash", 0)
printf("Change limits from (%g,%g) to (-1000000,1000000)\n", limm, limp)
set_lim(mnum, -1000000, 1000000)
printf("Go to both limits. Calculate total movement allowed\n")
_att_gotolim(mnum, -1)
chg_dial(mnum, 0)
chg_offset(mnum, 0)
course_pos = fabs(_att_gotolim(mnum, 1))
chg_dial(mnum, 0)
chg_offset(mnum, 0)
printf("Maximum movement from NEG to POS is %d steps\n\n", course_pos)
printf("Go to both limits in opposite direction. ")
printf ("Calculate total movement allowed\n")
#printf("Go to NEGATIVE limit to calculate total movement allowed\n")
course_neg = fabs(_att_gotolim(mnum, -1))
chg_dial(mnum, 0)
chg_offset(mnum, 0)
printf("Maximum movement from POS to NEG is %d steps\n\n", course_neg)
printf("Diagnostic from NEGATIVE to POSITIVE switches\n")
if (device == "icepap")
nbfilt = _attrefallinit(mnum,1,50)
else
nbfilt = _attdiag(mnum, 1, course_pos)
_attdiagprint(mnum, 1, course_pos, nbfilt)
printf("Diagnostic from POSITIVE to NEGATIVE switches\n")
if (device == "icepap")
nbfilt = _attrefallinit(mnum,-1,50)
else
nbfilt = _attdiag(mnum, -1, course_pos)
_attdiagprint(mnum, -1, course_neg, nbfilt)
for (diffarr=0,i=2;i<=nbfilt-1;i++) {
diffarr += (ATTDIAGPOS[motmne][sprintf("swstart%d",i)] - \
ATTDIAGNEG[motmne][sprintf("swstart%d",i)])
}
diffarr /= nbfilt-2
firstauxpos = ATTDIAGPOS[motmne]["swend1"]
firstauxneg = ATTDIAGNEG[motmne]["swend1"]
lastauxpos = ATTDIAGPOS[motmne][sprintf("swstart%d",nbfilt)]
lastauxneg = ATTDIAGNEG[motmne][sprintf("swstart%d",nbfilt)]
aux = ((firstauxpos+firstauxneg) > \
(course_pos-lastauxpos+course_neg-lastauxneg)?-1:1)
printf("***** Estimated backlash : %d (steps)\n", int(diffarr))
printf("***** Adviced backlash correction : %d (steps)\n", \
aux*int(diffarr*1.5))
motor_par(mnum, "step_size", stepsizeold)
motor_par(mnum, "backlash", backlashold)
set_lim(mnum, limm, limp)
spec_par("modify_step_size", 0)
}'
#%IU% (mnum, way, course, nbfilt)
#%MDESC% Print the information gathered during the diagnostic scan.
def _attdiagprint(mnum, way, course, nbfilt) '{
local infoarr motmne from to leng lengstr pos posstr pos_prec
local diff diffstr i fromstr
infoarr = (way==1?"ATTDIAGPOS":"ATTDIAGNEG")
motmne = motor_mne(mnum)
printf("\n***** Negative Hardware Limit at 0\n")
printf("***** filter # | pos (diff) | from | to | length |\n")
printf("***** ------------------------------------------------------------------\n")
from = @infoarr[motmne]["swstart1"]
to = @infoarr[motmne]["swend1"]
if (from == -1) {
fromstr = "( 0)"
lengstr = sprintf(">%7d", to)
posstr = " Unknown"
pos_prec = -1
} else {
fromstr = sprintf("%8d", from)
leng = fabs(from-to)
lengstr = sprintf("%8d", leng)
pos_prec = to - leng / 2
posstr = sprintf("%8d", pos_prec)
}
printf("***** 1 | %s | %s | %8d | %s |\n",posstr,fromstr,to,lengstr)
pos_prec = -1
for (i=2;i<nbfilt;i++) {
from = @infoarr[motmne][sprintf("swstart%d",i)]
to = @infoarr[motmne][sprintf("swend%d", i)]
leng = fabs(from-to)
pos = to - leng / 2
if (pos_prec > 0) {
diff = pos - pos_prec
printf("***** %2d | %8d (%8d) | %8d | %8d | %8d |\n",i,pos,diff,from,to,leng)
} else {
printf("***** %2d | %8d | %8d | %8d | %8d |\n",i,pos,from,to,leng)
}
pos_prec = pos
}
from = @infoarr[motmne][sprintf("swstart%d",nbfilt)]
to = @infoarr[motmne][sprintf("swend%d", nbfilt)]
if (to == -1) {
tostr = sprintf("(%6d)", course)
lengstr = sprintf(">%7d", course-from)
posstr = " Unknown"
pos_prec = -1
diffstr = " "
} else {
tostr = sprintf("%8d", to)
leng = fabs(from-to)
lengstr = sprintf("%8d", leng)
pos = to - leng / 2
posstr = sprintf("%8d", pos)
diffstr = sprintf("(%8d)", pos - pos_prec)
}
printf("***** %2d | %s %s | %8d | %s | %s |\n",nbfilt,posstr,diffstr,from,tostr,lengstr)
printf("***** positive Hardware Limit at %g\n\n", course)
}'
#%IU% (mnum, way, course)
#%MDESC% Internal function to scan the blade %B%mnum%B% in the direction of the
#scan %B%way%B% defined in advance as 1 (from negative to positive limit) or
#-1 (positive to negative limit). The algorithm is based on the home
#switchsignal being active or not moving in fine steps for at most %B%course%B%
#position. Returns the number of filters (home switches) found.
def _attdiag(mnum, way, course) '{
local step startpos endpos i nbfilt motmne nextpos
local prev_status new_status
local auxarr[]
step = way * 50
startpos = (way==1?0:course)
endpos = (way==1?course:0)
motmne = motor_mne(mnum)
auxarr[motmne]["HarLimNeg"] = 0
auxarr[motmne]["HarLimPos"] = course
_att_gotolim(mnum, -way)
waitmove ; get_angles
printf("*** check filter #1\n")
if (_att_checkhomef(mnum) == 0) {
if (way == 1)
auxarr[motmne]["swstart1"] = -1
else
auxarr[motmne]["swend1"] = -1
} else {
while (_att_checkhomef(mnum) == 4) {
A[mnum] += step
move_em
waitmove ; get_angles
}
if (way == 1)
auxarr[motmne]["swstart1"] = A[mnum]
else
auxarr[motmne]["swend1"] = A[mnum]
}
while (_att_checkhomef(mnum) == 0) {
A[mnum] += step
move_em
waitmove ; get_angles
}
if (way == 1)
auxarr[motmne]["swend1"] = A[mnum]
else
auxarr[motmne]["swstart1"] = A[mnum]
printf("*** check filter #2\n")
nbfilt = 1
nextpos = A[mnum]+step
test = (way==1?(nextpos<course):(nextpos>0))
prev_status = _att_checkhomef(mnum)
while (test) {
A[mnum] = nextpos
move_em
waitmove ; get_angles
new_status = _att_checkhomef(mnum)
if ((prev_status == 4) && (new_status == 0)) {
nbfilt++
if (way == 1)
auxarr[motmne][sprintf("swstart%d",nbfilt)] = A[mnum]
else
auxarr[motmne][sprintf("swend%d",nbfilt)] = A[mnum]
}
if ((prev_status == 0) && (new_status == 4)) {
if (way == 1)
auxarr[motmne][sprintf("swend%d", nbfilt)] = A[mnum]
else
auxarr[motmne][sprintf("swstart%d", nbfilt)] = A[mnum]
printf("*** check filter #%d\n", nbfilt+1)
}
prev_status = new_status
nextpos = A[mnum] + step
test = (way==1?(nextpos<course):(nextpos>0))
}
if (_att_checkhomef(mnum) == 0) {
if (way == 1)
auxarr[motmne][sprintf("swend%d", nbfilt)] = -1
else
auxarr[motmne][sprintf("swstart%d", nbfilt)] = -1
}
if (way == -1) {
ATTDIAGNEG[motmne]["HarLimNeg"] = 0
ATTDIAGNEG[motmne]["HarLimPos"] = course
for (i=1;i<=nbfilt;i++) {
ATTDIAGNEG[motmne][sprintf("swstart%d",i)] = \
auxarr[motmne][sprintf("swstart%d",nbfilt-i+1)]
ATTDIAGNEG[motmne][sprintf("swend%d",i)] = \
auxarr[motmne][sprintf("swend%d",nbfilt-i+1)]
}
} else {
ATTDIAGPOS[motmne]["HarLimNeg"] = 0
ATTDIAGPOS[motmne]["HarLimPos"] = course
for (i=1;i<=nbfilt;i++) {
ATTDIAGPOS[motmne][sprintf("swstart%d",i)] = \
auxarr[motmne][sprintf("swstart%d",i)]
ATTDIAGPOS[motmne][sprintf("swend%d",i)] = \
auxarr[motmne][sprintf("swend%d",i)]
}
}
return(nbfilt)
}'
#%IU% (mnum)
#%MDESC% Internal function to scan the blade %B%mnum%B%. The direction of the
#scan (_SIGN) could be defined in advance as 1 (from negative to positive
#limit) or -1 (positive to negative limit). The algorithm is based on the home
#switch signal being active or not moving in fine steps, which absolute value
#(_CALIB_STEP) could be set as well. This is the procedure used with icepep
#controller. Returns the number of filters (home switches) found.
def _attrefallinit(mnum, way, step) '{
local a0 a1 mid dist cmd stat motmne
global ATTDIAGNEG ATTDIAGPOS ATTFILTPARS[]
local step_mm label device
local i ii
motmne = motor_mne(mnum)
step_mm = motor_par(mnum,"step_size")
if (way)
_SIGN = way
if (step)
_CALIB_STEP = step
(_CALIB_STEP > 1) ? (label = "steps") : (label = "mm")
a0 = _att_gotolim(mnum,-1* _SIGN)
if (_ATTDEBUG)
printf ("Limit switch reacheat at position %.2f\n", a0)
sleep(.5)
#check if home switch active
if (_attswitchf (mnum, 0, 99) == 0) {
printf ("\t - both limit and home switches active\n")
a0 = A[mnum]
} else {
printf("\t - move until the home sitch of the first filter reached...\n")
a0 = _attswitchf (mnum,_CALIB_STEP,4)
}
if (_ATTDEBUG)
printf ("Home switch reached at position %.2f\n", a0)
printf("\t - move until the home switch of the first filter left...\n")
a1 = _attswitchf (mnum,_CALIB_STEP,0)
mid[0] = a1 - _SIGN * fabs(a1-a0)/2
if (_ATTDEBUG) {
printf ("Home switch left at position %.2f\n", a1)
printf ("Home switch size %.2f %s\n", fabs(a1-a0), label)
if (fabs(step_mm) < 1)
printf ("Home switch size %.2f mm\n", fabs((a1-a0)/step_mm))
}
if (_SIGN < 0) {
ATTDIAGNEG[motmne]["swstart1"] = a0
ATTDIAGNEG[motmne]["swend1"] = a1
} else {
ATTDIAGPOS[motmne]["swstart1"] = a0
ATTDIAGPOS[motmne]["swend1"] = a1
}
i = 2
while(1) {
printf("\t - move until the home switch of filter #%1d reached...\n", i)
a0 = _attswitchf (mnum,_CALIB_STEP,4)
if (_ATTDEBUG)
printf ("Home switch reached at position %.2f\n", a0)
printf("\t - move until the home switch of filter #%1d left...\n", i)
a1 = _attswitchf (mnum,_CALIB_STEP,0)
if (_ATTDEBUG)
printf ("Home switch left at position %.2f\n", a1)
if (fabs(a1-a0) > 0.05) {
if (_SIGN < 0) {
ATTDIAGNEG[motmne][sprintf("swstart%d",i)] = a0
ATTDIAGNEG[motmne][sprintf("swend%d",i)] = a1
} else {
ATTDIAGPOS[motmne][sprintf("swstart%d",i)] = a0
ATTDIAGPOS[motmne][sprintf("swend%d",i)] = a1
}
mid[i-1] = a1 - _SIGN * fabs(a1-a0)/2
dist[i-1] = fabs(mid[i-1] - mid[i-2])
if (_ATTDEBUG) {
printf ("Home switch size %.2f %s\n", fabs(a1-a0), label)
printf ("\t - Filter distance: %.2f %s. ", dist[i-1], label)
printf ("Filter (switch) size: %.2f %s\n", fabs(a1-a0), label)
if (fabs(step_mm) < 1) {
printf ("\t - Filter distance: %.2f mm. ", fabs(dist[i-1]/step_mm))
printf ("Filter (switch) size: %.2f mm\n", fabs((a1-a0)/step_mm))
}
}
stat = _attlimitswitchf (mnum, _SIGN)
if (stat == 0)
i++
else
break
} else {
printf ("No more filters, exit...\n")
i--
break
}
}
printf ("%d filters found\n",i)
if (fabs(_CALIB_STEP) < 1) {
ATTFILTPARS[motmne]["filtpos1"] = 0
#ATTFILTPARS[motmne]["filtpos1"] = mid[0]
for (ii=2; ii<=i; ii++) {
ATTFILTPARS[motmne][sprintf("filtpos%d",ii)] = \
(mid[ii-2] + dist[ii-1])*_SIGN
}
}
return(i)
}'
#%IU% ()
#%MDESC% Define a user macro to lock the attenuators.
def _att_locked() '{
global ATT_LOCKED
ATT_LOCKED = 0
user_att_locked
return(ATT_LOCKED)
}'
#%UU%
#%MDESC% Get the filter names and corresponding motor positions for the
#current axe from the default hardware object - xml file.
def att_getxml '{
local keys
if (!ATT_HO[_ATTMOT]["filename"])
ATT_HO[_ATTMOT]["filename"] = \
getval("Attenuator axe hardware object", ATT_HO[_ATTMOT]["filename"])
if (!ATT_HO[_ATTMOT]["root"])
ATT_HO[_ATTMOT]["root"] = \
getval("Attenuator axe hardware object root", ATT_HO[_ATTMOT]["root"])
if (!ATT_HO[_ATTMOT]["name"])
ATT_HO[_ATTMOT]["name"] = \
getval("Attenuator axe hardware object username keyword", \
ATT_HO[_ATTMOT]["name"])
if (!ATT_HO[_ATTMOT]["offset"])
ATT_HO[_ATTMOT]["offset"] = \
getval("Attenuator axe hardware object offset keyword", \
ATT_HO[_ATTMOT]["offset"])
keys["name"] = ATT_HO[_ATTMOT]["name"]
keys["offset"] = ATT_HO[_ATTMOT]["offset"]
_att_getxml(ATT_HO[_ATTMOT]["filename"], _ATTMOT, \
ATT_HO[_ATTMOT]["root"], keys)
}'
#%IU% (ho, motmne, keys_root, keys)
#%MDESC% Get the filter names and corresponding motor positions for the
#%B%motnum%B% axis from the %B%ho%B% hardware object - xml file.
def _att_getxml(ho, motmne, keys_root, keys) '{
local key name
global ATTFILTERS
key = sprintf ("%s/%s", keys_root, keys["name"])
if (xml_read(ho,key) == -1) {
eprintf ("Cannot read the axis XML file, names not set\n")
return(-1)
}
for (name in XML_tmp[]["__value__"]) {
ATTFILTERS[motmne][sprintf ("name%d", name+1)] = XML_tmp[name]["__value__"]
}
key = sprintf ("%s/%s", keys_root, keys["offset"])
if (xml_read(ho, key) == -1) {
eprintf ("Cannot read the axis XML file, names not set\n")
return(-1)
}
for (name in XML_tmp[]["__value__"]) {
ATTFILTERS[motmne][sprintf ("pos%d", name+1)] = XML_tmp[name]["__value__"]
}
return(0)
}'
#%UU%
#%MDESC% Write the filter names and corresponding motor positions for the
#current axe from the default hardware object - xml file. The information
#to write is taken from the ATTFILTERS arary.
def att_writexml '{
local keys
if (!ATT_HO[_ATTMOT]["filename"])
ATT_HO[_ATTMOT]["filename"] = \
getval("Attenuator axe hardware object", ATT_HO[_ATTMOT]["filename"])
if (!ATT_HO[_ATTMOT]["root"])
ATT_HO[_ATTMOT]["root"] = \
getval("Attenuator axe hardware object root", ATT_HO[_ATTMOT]["root"])
if (!ATT_HO[_ATTMOT]["name"])
ATT_HO[_ATTMOT]["name"] = \
getval("Attenuator axe hardware object username keyword", \
ATT_HO[_ATTMOT]["name"])
if (!ATT_HO[_ATTMOT]["offset"])
ATT_HO[_ATTMOT]["offset"] = \
getval("Attenuator axe hardware object offset keyword", \
ATT_HO[_ATTMOT]["offset"])
keys["name"] = ATT_HO[_ATTMOT]["name"]
keys["offset"] = ATT_HO[_ATTMOT]["offset"]
_att_writexml(ATT_HO[_ATTMOT]["filename"], _ATTMOT, \
ATT_HO[_ATTMOT]["root"], keys)
}'
#%IU% (ho, motmne, keys_root, keys)
#%MDESC% Write the filter names and corresponding motor positions for the
#%B%motnum%B% axis in the %B%ho%B% hardware object - xml file. The information
#to write is taken from the ATTFILTERS arary.
def _att_writexml(ho, motmne, keys_root, keys) '{
local i n newname newpos
local key
n = ATTTABLE[ATTTYPE[motmne]]["nbfilt"]
for (i=1;i<=n;i++) {
key = sprintf("%s[%d]/%s",keys_root,i, keys["name"])
newname = sprintf("%s", ATTFILTERS[motmne][sprintf("name%d", i)])
xml_cache_write(ho, key, newname)
#key = sprintf("/equipment/positions/position[%d]/motor",i)
key = sprintf("%s[%d]/%s",keys_root,i, keys["offset"])
newpos = sprintf("%g", ATTFILTERS[motmne][sprintf("pos%d", i)])
xml_cache_write(ho, key, newpos)
}
xml_do_write()
}'
#%UU% <motor_mnemonic [calibration_step [sign]]>
#%MDESC% Scan the blade %B%motor_mnemonic%B%. The direction of the movement
#%B%sign%B% is defined as 1 (from negative limit in positive direction) or -1
#(positive limit in negative direction) - default value is 1. The algorithm is
#based on the home switch signal being active or not, moving in fine steps,
#which absolute [mm] value %B%calibration_step%B% could be set - default value
#is 0.004 mm.
def attrefall '{
local mnum nbfilt olddebug
global _CALIB_STEP _SIGN _ATTDEBUG
if (_att_locked()) {
printf("%s\n", ATT_LOCKED_MSG)
exit
}
if ($# < 1) {
printf ("Usage: attrefall motor_mnemonic [calib_step [direction]]\n")
_ATTMOT = getval("Attenuator motor mnemonic: ",_ATTMOT)
_CALIB_STEP = fabs(getval("Attenuator calibration step [mm or step]: ", _CALIB_STEP))
_SIGN = getval("Direction to scan - 1(positive)/-1(negative)", _SIGN)
mnum =_check_mne(_ATTMOT)
} else {
_check0 "$1"
_ATTMOT ="$1"
mnum = $1
_CALIB_STEP = fabs($2)
_SIGN = $3
}
if (!_CALIB_STEP)
_CALIB_STEP = 0.004
if (!_SIGN)
_SIGN = 1
if (ATTTABLE[ATTTYPE[_ATTMOT]]["filter_distance_mm"] == -1) {
printf("Axis without switches! Cannot get reference, exit.\n")
exit
}
if (ATTTYPE[_ATTMOT] == 0 || \
(nbfilt = ATTTABLE[ATTTYPE[_ATTMOT]]["nbfilt"]) == 0) {
printf("Please, run attsetup first, exit\n")
exit
}
printf("**** Scanning filter positions of %s ****\n", _ATTMOT)
olddebug = _ATTDEBUG
_ATTDEBUG = 1
_attrefall(mnum)
printf ("Moving to filter #2...\n")
A[mnum] = ATTFILTPOS[_ATTMOT][2]
move_em; _show_waitf()
_ATTDEBUG = olddebug
}'
#%IU% (mnum)
#%MDESC% Internal function to scan the blade %B%mnum%B%. The direction of the
#scan (_SIGN) should be defined in advance as 1 (from negative to positive
#limit) or -1 (positive to negative limit). The algorithm is based on the home
#switchsignal being active or not moving in fine steps, which absolute value
#(_CALIB_STEP) should be set.
#Returns the number of filters (home switches) found.
def _attrefall(mnum) '{
local a0 a1 mid dist cmd stat motmne
global ATTDIAGNEG ATTDIAGPOS ATTFILTPARS[]
local dist_mm label
local i ii
motmne = motor_mne(mnum)
if (_SIGN < 0) {
cmd = sprintf ("motor_par(%d,\"low_lim_set\")",mnum)
} else {
cmd = sprintf ("motor_par(%d,\"high_lim_set\")",mnum)
}
if (_CALIB_STEP > 1) {
label = "steps"
dist_mm = 1
} else {
label = "mm"
dist_mm = ATTTABLE[ATTTYPE[motmne]]["filter_distance_mm"]
}
a0 = _att_gotolim(mnum,-1* _SIGN)
if (_ATTDEBUG)
printf ("Limit switch reacheat at position %.2f\n", a0)
step = _CALIB_STEP
sleep(.5)
#check if home switch active
if (_attswitchf (mnum, 0, 99) == 0) {
printf ("\t - both limit and home switches active\n")
a0 = A[mnum]
} else {
printf("\t - move until the home sitch of the first filter reached...\n")
a0 = _attswitchf (mnum,step,4)
}
if (_ATTDEBUG)
printf ("Home switch reached at position %.3f\n", a0)
printf("\t - move until the home switch of the first filter left...\n")
a1 = _attswitchf (mnum,step,0)
mid[0] = a1 - _SIGN * fabs(a1-a0)/2
if (_ATTDEBUG) {
printf ("Home switch left at position %.3f\n", a1)
printf ("Home switch size %.2f %s\n", fabs((a1-a0)*dist_mm), label)
}
printf ("\t - move to a position between the first and second filters...\n")
waitmove ; get_angles
A[mnum] += 0.5 * _SIGN
move_em
_show_waitf()
waitmove ; get_angles
i = 2
while(1) {
printf("\t - move until the home switch of filter #%1d reached...\n", i)
a0 = _attswitchf (mnum,step,4)
if (_ATTDEBUG)
printf ("Home switch reached at position %.3f\n", a0)
printf("\t - move until the home switch of filter #%1d left...\n", i)
a1 = _attswitchf (mnum,step,0)
if (_ATTDEBUG)
printf ("Home switch left at position %.3f\n", a1)
if (fabs(a1-a0) > 0.05) {
mid[i-1] = a1 - _SIGN * fabs(a1-a0)/2
dist[i-1] = fabs(mid[i-1] - mid[i-2])
if (_ATTDEBUG) {
printf ("Home switch size %.2f %s\n", fabs((a1-a0)*dist_mm), label)
printf ("\t - Filter distance: %.2f %s. ", \
fabs(dist[i-1]*dist_mm), label)
printf ("Filter (switch) size: %.2f %s\n", \
fabs((a1-a0)*dist_mm), label)
}
stat = eval(cmd)
if (stat == 0) {
i++
printf ("\t - move to a position between filter #%d and #%d ...\n", \
(i-1), i)
waitmove ; get_angles
A[mnum] += 0.5 * _SIGN
move_em
_show_waitf()
} else
break
} else {
i--
break
}
}
tty_cntl("md")
printf ("%d filter positions found:\n",i)
if (_CALIB_STEP < 1) {
ATTFILTPARS[motmne]["filtpos1"] = mid[0]
printf ("\tFilter #1: %.2f\n", ATTFILTPARS[motmne]["filtpos1"])
ATTFILTPOS[motmne][1] = mid[0]
for (ii=2; ii<=i; ii++) {
ATTFILTPARS[motmne][sprintf("filtpos%d",ii)] = \
(mid[ii-2] + dist[ii-1])*_SIGN
ATTFILTPOS[motmne][sprintf("%d",ii)] = \
(mid[ii-2] + dist[ii-1])*_SIGN
printf ("\tFilter #%d: %.2f\n", ii, \
ATTFILTPARS[motmne][sprintf("filtpos%d",ii)])
}
}
tty_cntl("me")
return(i)
}'
#%IU% (mnum)
#%MDESC% Internal function to find the "zero reference filter". The algorithm
# is based on the spec home mechanism. The direction of the movement (_SIGN)
#should be defined in advance as 1 (from negative limit in positive
#direction) or -1 (positive limit in negative direction). The absolute value
#of the step for the fine move when the home switch is active (_CALIB_STEP)
#should be set. At the end move to the centre of the filter and set it as
#position 2.
def _attrefhome(mnum) '{
local a0 a1 dist mid[] step
global ATTFILTPARS[]
a0 = _att_gotolim(mnum,-1* _SIGN)
printf ("Limit switch reacheat at position %.2f\n", a0)
step = _CALIB_STEP
sleep(.5)
#check if home switch active
if (_attswitchf (mnum, 0, 99) == 0) {
printf ("\t - both limit and home switches active\n")
a0 = A[mnum]
} else {
printf("\t - move until the home switch of the first filter reached...\n")
if ( _SIGN > 0)
chg_dial(mnum,"home+")
else
chg_dial(mnum,"home-")
_show_waitf()
a0 = A[mnum]
}
printf ("Home switch reached at position %.2f\n", a0)
printf("\t - move until the home switch of the first filter left...\n")
a1 = _attswitchf (mnum,step,0)
printf ("Home switch left at position %.2f\n", a1)
mid[0] = a1 - _SIGN * fabs(a1-a0)/2
printf ("Home switch size %.2f mm\n", fabs(a1-a0))
printf("\t - move until the home switch of the second filter reached...\n")
if ( _SIGN > 0)
chg_dial(mnum,"home+")
else
chg_dial(mnum,"home-")
_show_waitf()
a0 = A[mnum]
printf ("Home switch reached at position %.2f\n", a0)
printf("\t - move until the home switch of the second filter left...\n")
a1 = _attswitchf (mnum,step,0)
printf ("Home switch left at position %.2f\n", a1)
mid[1] = a1 - _SIGN * fabs(a1-a0)/2
printf ("Home switch size %.2f mm\n", fabs(a1-a0))
dist = fabs(mid[1] - mid[0])
printf ("\t - Filter distance: %.2f. Filter (switch) size: %.2f\n", \
dist, fabs(a1-a0))
printf ("Moving to the centre of the first filter (%.2f)\n", mid[0])
A[mnum] = mid[0]
move_all; waitmove
printf ("Set the position to 0\n")
chg_dial(mnum,0)
chg_offset(mnum,0)
ATTFILTPARS[motor_mne(mnum)]["filtpos1"] = 0
ATTFILTPARS[motor_mne(mnum)]["filtpos2"] = dist*_SIGN
}'
#%IU% (mnum)
#%MDESC% Internal function to scan the blade %B%mnum%B%. The direction of the
#scan (_SIGN) should be defined in advance as 1 (from negative to positive
#limit) or -1 (positive to negative limit). The algorithm is based on the home
#switch being hardware configured the same way for all the filters and uses
#the spec home mechanism. The absolute value of the step for the fine move
#when the home switch is active (_CALIB_STEP) should be set.
#Returns the number of filters (home switches) found.
def _attrefhomeall(mnum) '{
local a0 a1 dist step cmd stat motmne way
global ATTDIAGNEG ATTDIAGPOS ATTFILTPARS[]
local step_mm label
local i ii
motmne = motor_mne(mnum)
step_mm = motor_par(mnum,"step_size")
if (_SIGN < 0) {
cmd = sprintf ("motor_par(%d,\"low_lim_set\")",mnum)
} else {
cmd = sprintf ("motor_par(%d,\"high_lim_set\")",mnum)
}
(_CALIB_STEP > 1) ? (label = "steps") : (label = "mm")
a0 = _att_gotolim(mnum,-1* _SIGN)
if (_ATTDEBUG)
printf ("Limit switch reacheat at position %.2f\n", a0)
step = _CALIB_STEP * _SIGN
sleep(.5)
#check if home switch active
if (_attswitchf (mnum, 0, 99) == 0) {
printf ("\t - both limit and home switches active\n")
a0 = A[mnum]
} else {
printf("\t - move until the home switch of the first filter reached...\n")
if ( _SIGN > 0)
chg_dial(mnum,"home+")
else
chg_dial(mnum,"home-")
_show_waitf()
a0 = A[mnum]
}
if (_ATTDEBUG)
printf ("Home switch reached at position %.2f\n", a0)
printf("\t - move until the home switch of the first filter left...\n")
a1 = _attswitchf (mnum,step,0)
if (fabs(a1-a0) > 0.05) {
mid[0] = a1 - _SIGN * fabs(a1-a0)/2
if (_ATTDEBUG) {
printf ("Home switch left at position %.2f\n", a1)
printf ("Home switch size %.2f %s\n", fabs(a1-a0), label)
if (fabs(step_mm) < 1)
printf ("Home switch size %.2f mm\n", fabs((a1-a0)/step_mm))
}
if (_SIGN < 0) {
ATTDIAGNEG[motmne]["swstart1"] = a0
ATTDIAGNEG[motmne]["swend1"] = a1
} else {
ATTDIAGPOS[motmne]["swstart1"] = a0
ATTDIAGPOS[motmne]["swend1"] = a1
}
i = 2
} else
i = 1
while(1) {
printf("\t - move until the home switch of filter #%1d reached...\n", i)
if ( _SIGN > 0)
chg_dial(mnum,"home+")
else
chg_dial(mnum,"home-")
_show_waitf()
a0 = A[mnum]
if (_ATTDEBUG)
printf ("Home switch reached at position %.2f\n", a0)
printf("\t - move until the home switch of the filter #%1d left...\n", i)
a1 = _attswitchf (mnum,step,0)
if (_ATTDEBUG)
printf ("Home switch left at position %.2f\n", a1)
if (fabs(a1-a0) > 0.05) {
if (_SIGN < 0) {
ATTDIAGNEG[motmne][sprintf("swstart%d",i)] = a0
ATTDIAGNEG[motmne][sprintf("swend%d",i)] = a1
} else {
ATTDIAGPOS[motmne][sprintf("swstart%d",i)] = a0
ATTDIAGPOS[motmne][sprintf("swend%d",i)] = a1
}
mid[i-1] = a1 - _SIGN * fabs(a1-a0)/2
dist[i-1] = fabs(mid[i-1] - mid[i-2])
if (_ATTDEBUG) {
printf ("Home switch size %.2f %s\n", fabs(a1-a0), label)
printf ("\t - Filter distance: %.2f %s. ", dist[i-1], label)
printf ("Filter (switch) size: %.2f %s\n", fabs(a1-a0), label)
if (fabs(step_mm) < 1) {
printf ("\t - Filter distance: %.2f mm. ", fabs(dist[i-1]/step_mm))
printf ("Filter (switch) size: %.2f mm\n", fabs((a1-a0)/step_mm))
}
}
stat = eval(cmd)
if (stat == 0)
i++
else
break
} else {
printf ("No more filters, exit...\n")
i--
break
}
}
printf ("%d filters found\n",i)
ATTFILTPARS[motmne]["filtpos1"] = mid[0]
for (ii=2; ii<=i; ii++)
ATTFILTPARS[motmne][sprintf("filtpos%d",ii)] = \
(mid[ii-2] + dist[ii-1])*_SIGN
return(i)
}'
#### Obsolete macros - SpecGUI ####
#%IU% [<where to see atenuators (gui/ascii)]
#%MDESC% Starts the interactive menu.
#If no parameter is set, choose gui if SpecGUI is running 0n the SPEC version.
#Otherewise take the parameter.
def attshow_old '{
if ( (($# != 1) && (!GUI_RUN)) || (($# == 1) && ("$1" != "gui")))
attshow_ascii
else
attshow_gui
}'
#%IU%
#%MDESC% Starts the interactive ASCII menu.
def attshow_gui '{
global ATT_PID
local file
if (\!(ATT_PID && file_info(ATT_PID,"alive"))) {
file = sprintf("/tmp/attgui_%s_%s.pid",USER,SPEC)
attcmd = "att_gui"
unix(sprintf("/bin/rm -f %s",file))
unix(sprintf("%s >/dev/null 2>&1 & echo \$! > %s",attcmd,file))
ATT_PID = getline(file)
getline(file,"close")
}
}'
#%IU%
#%MDESC%
# setup GUI use of attenuator, chains Xattwa with user_getpangles
def Xattsetup '{
if (GUI_RUN) cdef("user_getpangles","Xattwa\n","_Xatt_",0x20)
Xattwa 0
}'
#%IU%
#%MDESC%
# update GUI att filter.
# GUI outputfield name must be "att-mnemonic"_name, e.g. att1 -> att1_name
# This macro can be chained with user_getpangles.
def Xattwa '{
local i name motmne moti
global XOLDATT_A[]
for (i=0;i<ATTNB;i++) {
motmne = ATTNUM[i]
moti = motor_num(motmne)
if(A[moti] != XOLDATT_A[moti] || $#) {
Xval(name=motmne"_name", _attwm_f(motmne))
XOLDATT_A[moti]=A[moti]
}
}
}'
#%IU%
#%MDESC%
# Send configuration to graphical application
def Xattconfig '{
local i j str
str = sprintf("%d %g", ATTNB, ATT_DELTA)
for (i=0;i<ATTNB;i++) {
str = sprintf(" %s %s", str, ATTNUM[i])
str = sprintf(" %s %d", str, motor_num(ATTNUM[i]))
nbfilt = ATTTABLE[ATTTYPE[ATTNUM[i]]]["nbfilt"]
str = sprintf(" %s %d", str, nbfilt)
str = sprintf(" %s %d", str, ATTSEC[ATTNUM[i]])
for (j=1;j<=nbfilt;j++) {
str = sprintf(" %s %s", str, ATTFILTNAME[ATTNUM[i]][j])
str = sprintf(" %s %g", str, ATTFILTPOS[ATTNUM[i]][j])
}
}
bpipe attconfig
fprintf("pipe", " %s ", str)
epipe
}'
#### Enf obsolete macros ####
#%MACROS%
#%IMACROS%
#%AUTHOR% %BR%
#%TOC%
#$Revision: 1.17 $, $Date: 2014/10/14 13:27:32 $
#%END%
#%LOG%
#$Log: natt.mac,v $
#Revision 1.17 2014/10/14 13:27:32 papillon
#* added a global variable ATT_MENU_TIMEOUT : if set attshow
# will silently exit after ATT_MENU_TIMEOUT sec without
# any user input in order to not block spec session
# for guis, spec server, ...
# This variable is reset to 0 on attsetup to not disturb
# current installation.
#
#Revision 1.16 2013/08/23 10:18:41 papillon
#* add a user hook macro on end of att move
#
#Revision 1.15 2013/04/16 13:48:42 beteva
#print warning for wrong configuration only if needed (ATT_CHECK!=0)
#
#Revision 1.14 2012/09/18 14:09:32 papillon
#* correct attwa / _attwm_f
#
#Revision 1.13 2012/03/07 16:28:38 beteva
#Commands to control the attenuator, using ICEPAP motors.
#Two new types (from ID24).
#
#Revision 1.12 2008/08/12 14:36:19 rey
#documentaiton changes
#
#Revision 1.11 2006/06/21 14:59:37 berruyer
#* add a new attenuator type: no switches
#their position without checks
#* add global variables to store motors and positions during a _attmv. To be used in user_att_lock for attenuators checking
#
#Revision 1.10 2006/02/06 08:52:24 rey
#Added support for ID14 attenuators
#
#Revision 1.9 2006/02/06 08:42:19 rey
#ID14 attenuators type added.
#
#Revision 1.8 2005/09/21 12:44:34 pepellin
#Use clscreen()
#
#Revision 1.7 2003/02/27 13:55:31 klora
#Changed documentation and WARNING message in attmv (motor number was given
#and not the mnemonic)
#
#Revision 1.6 2003/01/27 13:25:26 claustre
#move ATT_DELTAMV and ATT_DELTAMAX globals to attsetup macro to get them
#initialized right now.
#
#Revision 1.5 2003/01/10 15:55:45 berruyer
#add attenuator set for Spline beamline
#
#Revision 1.4 2002/09/11 08:13:32 berruyer
#correct sel_lm dans attdiag
#change display policy in attshow: add delta to be n filter and show if or not on switches
#add new id17 attenuator type (oxford 4filters 35mm)
#
#Revision 1.3 2002/04/30 10:38:00 10:38:00 berruyer (Gilles Berruyer)
#add parameters number ceck in attlimits
#
#Revision 1.2 2002/03/07 15:55:00 15:55:00 berruyer (Gilles Berruyer)
#add saving in files
#remove database support
#direct access via builder to natt_appli
#attlimits added
#attdiag added
#last correction: syntax error in Xattconfig, _attmv, added change of limits in attdiag and parameter presence in the same macros
#
#Revision 1.1 2001/03/19 14:40:55 14:40:55 beteva (Antonia Beteva)
#Initial revision
#
|