Files
sics/site_ansto/instrument/config/hmm/sct_orhvps_common.tcl
2014-05-16 17:23:58 +10:00

374 lines
9.3 KiB
Tcl
Executable File

##
# @file Implements control for the Ordela high voltage power supply using the odrhvps protocol handler.
#
# This controller implements voltage ramping and always reads the current value before
# attempting to set the new voltage.
MakeSicsObj so_dhv1 SCT_OBJECT
namespace eval ::scobj::dethvps { }
##
# @brief Requests a value using the given command.
#
# @param nextSubState, Specifies the state which will handle the reply.
# @param cmd, The query command.
proc ::scobj::dethvps::rqValue {nextSubState cmd} {
set catch_status [ catch {
sct send $cmd
return $nextSubState
} msg ]
handle_exception $catch_status $msg
}
##
# @brief Processes replies from the voltage controller and controls the
# transition between the ramping superstates.
#
# @param vPath, Hdb node path for the voltage.
proc ::scobj::dethvps::rdValue {vPath} {
variable RAMPIDLE
variable RAMPSTOP
variable RAMPSTART
variable RAMPBUSY
variable MAXPOTVAL
variable RAMPINTEREST
set catch_status [ catch {
set data [sct result]
set currSuperState [sct ramping]
switch -glob -- $data {
"ASCERR:*" {
sct geterror $data
if {$currSuperState == $RAMPBUSY || $currSuperState == $RAMPSTART} {
broadcast "DHVERROR: $data, dhv1 stopped ramping detector voltage"
statemon stop dhv1
} else {
# broadcast "DHVERROR: $data"
}
if {$currSuperState != $RAMPIDLE} {
sct ramping $RAMPIDLE
}
return idle
}
default {
if {$data != [sct oldval]} {
sct geterror ""
sct oldval $data
sct update $data
set voltage [expr [sct max] * $data / double($MAXPOTVAL) ]
hset $vPath $voltage
if {$RAMPINTEREST} {
broadcast "dhv1 = $voltage"
}
sct utime readtime
}
}
}
switch $currSuperState [ subst {
$RAMPSTART {
sct ramping $RAMPBUSY
statemon start dhv1
return ramp
}
$RAMPBUSY {
return ramp
}
$RAMPSTOP {
sct ramping $RAMPIDLE
statemon stop dhv1
return idle
}
$RAMPIDLE {
return idle
}
default {
broadcast "DHVERROR: dhv1([info level 0]) sct ramping = [sct ramping], STOPPING"
sct ramping $RAMPIDLE
statemon stop dhv1
return idle
}
} ]
} msg ]
handle_exception $catch_status $msg
}
##
# @brief Checks the target voltage and sets the ramping superstate and ramp direction.
proc ::scobj::dethvps::setValue {nextSubState} {
variable RAMPIDLE
variable RAMPSTOP
variable RAMPSTART
variable RAMPBUSY
set catch_status [ catch {
set par [sct target]
set maxV [sct max]
if {$par < 0 || $par > $maxV} {
broadcast "DHVERROR: dhv1 target must be between 0 and $maxV"
sct seterror "DHVERROR: dhv1 target must be between 0 and $maxV"
return idle
}
set currSuperState [sct ramping]
set oldval [sct oldval]
if {$par == $oldval} {
if {$currSuperState == $RAMPBUSY || $currSuperState == $RAMPSTART} {
sct ramping $RAMPSTOP
}
return idle
}
if {$par < $oldval} {
sct rampstep -1
} else {
sct rampstep 1
}
if {$currSuperState != $RAMPBUSY && $currSuperState != $RAMPSTART} {
sct ramping $RAMPSTART
}
return $nextSubState
} msg ]
handle_exception $catch_status $msg
}
##
# @brief Checks that a command has been acknowledged
proc ::scobj::dethvps::getACK {} {
variable RAMPIDLE
variable RAMPSTOP
variable RAMPSTART
variable RAMPBUSY
set catch_status [ catch {
set currSuperState [sct ramping]
set data [sct result]
switch -glob $data {
"ASCERR:*" {
sct seterror $data
if {$currSuperState == $RAMPBUSY || $currSuperState == $RAMPSTART} {
broadcast "DHVERROR: $data, dhv1 stopped ramping detector voltage"
statemon stop dhv1
} else {
# broadcast "DHVERROR: $data"
}
if {$currSuperState != $RAMPSTOP} {
sct ramping $RAMPSTOP
}
return idle
}
ACK {
return idle
}
default {
return idle
}
}
} msg ]
handle_exception $catch_status $msg
}
##
# @brief Increments or decrements voltage until target has been reached
#
# @param cmd, The set voltage command
proc ::scobj::dethvps::ramping {cmd} {
variable RAMPIDLE
variable RAMPSTOP
variable RAMPSTART
variable RAMPBUSY
variable MINRAMPINTERVAL
set catch_status [ catch {
set rampstep [sct rampstep]
set target [sct target]
set oldval [sct oldval]
switch -- $rampstep {
1 {
if {$oldval >= $target} {
sct ramping $RAMPSTOP
return idle
}
}
-1 {
if {$oldval <= $target} {
sct ramping $RAMPSTOP
return idle
}
}
default {
sct ramping $RAMPSTOP
broadcast "DHVERROR: dhv1, Invalid ramp step: $rampstep STOPPING"
sct seterror "DHVERROR: dhv1, Invalid ramp step: $rampstep"
return idle
}
}
set target [expr [sct oldval] + [sct rampstep]]
sct send "$cmd $target"
return getACK
} msg ]
handle_exception $catch_status $msg
}
##
# @brief Command interface for voltage controller
proc ::scobj::dethvps::drvCmd {} {
variable RAMPIDLE
variable RAMPSTOP
variable RAMPSTART
variable RAMPBUSY
variable potValPath
set catch_status [ catch {
set cmd [sct target]
switch -- $cmd {
"halt" - "stop" {
hsetprop $potValPath ramping $RAMPSTOP
}
"up" {
hset $potValPath [sct upper]
}
"down" {
hset $potValPath [sct lower]
}
"off" {
hset $potValPath 0
}
default {
clientput "DHVERROR: Unknown command $cmd"
sct seterror "DHVERROR: Unknown command $cmd"
return idle
}
}
return idle
} msg ]
handle_exception $catch_status $msg
}
##
# @brief Implements the old command line interface for the dhv1 voltage controller.
proc ::scobj::dethvps::dhv1 {{CMD getVoltage} {val ""} } {
variable RAMPINTEREST
variable potValPath
variable voltagePath
variable cmdPath
set catch_status [ catch {
set qsObjPath ""
switch -- $CMD {
"list" {
clientput "dhv1.interval = [hgetpropval $potValPath interval]"
clientput "dhv1.upper = [hgetpropval $cmdPath upper]"
clientput "dhv1.lower = [hgetpropval $cmdPath lower]"
clientput "dhv1.max = [hgetpropval $potValPath max]"
return
}
"interval" {
return "dhv1.interval = [hgetpropval $potValPath interval]"
}
"max" {
set qsObjPath $potValPath
}
"upper" {
if {$val > 63.0} {
error "dhv1 upper must be no greater than 63"
}
set qsObjPath $cmdPath
}
"lower" {
if {$val > 63.0} {
error "dhv1 lower must be no greater than 63"
}
set qsObjPath $cmdPath
}
"getVoltage" {
return "[info level 0 ] = [hval $voltagePath]"
}
"interest" {
set RAMPINTEREST 1
statemon interest
}
"uninterest" {
set RAMPINTEREST 0
statemon uninterest
}
"reset" - "lock" - "unlock" - "debug" {
return
}
default {
hset $cmdPath $CMD
}
}
if {$qsObjPath != ""} {
if {$val != ""} {
if {[SplitReply [config myrights]] == 0} {
hsetprop $qsObjPath $CMD $val
} else {
error "DHVERROR: $CMD can only be initialised from a configuration file"
}
} else {
return "dhv1.$CMD = [hgetpropval $qsObjPath $CMD]"
}
}
} msg ]
handle_exception $catch_status $msg
}
namespace eval ::scobj::dethvps {
variable RAMPIDLE 0
variable RAMPSTOP 1
variable RAMPSTART 2
variable RAMPBUSY 3
variable MINRAMPINTERVAL 10
variable RAMPINTEREST 0
variable MAXPOTVAL 63.0
variable INITMAXVOLTAGE 2600.0
variable INITUPPERPOTVAL 57
variable INITLOWERPOTVAL 19
variable potValPath /sics/so_dhv1/potval
variable voltagePath /sics/so_dhv1/voltage
variable cmdPath /sics/so_dhv1/cmd
namespace export dhv1
hfactory $potValPath plain user int
hsetprop $potValPath read ::scobj::dethvps::rqValue rdValue "H"
hsetprop $potValPath rdValue ::scobj::dethvps::rdValue $voltagePath
hsetprop $potValPath write ::scobj::dethvps::setValue idle
hsetprop $potValPath getACK ::scobj::dethvps::getACK
hsetprop $potValPath ramp ::scobj::dethvps::ramping "h"
hsetprop $potValPath ramping $RAMPIDLE
hsetprop $potValPath rampstep 0
hsetprop $potValPath oldval -1
hsetprop $potValPath max $INITMAXVOLTAGE
hsetprop $potValPath interval -1
hfactory $voltagePath plain internal float
hset $voltagePath -1
hfactory $cmdPath plain user text
hsetprop $cmdPath write ::scobj::dethvps::drvCmd
hsetprop $cmdPath upper $INITUPPERPOTVAL
hsetprop $cmdPath lower $INITLOWERPOTVAL
}
proc ::scobj::dethvps::init {host ip rampinterval} {
variable potValPath
variable voltagePath
variable cmdPath
variable MINRAMPINTERVAL
if {[SplitReply [detector_simulation]] == "false"} {
makesctcontroller sct_dhv ordhvps $host:$ip
set MINRAMPINTERVAL $rampinterval
hsetprop $potValPath interval $rampinterval
sct_dhv poll $potValPath $rampinterval
sct_dhv write $potValPath
sct_dhv write $cmdPath
}
}
namespace import ::scobj::dethvps::dhv1
publish dhv1 user