Files
sics/site_ansto/instrument/config/environment/sct_protek_common.tcl

169 lines
5.2 KiB
Tcl

##
# @file sct_protek_common.tcl
# @brief Gets display state from Protek 608 multimeters.
#
# Author: Ferdi Franceschini (ffr@ansto.gov.au)
## MULTIMETER STATE FIELDS AND VALUES
###### MODES
# AUTOOFF:1/0 PULSE:1/0 MAX:1/0 PLUSPEAK:1/0 REL:1/0 RECALL:1/0 GO/NG:1/0 MINUSPER:1/0
# RS232C:1/0 PLUS:1/0 MINUS:1/0 MIN:1/0 MINUSPEAK:1/0 AVG:1/0 STORE:1/0 REF:1/0 PLUSPER:1/0
# LOBAT:1/0
###### MAIN DISPLAY
# AC1:1/0 SIGN1:1/0 DC1:1/0 PW1:1/0
# MD5:np MD4:np MD3:np MD2:np MD1:n
# M1:1/0 k1:1/0 OHM1:1/0
# u1:1/0 Hz1:1/0
# m1:1/0 V1:1/0 A1:1/0
# n1:1/0 S1:1/0 F1:1/0
# DEGC1:1/0 s1:1/0
# DEGF1:1/0
###### BAR GRAPH
# B16K:1/0 B8K:1/0 B4K:1/0 B2K:1/0 B1K:1/0
# B512:1/0 B256:1/0 B128:1/0 B64:1/0 B32:1/0
# B16:1/0 B8:1/0 B4:1/0 B2:1/0 B1:1/0 B0:1/0
###### SUB DISPLAY
# RANGE2:1/0 HOLD2:1/0 DUTY2:1/0
# CONT2:1/0 ZD2:1/0
# AC2:1/0 SIGN2:1/0 DC2:1/0
# SD5:np SD4:np SD3:np SD2:np SD1:n
# PERCENT2:1/0 dBm2:1/0
# m2:1/0 V2:1/0 A2:1/0 DEGK2:1/0
# G2:1/0 M2:1/0 k2:1/0 OHM2:1/0 Hz2:1/0
# ROTSWITCH:[0-8]
### The return values for nine bytes is undocumented,
### they are labelled as X1 to X9
# X[1-9]:?
##
# @brief Sends a state report request to the protek script context protocol handler.
proc rqStateRep {} {
sct send "STATE"
return rdStateRep
}
##
# @brief Processes state report from the protek script context protocol handler.
proc rdStateRep {} {
set stateRep [sct result]
if {[string match "ASCERR:*" $stateRep]} {
sct geterror $stateRep
# Setting oldval forces update and clears geterror on next call
sct oldval "UNKNOWN"
return idle
}
array set stateArr [split $stateRep "|:"]
if {$stateArr(AUTOOFF)} {
broadcast "PROTEK608:[sct] WARNING AUTO OFF IS ENABLED"
}
if {$stateArr(LOBAT)} {
broadcast "PROTEK608:[sct] LOW BATTERY WARNING"
}
if {$stateRep != [sct oldval]} {
sct update $stateRep
sct oldval $stateRep
}
return idle
}
proc rqVal {nextState} {
return $nextState
}
proc ProtekMainDisplay {protek nextState} {
if [catch {
set stateRep [hval $protek/state]
set MDpath [sct]
set parname [file tail $MDpath]
set scale [hval $MDpath/scale]
set offset [hval $MDpath/offset]
array set SA [split $stateRep "|:"]
if {$SA(SIGN1)} {
set sign1 "-"
} else {
set sign1 ""
}
set MDISP "$sign1$SA(MD5)$SA(MD4)$SA(MD3)$SA(MD2)$SA(MD1)"
if {[string is double $MDISP] == 0} {
error "Non-numeric reading ($MDISP) from Protek main display"
}
set MDISP [expr {$scale * $MDISP + $offset}]
set oldval [sct oldval]
if {$MDISP != $oldval} {
sct update $MDISP
sct oldval $MDISP
protek_debug_log $parname $MDISP
}
} msg ] {
return -code error "[info level 0]: $msg"
}
return $nextState
}
proc protek_debug_log {name args} {
set fd [open "/usr/local/sics/data/protek_$name.csv" a]
puts $fd "[clock format [clock seconds] -format "%d/%m/%Y, %T"], $args"
close $fd
}
##
# @brief Makes a state monitor object for the protek multimeter
#
# @param name, name of object which reports main display reading
# @param IP, IP address of protek moxa box
# @param PORT, port number for protek on moxa box
# @param scale, scales reading to physical units
# @param offset, offset for main display reading
# @param interval, polling interval in seconds (optional, default = 0.5seconds)
# @param cbFunc, this function will be called after the voltage reading has been updated
# NOTE: If the interval is negative then the multimeter will be polled on every cycle of
# the SICS task loop.
proc MakeProtek {name sctName {scale 1.0} {offset 0.0} {interval 0.5} {cbFunc "return idle"}} {
set catch_status [ catch {
set sctName "sct_$name"
set sobjName "$name"
set soState "so_state_$name"
clientput "MakeSICSObj $sobjName SCT_OBJECT"
MakeSICSObj $soState SCT_OBJECT
sicslist setatt $sobjName long_name $sobjName
hfactory /sics/$soState/state plain user text
hsetprop /sics/$soState/state read rqStateRep
hsetprop /sics/$soState/state rdStateRep rdStateRep
hsetprop /sics/$soState/state oldval "UNKNOWN"
hsetprop /sics/$sobjName read rqVal "reportVal"
hsetprop /sics/$sobjName reportVal ProtekMainDisplay /sics/$soState callBack
hsetprop /sics/$sobjName callBack $cbFunc
hfactory /sics/$sobjName/scale plain user float
hset /sics/$sobjName/scale $scale
hfactory /sics/$sobjName/offset plain user float
hset /sics/$sobjName/offset $offset
hsetprop /sics/$sobjName oldval "UNKNOWN"
sicslist setatt $sobjName klass sample
::scobj::hinitprops $sobjName
sicslist setatt $sobjName long_name $name
if {[SplitReply [environment_simulation]] == false} {
$sctName poll /sics/$soState/state $interval
$sctName poll /sics/$sobjName $interval
}
} catch_message ] {
handle_exception ${catch_status} ${catch_message}
}
return /sics/$sobjName
}
# proc add_protekmm {name IP PORT CTYPE CID {scale 1.0} {offset 0.0} {interval 0.5} {cbFunc "return idle"}} {
# set catch_status [ catch {
# MakeProtek $name $IP $PORT $scale $offset $interval $cbFunc
# hsetprop /sics/$name permlink data_set ${CTYPE}${CID}S1
# } catch_message ] {
# handle_exception ${catch_status} ${catch_message}
# }
# }