#%TITLE% millitron196.mac
#%NAME%
# Millitron read through Wago or ICV196
#%CATEGORY% Positioning
#
#%DESCRIPTION%
# The millitron sensor can be read by cabling 16 digital inputs on
# a corresponding I/O card. This macro set allows to read a millitron
# as a counter in spec by using either an ICV196 or a wago module.
#%BR% %BR%
# The %B%millitron%B% output is a DB25 connector where pins are
# defined as follow:
#%PRE%
# pin 1 :
# pin 2 :
# pin 3 : overflow
# pin 4 : x1000
# pin 5 : ready for measurement = 1
# pin 6 : ready for measurement = 0
# pin 7 : digital point 0.01
# pin 8 : digital point 0.1
# pin 9 : 0v DC
# pin 10 : 0v DC
# pin 11 :
# pin 12 : sign 0->+ 1->-
# pin 13 : x800
# pin 14 : x400
# pin 15 : x100
# pin 16 : x80
# pin 17 : x40
# pin 18 : x20
# pin 19 : x10
# pin 20 : x8
# pin 21 : x8
# pin 22 : x4
# pin 23 : x2
# pin 24 : x1
# pin 25 :
#%PRE%
#%SETUP%
#%BR% %BR%
# %B%WAGO%B% :
#%BR% %BR%
# The macro counter method is used.
#%UL%
# %LI%The macro set %B%wagocore%B% has to be loaded in spec.
# %LI%Use spec config editor to setup a macro counter controller with
# prefix %B%millitron%B% .
# %LI% Set the ADDR field to the wago controller name. Ex.: wcid51d.
# %LI% Set the NUM field to a value holding as many counters
# as you will defined
# %LI% In the scaler configuration window add individiual counters
# on that controller (type MAC_CNT) and assign corresponding unit number.
# The channel number is arbitrary but it must be unique and be coherent
# with the NUM value of the controller
# %LI% Still in that window, set the cursor on top of the line of your
# counter. Hit the key "p" to add an extra parameter
# to the counter. This parameter must have its name set to "key" and
# the value corresponds to the wago key associated with the 16
# digital input values.
# %LI% Finally you can add an optional parameter with name "average" and
# value set to "1". The reading will then be averaged during counting.
# The default is set to 0 (= no average).
#%XUL%
#%BR% %BR%
# %B%ICV196%B% :
#%BR% %BR%
# The old pseudo counter method is used:
#%BR% %BR%
# Three counters must be defined in spec
# to get the readings. Use the macro %B%millitronsetup%B% (see usage
# below) to configure the card and assign the counters
#
# When using an ICV196 this macro set supposes that the millitron is
# cabled using 1 connector (J1, J2 or J3) by device. Each connector
# is clabed as follows :
#%PRE%
# bit 0 (mod 32) : x1
# bit 1 (mod 32) : x2
# bit 2 (mod 32) : x4
# bit 3 (mod 32) : x8
# bit 4 (mod 32) : x10
# bit 5 (mod 32) : x20
# bit 6 (mod 32) : x40
# bit 7 (mod 32) : x80
# bit 8 (mod 32) : x100
# bit 9 (mod 32) : x200
# bit 10 (mod 32) : x400
# bit 11 (mod 32) : x800
# bit 12 (mod 32) : x1000
# bit 13 (mod 32) : val x 0.1
# bit 14 (mod 32) : val x 0.01
# bit 15 (mod 32) : sign
# bit 16 (mod 32) : ready
# bit 17 (mod 32) : overflow
#%PRE%
# In the case of ICV196:
# up to 3 millitron devices can be read. There is on cable per device
# connected to a Icv196 connector.
# We associate a pseudo counter per each Icv196 connector even if there no
# millitron device connected.
#
#%END%
#%UU% wagokey
#%MDESC% Reads a millitron on a wago system. Prints the value on the screen
def milwagoread '{
print _milwagoread("$1")
}'
#%IU%
#%MDESC% Called by spec at config time.
def millitron_config(mne, type) '{
if (mne == "..") {
print "Configuring millitron on wago " millitron_ADDR
_dowagosetup ( millitron_ADDR )
}
}'
#%IU%
#%MDESC% Called by spec to read values
def millitron_cmd(mne, cmd, p1,p2) '{
# This macro will read as many times as possible during
# the counting time. But only the last one will be used.
# Not so efficient but users wanted the last value and not
# an average for example. This could added as an extra parameter
local key
if (mne == "..") return
key = counter_par( mne, "key")
if (cmd == "start_one") {
if ( counter_par(mne, "average") == 1 ) {
counter_par(mne, "accumulator",0, "add")
counter_par(mne, "nbcnts", 0, "add")
}
}
if (cmd == "counts") {
local _cnts accum nbcnts
_cnts = _milwagoread(key)
if ( counter_par(mne, "average") == 1 ) {
accum = counter_par(mne, "accumulator") + _cnts
nbcnts = counter_par(mne, "nbcnts") + 1
accum = counter_par(mne, "accumulator",accum)
nbcnts = counter_par(mne, "nbcnts",nbcnts)
S[mne] = accum / nbcnts
} else { # no average
S[mne] = _milwagoread(key)
}
}
}'
#%IU%
#%MDESC% Perform the actual reading on wago and convert values
def _milwagoread(key) '{
local i j n value
short array milwagovals[16]
# read
wago_readch( key, milwagovals )
# algorithm to convert to user readings
value = 0
n = 0
for (j = 0; j < 3; j++) {
for (i = 0; i < 4; i++) {
value += milwagovals[i + n] * pow(2,i) * exp10(j)
}
n += 4
}
value += 1000 * milwagovals[12]
if (milwagovals[13] == 1) {
value *= -1
}
if (milwagovals[14] == 0) {
value *= 0.01
} else if (milwagovals[15] == 0) {
value *= 0.1
}
return(value)
}'
#%IU%
#%MDESC%
def millitron_globals '{
global ESRF_ERR, ESRF_ERR_MSG
global MIL_DEV ;# Icv196 device name
global MIL_MNE[] ;# Counters names
global MIL_FACT[] ;# The weight of each bit (see above).
global MILLITRON_ON ;# As usual
global MIL_DBG ;# As usual
}'
#%UU% 0 | 1
#%MDESC% Activates / Inactivates debuggin (ICV196)
def millidbg '{
millitron_globals
MIL_DBG=($1?1:0)
}'
#%UU% icv196_device_name cntj1 cntj2 cntj3
#%MDESC% setup macro for ICV196
def millitronsetup '{
millitron_globals
if($# != 4) {
printf("millitronsetup usage: millitronsetup icv196_device_name cntj1 cntj2 cntj3\n")
millitronoff
exit
}
MIL_FACT[0] = 1 ; MIL_FACT[1] = 2 ; MIL_FACT[2] = 4 ; MIL_FACT[3] = 8
MIL_FACT[4] = 10 ; MIL_FACT[5] = 20 ; MIL_FACT[6] = 40 ; MIL_FACT[7] = 80
MIL_FACT[8] = 100 ; MIL_FACT[9] = 200 ; MIL_FACT[10] = 400 ; MIL_FACT[11] = 800
MIL_FACT[12] = 1000
MIL_DEV = "$1"
MIL_MNE[0] = "$2" ; MIL_MNE[1] = "$3" ; MIL_MNE[2] = "$4"
cdef("user_getcounts", "_millitronread()\n", "millitron")
}'
#%UU%
#%MDESC% Activates pseudo counters (for ICV196)
def millitronon '{
millitron_globals
local ii, mil_num
for (ii=0 ; ii<3 ; ii++) {
mil_num = cnt_num(MIL_MNE[ii])
counter_par(mil_num, "disable", 0)
}
MILLITRON_ON = 1
}'
#%UU%
#%MDESC% Inactivates pseudo counters (for ICV196)
def millitronoff '{
millitron_globals
local ii, mil_num
for (ii=0 ; ii<3 ; ii++) {
mil_num = cnt_num(MIL_MNE[ii])
counter_par(mil_num, "disable", 1)
}
MILLITRON_ON = 0
}'
#%IU%()
#%MDESC% For ICV196 / Reads J1, J2 and J3 and set the corresponding
# counters (32 channels per connector)
# If en error occurs (not_ready or overflow) the corresponding counter
# is set to -88888
# If the millittron is disabled (cmd millitronoff) the 3 counters are
# set to -99999
# The command DevMultipleChannelRead returns 12 values of 8 bits
# (12*8=96 channels).
def _millitronread() '{
millitron_globals
local ret, ii, mil_num[]
local short array rel_tab[11]
if(MIL_DBG) {p "Enter _millitronread()\n"}
if(!MILLITRON_ON) {
for (ii=0 ; ii<3 ; ii++) {
if(cnt_num(MIL_MNE[ii]) != -1) {S[cnt_num(MIL_MNE[ii])] = -99999}
}
if(MIL_DBG) {p "millitronoff activated"}
return(0)
}
ESRF_ERR=-1
ret = esrf_io(MIL_DEV, "DevMultipleChannelRead", rel_tab)
if(ESRF_ERR!=0) {
printf("Error reading Icv196: %s\n",ESRF_ERR_MSG)
return(0)
}
for (ii=0 ; ii<3 ; ii++) {
if ((mil_num[ii] = cnt_num(MIL_MNE[ii])) != -1) {
if (_millitron_ready(rel_tab, ii)) {
if (!_millitron_overflow(rel_tab, ii)) {
S[mil_num[ii]] = _millitron_getval(rel_tab, ii)
} else {
printf("millitron %s overflow \n",MIL_MNE[ii])
S[mil_num[ii]] = -88888
}
} else {
print "millitron ",MIL_MNE[ii]," not ready"
S[mil_num[ii]] = -88888
}
}
}
}'
#%IU%(tabval,conn)
#%MDESC% Returns the decimal value of one millitron (one connector) (ICV196 only)
def _millitron_getval(tabval,conn) '{
millitron_globals
local ii val
if(MIL_DBG) {printf("Enter _millitron_getval(tabval,%d)\n",conn)}
for (ii=0,val=0 ; ii<16 ; ii++) {
if (ii<13) {
val = val + _millitron_getbit(tabval, ii, conn) * MIL_FACT[ii]
} else if ((ii == 13) && (!_millitron_getbit(tabval, ii, conn))) {
val = val * 0.1
} else if ((ii == 14) && (!_millitron_getbit(tabval, ii, conn))) {
val = val * 0.01
} else if ((ii == 15) && (!_millitron_getbit(tabval, ii, conn))) {
val = -val
}
}
if(MIL_DBG) {printf("val=%d\n",val)}
return(val)
}'
#%IU%(tabval,conn)
#%MDESC%
def _millitron_ready(tabval,conn) '{
millitron_globals
return(_millitron_getbit(tabval, 16, conn))
}'
#%IU%(tabval,conn)
#%MDESC%
def _millitron_overflow(tabval,conn) '{
millitron_globals
return(!_millitron_getbit(tabval, 17, conn))
}'
#%IU%(tabval,bit,conn)
#%MDESC% returns the value of one bit
def _millitron_getbit(tabval,bit,conn) '{
millitron_globals
local shift ind
shift = bit%8
ind = int(bit/8) + 4*conn
return(~(tabval[ind]>>shift) & 0x01)
}'
#%UU% Connector_number [0-2]
#%MDESC% (ICV196 only)
def millprint '{
millitron_globals
local ret, str
local short array rel_tab[11]
ESRF_ERR=-1
ret = esrf_io(MIL_DEV, "DevMultipleChannelRead", rel_tab)
if(ESRF_ERR!=0) {
printf("Error reading Icv196: %s\n",ESRF_ERR_MSG)
exit
}
printf(" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 29 20 21 22 23 \n")
printf(" 1 2 4 8 10 20 40 80 100 200 400 800 1000 0.1 0.01 sign READ OVR \n")
printf("------------------------------------------------------------------------------------------------------------------------\n")
for (str="",ii=0 ; ii<24 ; ii++) {
str = sprintf("%s%4d ", str, _millitron_getbit(rel_tab, ii))
}
printf("%s\n", str)
printf("val = %g\n", _millitron_getval(rel_tab, $1))
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% Original: G. Berruyer . Commented and generalized: G. Pepellin / V.Rey for the wago version
#%TOC%
|