#%TITLE% MAXEENC.MAC
#%NAME%
# Using encoder readings from a maxe server as pseudo counters
#
#%CATEGORY% Positioning
#
#%DESCRIPTION%
# Encoders which are configured can be used as counters. This allows
# you to do scans to measure encoder ratio ( specially useful if
# it is not linear). The encoder readings will also be written to the
# scanfile to allow off-line analysis. %BR%.
# The encoder will be read during counting and the result will be
# the average of all these readings.
# You have to define a counter with controller set to NONE and call
# encsetup . If you do not want to use the encoder pseudo counter any
# more, just delete it with specs configuration editor.
#
#%EXAMPLE%
#%DL%
#%DT% encsetup inch "ID18/spec_maxe/1" 1 %DD%
# This sets up the inch pseudo counter to read from Maxe device
# ID18/spec_maxe/1 , channel 1. This is usually be done in the
# idxxxsetup.mac
#%XDL%
#%SETUP%
# The resource files of the Maxe server have to be configured for
# encoders.
#%END%
#
# encsetup [counter-mne device channel] [counter-mne device channel] ...
#%UU% [counter-mne device channel] [counter-mne device channel] ...
#%MDESC%
# This macro defines the pseudo counters. The counter will read
# the encoder value from mxe device <device> channel <channel>.
def encsetup '
{
global ENC_DEV ENC_CHA ENC_NO ENC_MNE ENC_AVER ENC_NOREADS
local _args
encoff
if ($#) {
ENC_NO = split("$*",_args) /3
for (ii=0;ii<ENC_NO;ii++) {
ENC_MNE[ii] = _args[ii*3]
ENC_DEV[ii] = _args[ii*3+1]
ENC_CHA[ii] = _args[ii*3+2]
}
} else {
ENC_NO = getval("Number of encoders to define as counters",ENC_NO)
for (jj=0;jj<ENC_NO;jj++) {
ENC_MNE[jj] = getval(sprintf("Counter mnemonic for %d. encoder",\
jj+1),ENC_MNE[jj])
ENC_DEV[jj] = getval(sprintf("Maxe device name for %d. encoder",\
jj+1),ENC_DEV[jj])
ENC_CHA[jj] = getval(sprintf("Maxe channel for %d. encoder",\
jj+1),ENC_CHA[jj])
}
}
encon
setup_tail("enc")
}'
#%UU% counter-mne value
#%MDESC%
# Resets the (incremental) encoder counted in %B%counter-mne%B% to %B%value%B%.
# Similar to %B%set\ motor-mne\ value%B%.
#
def encset '{
local mne found old stepsize new
mne = "$1"
for (found=0,i = 0; i < ENC_NO; i++) {
if (ENC_MNE[i] == mne && cnt_num(ENC_MNE[i]) != -1) {
stepsize = counter_par(cnt_num(ENC_MNE[i]),"scale")
old = esrf_io(ENC_DEV[i],"DevReadEncPos",ENC_CHA[i]) * stepsize
esrf_io(ENC_DEV[i],"DevLoadEncPos",ENC_CHA[i], ($2) / stepsize)
new = esrf_io(ENC_DEV[i],"DevReadEncPos",ENC_CHA[i]) * stepsize
comment "Encoder \'%s\' reset from to %g to %g" "mne,old,new"
found = 1
}
}
if (!found)
print "Counter $1 is not a valid Maxe encoder mnemonic!"
}'
def encon '{
local jj i
global ENC_STATE
# define the pseudo counters
for (jj=0;jj<ENC_NO;jj++) {
local pstring
pstring = sprintf ("%s enc_precount none enc_getcounts none none %s %s",\
ENC_MNE[jj],ENC_DEV[jj],ENC_CHA[jj])
cpseudosdef pstring
cdef("user_pollcounts",sprintf("enc_getcounts %s %s %d ;"\
,ENC_MNE[jj],ENC_DEV[jj],ENC_CHA[jj]),ENC_MNE[jj],0x02)
}
for (i=0; i < ENC_NO; i++) {
if (cnt_num(ENC_MNE[i]) == -1)
printf("You have to define counter with mnemonic %s in the config file\n",\
ENC_MNE[i])
}
ENCSTATE = 1
}'
def encoff '{
local jj
global ENCSTATE
for (jj=0;jj<ENC_NO;jj++) {
cdef("","",ENC_MNE[jj],"delete")
}
ENCSTATE = 0
}'
def encunsetup '{
local i
for (i=0; i < ENC_NO; i++) {
if (cnt_num(ENC_MNE[i]) != -1)
printf("You can delete counter with mnemonic %s from the config file\n",\
ENC_MNE[i])
}
encoff
}'
def encbody (how) '{
if (how == 1) {
if (ENCSTATE) {
encoff
} else {
encon
}
} else if (how == 2) {
encsetup
}
return ENCSTATE ? "In use" : "Not used"
}'
#%UU% [enc-mne sigma-mne first-mne last-mne]
#%MDESC%
# Switches on test mode where not only the average value for an
# encoder reading is calculated but also the sigma.
# (sigma = sqrt(sum(y-avarage)**2/ N)).
# sigma should not depend on the number of readings.
# The encoder mne specifies the encoder for which the sigma
# calculation has to be done. The sigma-mne is pseudo counter
# where the result has to be written to. (Can be empty - in this case
# there will be no sigma calculation but the values will still be stored
# in the ENC_TESTGRP
def encteston '
global ENC_TESTMNE ENC_TESTSIGMA ENC_TESTGRP ENC_TESTT ENC_TESTL ENC_TESTF
ENC_TESTGRP = 62
if ($#) {
ENC_TESTMNE = $1
ENC_TESTSIGMA = $2
ENC_TESTF = $3
ENC_TESTL = $4
} else {
local defa
if ((ENC_TESTMNE <= 0) || ((defa= cnt_mne(ENC_TESTMNE)) == -1))
defa = ""
ENC_TESTMNE = cnt_num(getval("Enc counter mne to test",defa))
if ((ENC_TESTSIGMA <= 0) || ((defa= cnt_mne(ENC_TESTSIGMA)) == -1))
defa = ""
ENC_TESTSIGMA = cnt_num(getval("Counter mne for sigma",defa))
if ((ENC_TESTF <= 0) || ((defa= cnt_mne(ENC_TESTF)) == -1))
defa = ""
ENC_TESTF = cnt_num(getval("Counter mne for first reading",defa))
if ((ENC_TESTL <= 0) || ((defa= cnt_mne(ENC_TESTL)) == -1))
defa = ""
ENC_TESTL = cnt_num(getval("Counter mne for last reading",defa))
}
'
#%UU%
#%MDESC% Switches off test mode
def enctestoff '
data_grp(ENC_TESTGRP,0,0)
unglobal ENC_TESTMNE ENC_TESTSIGMA ENC_TESTGRP ENC_TESTT ENC_TESTF ENC_TESTL
'
#%IU% <counter-mne> <device> <channel>
#%MDESC%
# Resets internal registers
def enc_precount '
ENC_AVER[$1] = 0 ; ENC_NOREADS[$1]=0
# From here on for sigma tests
if (ENC_TESTMNE == $1) {
data_grp(ENC_TESTGRP,10000,2)
ENC_TESTT = time()
}
'
#%IU% <counter-mne> <device> <channel>
#%MDESC%
# The actual reading routine
def enc_getcounts '
{
local val
ESRF_ERR = -1
val = esrf_io("$2","DevReadEncPos",$3)
if (!ESRF_ERR) {
ENC_AVER[$1] += val
ENC_NOREADS[$1]++;
}
S[$1] = counter_par($1,"scale")*\
ENC_AVER[$1] / ((ENC_NOREADS[$1]==0)? 1 : ENC_NOREADS[$1])
# From here on for sigma tests
if (!ESRF_ERR && (ENC_TESTMNE == $1)) {
local av
data_nput(ENC_TESTGRP,ENC_NOREADS[$1]-1,time()-ENC_TESTT,val)
if ((ENC_TESTSIGMA > 0) && ENC_NOREADS[$1]) {
av = ENC_AVER[$1] / ENC_NOREADS[$1]
data_uop (ENC_TESTGRP,1,ENC_TESTGRP,1,"sub",av)
S[ENC_TESTSIGMA] = sqrt (data_anal(ENC_TESTGRP,0,0,1,1,"sumsq") / \
ENC_NOREADS[$1])
data_uop (ENC_TESTGRP,1,ENC_TESTGRP,1,"add",av)
if (ENC_TESTF>0)
S[ENC_TESTF] = data_get(ENC_TESTGRP,0,1)
if (ENC_TESTL>0)
S[ENC_TESTL] = val
}
}
}
'
#%MACROS%
#%IMACROS%
#%ATTENTION%
#%UL%
# %LI% There is no delete macro for the moment
# %LI% Reading is done for each encoder separately. These macros have not
# been written with fast execution speed in mind and should therefore
# only be used during testing.
# %XUL%
#%DEPENDENCIES%
# The file maxeenc.mac has to be read in !done by: startup script
# (this file needs: cpseudo.mac stchanges.mac)
#%AUTHOR%
# MAXEENC.MAC - JK 3.94
#%TOC%
|