########################################################################################################################### # # file Proptocols between SICS and Embedded I/O device in Kookoburra # # This is a driver for SICS to communicate with the embedded I/O box on Kookoburra # # Author: Jing Chen (jgn@ansto.gov.au) June 2013 # # The driver can be installed with the following command, # # ::scobj::emHV::mkEmHV { # name "emHV" # IP localhost # PORT 55010 # tuning 1 # interval 1 # ############################################################################################################################## proc debug_log {args} { set d1 [clock format [clock seconds] -format %d%h%Y] set fd [open "../log/pressure$d1.log" a] puts $fd "[clock format [clock seconds] -format "%D %T "] [string trim $args "{}"]" close $fd } namespace eval ::scobj::emHV { } proc ::scobj::emHV::getEmStatusFunc {chan} { if {[hpropexists [sct] geterror]} { hdelprop [sct] geterror } set comm "get hvstatus$chan" sct send $comm return rdEmStatus$chan } proc ::scobj::emHV::rdEmStatusFunc {basePath chan} { set replyStr [sct result] if {[string first "ASCERR" $replyStr] != -1} { sct geterror $replyStr return -code error "Error in emHV Response: $replyStr" } elseif {[string length $replyStr] < 1} { return -code error "Error in emHV: no message returned from device" } else { hset $basePath/hv$chan [lindex [split $replyStr ","] 3] hset $basePath/rate$chan [lindex [split $replyStr ","] 5] hset $basePath/uA$chan [lindex [split $replyStr ","] 7] hset $basePath/status$chan [lindex [split $replyStr ","] 9] } if {$chan == 1} { return getEmStatus2 } else { return idle } } proc ::scobj::emHV::setCounterFunc {basePath} { set countermode [sct target] clientput "$countermode" sct send "$countermode\r\n" return ckCounterState } proc ::scobj::emHV::ckCounterStateFunc {basePath} { set replyStr [sct result] if {[string first "ASCERR" $replyStr] != -1} { sct geterror $replyStr return -code error "Error in emHV Response: $replyStr" } elseif {[string first "Invalid Cmd" $replyStr] != -1} { sct geterror $replyStr return -code error "Error in emHV Response: $replyStr" } elseif {[string length $replyStr] < 1} { return -code error "Error in emHV: no message returned from device" } else { hset $basePath/count1 [lindex [split $replyStr ","] 5] hset $basePath/count2 [lindex [split $replyStr ","] 7] hset $basePath/countstate [lindex [split $replyStr ","] 3] if {[hval $basePath/countstate] == "stopped"} { clientput "Counter stops" return idle } elseif {[hval $basePath/countstate] == "paused"} { clientput "Counter pause" return idle } else { clientput "Counter progressing ..." set comm "get counter\r\n" sct send $comm return ckCounterState } } } proc ::scobj::emHV::setPointFunc {basePath chan} { set vol [sct target] hset $basePath/target$chan $vol sct send "set hv$chan=$vol\r\n" return ckVolStatus$chan } proc ::scobj::emHV::ckVolStatusFunc {basePath chan} { set replyStr [sct result] if {[string first "ASCERR" $replyStr] != -1} { sct geterror $replyStr return -code error "Error in emHV Response: $replyStr" } elseif {[string length $replyStr] < 1} { return -code error "Error in emHV: no message returned from device" } else { hset $basePath/hv$chan [lindex [split $replyStr ","] 3] hset $basePath/rate$chan [lindex [split $replyStr ","] 5] hset $basePath/uA$chan [lindex [split $replyStr ","] 7] hset $basePath/status$chan [lindex [split $replyStr ","] 9] } if {[hval $basePath/hv$chan] == [hval $basePath/target$chan]} { return idle } else { if {[hval $basePath/status$chan] != "OK"} { clientput "Voltage channel $chan is busy, wait ..." sct send "get hvstatus$chan\r\n" return ckVolStatus$chan } else { clientput "Start ramping voltage$chan to target [hval $basePath/target$chan] ..." sct send "set poweruphv$chan\r\n" return rampVol$chan } } } proc ::scobj::emHV::rampVolFunc {basePath chan} { set replyStr [sct result] if {[string first "ASCERR" $replyStr] != -1} { sct geterror $replyStr return -code error "Error in emHV Response: $replyStr" } elseif {[string length $replyStr] < 1} { return -code error "Error in emHV: no message returned from device" } else { hset $basePath/hv$chan [lindex [split $replyStr ","] 3] hset $basePath/rate$chan [lindex [split $replyStr ","] 5] hset $basePath/uA$chan [lindex [split $replyStr ","] 7] hset $basePath/status$chan [lindex [split $replyStr ","] 9] if {[hval $basePath/status$chan] == "OK"} { clientput "Finished ramping voltage$chan to [hval $basePath/target$chan]" return idle } else { clientput "Ramping voltage$chan to [hval $basePath/hv$chan] ..." sct send "get hvstatus$chan\r\n" return rampVol$chan } } } ## # @brief Make a emHV Controller # # @param argList, {name "emHV" IP localhost PORT 65123 tuning 1 interval 1} # # name: name of emHV controller object # IP: IP address of RF generator moxa box # PORT: Port number assigned to the generator on the moxa-box # tuning: boolean, set tuning=1 to allow instrument scientists to set the axe positions # interval: polling and ramping interval in seconds. proc ::scobj::emHV::mkEmHV {argList} { # Generate parameter array from the argument list foreach {k v} $argList { set KEY [string toupper $k] set pa($KEY) $v } MakeSICSObj $pa(NAME) SCT_OBJECT sicslist setatt $pa(NAME) klass environment sicslist setatt $pa(NAME) long_name $pa(NAME) sicslist setatt $pa(NAME) privilege spy set scobj_hpath /sics/$pa(NAME) makesctcontroller sct_$pa(NAME) std $pa(IP):$pa(PORT) # High Voltage Component hfactory $scobj_hpath/hv1 plain user int hfactory $scobj_hpath/rate1 plain user int hfactory $scobj_hpath/uA1 plain user int hfactory $scobj_hpath/status1 plain user text hfactory $scobj_hpath/target1 plain user int hfactory $scobj_hpath/hv2 plain user int hfactory $scobj_hpath/rate2 plain user int hfactory $scobj_hpath/uA2 plain user int hfactory $scobj_hpath/status2 plain user text hfactory $scobj_hpath/target2 plain user int # Counter Component hfactory $scobj_hpath/count1 plain user int hfactory $scobj_hpath/count2 plain user int hfactory $scobj_hpath/countstate plain user text hset $scobj_hpath/hv1 0 hset $scobj_hpath/rate1 0 hset $scobj_hpath/uA1 0 hset $scobj_hpath/status1 UNKNOWN hset $scobj_hpath/target1 0 hset $scobj_hpath/hv2 0 hset $scobj_hpath/rate2 0 hset $scobj_hpath/uA2 0 hset $scobj_hpath/status2 UNKNOWN hset $scobj_hpath/target2 0 hset $scobj_hpath/count1 0 hset $scobj_hpath/count2 0 hset $scobj_hpath/countstate UNKNOWN hsetprop $scobj_hpath read ::scobj::emHV::getEmStatusFunc 1 hsetprop $scobj_hpath rdEmStatus1 ::scobj::emHV::rdEmStatusFunc $scobj_hpath 1 hsetprop $scobj_hpath getEmStatus2 ::scobj::emHV::getEmStatusFunc 2 hsetprop $scobj_hpath rdEmStatus2 ::scobj::emHV::rdEmStatusFunc $scobj_hpath 2 if {[SplitReply [environment_simulation]]=="false"} { sct_emHV poll $scobj_hpath $pa(INTERVAL) #sct_emHV queue $scobj_hpath progress read } hfactory $scobj_hpath/setpoint1 plain user int hsetprop $scobj_hpath/setpoint1 write ::scobj::emHV::setPointFunc $scobj_hpath 1 hsetprop $scobj_hpath/setpoint1 ckVolStatus1 ::scobj::emHV::ckVolStatusFunc $scobj_hpath 1 hsetprop $scobj_hpath/setpoint1 rampVol1 ::scobj::emHV::rampVolFunc $scobj_hpath 1 hfactory $scobj_hpath/setpoint2 plain user int hsetprop $scobj_hpath/setpoint2 write ::scobj::emHV::setPointFunc $scobj_hpath 2 hsetprop $scobj_hpath/setpoint2 ckVolStatus2 ::scobj::emHV::ckVolStatusFunc $scobj_hpath 2 hsetprop $scobj_hpath/setpoint2 rampVol2 ::scobj::emHV::rampVolFunc $scobj_hpath 2 hfactory $scobj_hpath/counter plain user text hsetprop $scobj_hpath/counter write ::scobj::emHV::setCounterFunc $scobj_hpath hsetprop $scobj_hpath/counter ckCounterState ::scobj::emHV::ckCounterStateFunc $scobj_hpath if {[SplitReply [environment_simulation]]=="false"} { sct_emHV write $scobj_hpath/setpoint1 sct_emHV write $scobj_hpath/setpoint2 sct_emHV write $scobj_hpath/counter } # add HDB structure here ::scobj::hinitprops $pa(NAME) ::scobj::set_required_props $scobj_hpath hsetprop $scobj_hpath klass environment hsetprop $scobj_hpath type part hsetprop $scobj_hpath privilege spy hsetprop $scobj_hpath control true hsetprop $scobj_hpath data true foreach {hPath klass control data priv type} { ch1 NXsensor true true user NXsensor ch2 NXsensor true true user NXsensor } { hsetprop $scobj_hpath/$hPath klass $klass hsetprop $scobj_hpath/$hPath privilege $priv hsetprop $scobj_hpath/$hPath type $type hsetprop $scobj_hpath/$hPath control $control hsetprop $scobj_hpath/$hPath data $data } foreach {hpath klass control data nxsave mutable priv alias} { hv1 sensor true true true true user emHV-hv1 rate1 sensor true true true true user emHV-rate1 uA1 sensor true true true true user emHV-uA1 status1 sensor true true true true user emHV-status1 hv2 sensor true true true true user emHV-hv2 rate2 sensor true true true true user emHV-rate2 uA2 sensor true true true true user emHV-uA2 status2 sensor true true true true user emHV-status2 count1 sensor true true true true user emHV-count1 count2 sensor true true true true user emHV-count2 countstate sensor true true true true user emHV-countstate } { hsetprop $scobj_hpath/$hpath klass $klass hsetprop $scobj_hpath/$hpath privilege $priv hsetprop $scobj_hpath/$hpath control $control hsetprop $scobj_hpath/$hpath data $data hsetprop $scobj_hpath/$hpath nxsave $nxsave hsetprop $scobj_hpath/$hpath mutable $mutable hsetprop $scobj_hpath/$hpath nxalias $alias hsetprop $scobj_hpath/$hpath sdsinfo ::nexus::scobj::sdsinfo } } proc emHV1 {{vol ""} args} { if {$vol == ""} { hval /sample/emHV/hv1 } else { hset /sample/emHV/setpoint1 $vol } } proc emHV2 {{vol ""} args} { if {$vol == ""} { hval /sample/emHV/hv2 } else { hset /sample/emHV/setpoint2 $vol #set cmd "set hv2=$vol\r\n" #sct_emHV transact $cmd } } proc hvramp1 {amp} { set cmd "set hvramp1=$amp\r\n" sct_emHV transact $cmd } proc hvramp2 {amp} { set cmd "set hvramp2=$amp\r\n" sct_emHV transact $cmd } proc poweruphv1 {} { set cmd "set poweruphv1\r\n" sct_emHV transact $cmd } proc poweruphv2 {} { set cmd "set poweruphv2\r\n" sct_emHV transact $cmd } proc powerdownhv1 {} { set cmd "set powerdownhv1\r\n" sct_emHV transact $cmd } proc powerdownhv2 {} { set cmd "set powerdownhv2\r\n" sct_emHV transact $cmd } proc bmthreshold {{vol ""} args} { if {$vol == ""} { set cmd "get bmthreshold\r\n" } else { set cmd "set bmthreshold=$vol\r\n" } sct_emHV transact $cmd } proc setcounter {args} { set cmd "set counter" foreach arg $args { lappend cmd $arg } hset /sample/emHV/counter $cmd } publish emHV1 user publish emHV2 user publish hvramp1 user publish hvramp2 user publish poweruphv1 user publish poweruphv2 user publish powerdownhv1 user publish powerdownhv2 user publish bmthreshold user publish setcounter user # Main process call to create the driver #IP 137.157.205.22 #IP for SIS PLC 137.157.205.21 30000 ::scobj::emHV::mkEmHV { name "emHV" IP 137.157.205.22 PORT 30000 tuning 1 interval 1 }