## # @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 IP]:[sct PORT] WARNING AUTO OFF IS ENABLED" } if {$stateArr(LOBAT)} { broadcast "PROTEK608: 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 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 } } msg ] { return -code error "[info level 0]: $msg" } return $nextState } ## # @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 IP PORT {scale 1.0} {offset 0.0} {interval 0.5} {cbFunc "return idle"}} { set sctName "sct_$name" set sobjName "$name" set soState "so_state_$name" puts "MakeSICSObj $sobjName SCT_OBJECT" MakeSICSObj $soState SCT_OBJECT MakeSICSObj $sobjName SCT_OBJECT user float 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} { makesctcontroller $sctName protek608 $IP:$PORT hsetprop /sics/$soState/state IP $IP hsetprop /sics/$soState/state PORT $PORT $sctName poll /sics/$soState/state $interval $sctName poll /sics/$sobjName $interval } return /sics/$sobjName }