Lakeshore 336 drivers with known IP addresses have been added to the ini files with unique IDs. All entries in the ini files now have unique IDs The wombat ini now has radio buttons to select sample stage motor configurations.
595 lines
22 KiB
Tcl
595 lines
22 KiB
Tcl
# Temperature Controller driver - Watlow RM
|
|
# Author Douglas Clowes (dcl@ansto.gov.au)
|
|
# Based on the Watlow PM driver
|
|
# Define procs in ::scobj::xxx namespace
|
|
# MakeSICSObj $obj SCT_<class>
|
|
# The MakeSICSObj cmd adds a /sics/$obj node. NOTE the /sics node is not browsable.
|
|
|
|
|
|
namespace eval ::scobj::watlow_rm {
|
|
# Temperature controllers must have at least the following nodes
|
|
# /tempcont/setpoint
|
|
# /tempcont/sensor/value
|
|
proc debug_log {args} {
|
|
set fd [open "/tmp/watlow_rm.log" a]
|
|
puts $fd "[clock format [clock seconds] -format "%T"] $args"
|
|
close $fd
|
|
}
|
|
|
|
proc f_to_c { f_temp } {
|
|
return [expr ($f_temp - 32.0) * (5.0 / 9.0)]
|
|
}
|
|
|
|
proc c_to_f { c_temp } {
|
|
return [expr $c_temp * (9.0 / 5.0) + 32.0]
|
|
}
|
|
|
|
# issue a command to read a register and expect a value response
|
|
proc getValue {tc_root nextState cmd} {
|
|
set dev "[hval $tc_root/dev_id]"
|
|
sct send "$dev:3:$cmd"
|
|
return $nextState
|
|
}
|
|
|
|
# issue a command with a value in the target property of the variable
|
|
proc setValue {tc_root nextState cmd} {
|
|
set dev "[hval $tc_root/dev_id]"
|
|
set par [sct target]
|
|
sct send "$dev:16:$cmd $par"
|
|
debug_log "setValue $dev:16:$cmd $par"
|
|
return $nextState
|
|
}
|
|
|
|
proc rdValue {tc_root} {
|
|
set data [sct result]
|
|
switch -glob -- $data {
|
|
"ASCERR:*" {
|
|
sct geterror $data
|
|
}
|
|
default {
|
|
if { [hpropexists [sct] geterror] } {
|
|
hdelprop [sct] geterror
|
|
}
|
|
if {$data != [sct oldval]} {
|
|
sct oldval $data
|
|
sct update $data
|
|
sct utime readtime
|
|
}
|
|
}
|
|
}
|
|
return idle
|
|
}
|
|
|
|
# write a floating point value
|
|
proc setFloat {tc_root nextState cmd} {
|
|
set dev "[hval $tc_root/dev_id]"
|
|
set par [sct target]
|
|
sct send "$dev:1016:$cmd $par"
|
|
debug_log "setFloat $dev:1016:$cmd $par"
|
|
return $nextState
|
|
}
|
|
|
|
# request a floating point value
|
|
proc getFloat {tc_root nextState cmd} {
|
|
set dev "[hval $tc_root/dev_id]"
|
|
sct send "$dev:1003:$cmd"
|
|
return $nextState
|
|
}
|
|
|
|
# read a floating point value
|
|
proc rdFloat {tc_root} {
|
|
set data [sct result]
|
|
switch -glob -- $data {
|
|
"ASCERR:*" {
|
|
sct geterror $data
|
|
}
|
|
default {
|
|
if { [hpropexists [sct] geterror] } {
|
|
hdelprop [sct] geterror
|
|
}
|
|
if {$data != [sct oldval]} {
|
|
sct oldval $data
|
|
sct update $data
|
|
sct utime readtime
|
|
}
|
|
}
|
|
}
|
|
return idle
|
|
}
|
|
|
|
# write a floating point value as a temperature
|
|
proc setTemp {tc_root nextState cmd} {
|
|
set dev "[hval $tc_root/dev_id]"
|
|
set par [sct target]
|
|
#set par [c_to_f $par]
|
|
sct send "$dev:1016:$cmd $par"
|
|
debug_log "setTemp $dev:1016:$cmd $par"
|
|
return $nextState
|
|
}
|
|
|
|
# request a floating point value as a temperature
|
|
proc getTemp {tc_root nextState cmd} {
|
|
set dev "[hval $tc_root/dev_id]"
|
|
sct send "$dev:1003:$cmd"
|
|
return $nextState
|
|
}
|
|
|
|
# read a floating point value as a temperature
|
|
proc rdTemp {tc_root} {
|
|
set data [sct result]
|
|
#set data [f_to_c $data]
|
|
switch -glob -- $data {
|
|
"ASCERR:*" {
|
|
sct geterror $data
|
|
}
|
|
default {
|
|
if { [hpropexists [sct] geterror] } {
|
|
hdelprop [sct] geterror
|
|
}
|
|
if {$data != [sct oldval]} {
|
|
sct oldval $data
|
|
sct update $data
|
|
sct utime readtime
|
|
}
|
|
}
|
|
}
|
|
return idle
|
|
}
|
|
|
|
proc getState {tc_root nextState cmd} {
|
|
set dev "[hval $tc_root/dev_id]"
|
|
sct send "$dev:3:$cmd"
|
|
return $nextState
|
|
}
|
|
|
|
##
|
|
# @brief Reads the current watlow state and error messages.
|
|
proc rdState {tc_root} {
|
|
set my_driving [SplitReply [hgetprop $tc_root/setpoint driving]]
|
|
debug_log "rdState $tc_root: driving=$my_driving"
|
|
set val [hval $tc_root/setpoint]
|
|
debug_log "rdState $tc_root: setpoint=$val"
|
|
if {[hpropexists $tc_root/setpoint target]} {
|
|
set tgt [SplitReply [hgetprop $tc_root/setpoint target]]
|
|
debug_log "rdState $tc_root: target=$tgt"
|
|
} else {
|
|
hsetprop $tc_root/setpoint target $val
|
|
set tgt [SplitReply [hgetprop $tc_root/setpoint target]]
|
|
debug_log "rdState $tc_root: initialised target to: target=$tgt"
|
|
}
|
|
if {$my_driving > 0} {
|
|
set temp [hval $tc_root/sensor/value]
|
|
set tol [hval $tc_root/tolerance]
|
|
set lotemp [expr {$tgt - $tol}]
|
|
set hitemp [expr {$tgt + $tol}]
|
|
debug_log "rdState driving $tc_root until $temp in ($lotemp, $hitemp)"
|
|
if {$temp < $lotemp} {
|
|
} elseif {$temp > $hitemp} {
|
|
} else {
|
|
hset $tc_root/status "idle"
|
|
hsetprop $tc_root/setpoint driving 0
|
|
}
|
|
} else {
|
|
if {[hval $tc_root/status] != "idle"} {
|
|
hset $tc_root/status "idle"
|
|
}
|
|
}
|
|
set data [SplitReply [hgetprop $tc_root/setpoint driving]]
|
|
debug_log "rdState $tc_root: result=$data"
|
|
if {[string first "ASCERR:" $data] >=0} {
|
|
sct geterror $data
|
|
} elseif {$data != [sct oldval]} {
|
|
hdelprop [sct] geterror
|
|
sct oldval $data
|
|
sct update $data
|
|
sct utime readtime
|
|
}
|
|
return idle
|
|
}
|
|
|
|
proc getHP {tc_root nextState cmd} {
|
|
set data [hval $tc_root/Loop1/power]
|
|
if {$data != [sct oldval]} {
|
|
sct oldval $data
|
|
sct update $data
|
|
sct utime readtime
|
|
}
|
|
debug_log "getHP $tc_root $nextState $cmd [sct] $data"
|
|
return idle
|
|
}
|
|
|
|
proc getPV {tc_root nextState cmd} {
|
|
set data [hval $tc_root/Loop1/sensor]
|
|
if {$data != [sct oldval]} {
|
|
sct oldval $data
|
|
sct update $data
|
|
sct utime readtime
|
|
}
|
|
debug_log "getPV $tc_root $nextState $cmd [sct] $data"
|
|
return idle
|
|
}
|
|
|
|
proc getSP {tc_root nextState cmd} {
|
|
set data [hval $tc_root/Loop1/setpoint]
|
|
if {$data != [sct oldval]} {
|
|
sct oldval $data
|
|
sct update $data
|
|
sct utime readtime
|
|
}
|
|
debug_log "getSP $tc_root $nextState $cmd [sct] $data"
|
|
return idle
|
|
}
|
|
|
|
proc setSP {tc_root nextState cmd} {
|
|
debug_log "setSP $tc_root $nextState $cmd [sct]=[sct target] [hget [sct]]"
|
|
debug_log "setSP sct = [sct], sct writestatus = [sct writestatus]"
|
|
if {[sct writestatus] == "start"} {
|
|
# Called by drive adapter
|
|
hset $tc_root/status "busy"
|
|
debug_log "setSP hsetprop $tc_root/setpoint driving 1"
|
|
hsetprop $tc_root/setpoint driving 1
|
|
}
|
|
hset $tc_root/Loop1/setpoint [sct target]
|
|
return idle
|
|
}
|
|
|
|
proc setPoint {tc_root nextState cmd} {
|
|
set dev "[hval $tc_root/dev_id]"
|
|
set par [sct target]
|
|
|
|
if {[sct writestatus] == "start"} {
|
|
# Called by drive adapter
|
|
hset $tc_root/status "busy"
|
|
hsetprop $tc_root/setpoint driving 1
|
|
}
|
|
set par [c_to_f $par]
|
|
sct send "$dev:1016:$cmd $par"
|
|
debug_log "setPoint $dev:1016:$cmd $par"
|
|
return $nextState
|
|
}
|
|
|
|
proc noResponse {} {
|
|
return idle
|
|
}
|
|
proc wrtValue {wcmd args} {
|
|
}
|
|
|
|
# check that a target is within allowable limits
|
|
proc check {tc_root} {
|
|
set setpoint [sct target]
|
|
set lolimit [hval $tc_root/lowerlimit]
|
|
set hilimit [hval $tc_root/upperlimit]
|
|
if {$setpoint < $lolimit || $setpoint > $hilimit} {
|
|
error "setpoint violates limits"
|
|
}
|
|
return OK
|
|
}
|
|
|
|
# Check that the sensor is reading within tolerance of the setpoint.
|
|
# Return 1 or 0 if it is or is not, respectively.
|
|
proc checktol {tc_root currtime timecheck} {
|
|
debug_log "checktol $tc_root $currtime $timecheck"
|
|
set temp [hval $tc_root/sensor/value]
|
|
set lotemp [hval $tc_root/subtemp_warnlimit]
|
|
set hitemp [hval $tc_root/overtemp_warnlimit]
|
|
if { $temp < $lotemp || $temp > $hitemp} {
|
|
hset $tc_root/emon/isintol 0
|
|
return 0
|
|
} else {
|
|
set timeout [hval $tc_root/tolerance/settletime]
|
|
if { ($currtime - $timecheck) > $timeout } {
|
|
hset $tc_root/emon/isintol 1
|
|
}
|
|
return 1
|
|
}
|
|
}
|
|
|
|
##
|
|
# @brief Implement the checkstatus command for the drivable interface
|
|
#
|
|
# NOTE: The drive adapter initially sets the writestatus to "start" and will
|
|
# only call this when writestatus!="start"
|
|
proc drivestatus {tc_root} {
|
|
if {[sct driving]} {
|
|
return busy
|
|
} else {
|
|
sct print "drivestatus: idle"
|
|
return idle
|
|
}
|
|
}
|
|
|
|
proc halt {tc_root} {
|
|
debug_log "halt $tc_root"
|
|
hset $tc_root/setpoint [hval $tc_root/sensor/value]
|
|
hsetprop $tc_root/setpoint driving 0
|
|
return idle
|
|
}
|
|
|
|
##
|
|
# @brief createNode() creates a node for the given nodename with the properties and virtual
|
|
# function names provided
|
|
# @param scobj_hpath string variable holding the path to the object's base node in sics (/sample/tc1)
|
|
# @param sct_controller name of the scriptcontext object (typically sct_xxx_yyy)
|
|
# @param cmdGroup subdirectory (below /sample/tc*/) in which the node is to be created
|
|
# @param varName name of the actual node typically representing one device command
|
|
# @param readable set to 1 if the node represents a query command, 0 if it is not
|
|
# @param writable set to 1 if the node represents a request for a change in settings sent to the device
|
|
# @param drivable if set to 1 it prepares the node to provide a drivable interface
|
|
# @param dataType data type of the node, must be one of none, int, float, text
|
|
# @param permission defines what user group may read/write to this node (is one of spy, user, manager)
|
|
# @param rdCmd actual device query command to be sent to the device
|
|
# @param rdFunc nextState Function to be called after the getValue function, typically rdValue()
|
|
# @param wrCmd actual device write command to be sent to the device
|
|
# @param wrFunc Function to be called to send the wrCmd to the device, typically setValue()
|
|
# @param allowedValues allowed values for the node data - does not permit other
|
|
# @param klass Nexus class name (?)
|
|
# @return OK
|
|
proc createNode {scobj_hpath sct_controller cmdGroup varName readable writable\
|
|
drivable dataType permission rdCmd rdFunc wrCmd\
|
|
wrFunc allowedValues klass} {
|
|
|
|
set catch_status [ catch {
|
|
# set ns ::scobj::ls460
|
|
set ns "[namespace current]"
|
|
set nodeName "$scobj_hpath/$cmdGroup/$varName"
|
|
if {1 > [string length $cmdGroup]} {
|
|
set nodeName "$scobj_hpath/$varName"
|
|
}
|
|
debug_log "Creating node $nodeName"
|
|
hfactory $nodeName plain $permission $dataType
|
|
if {$readable > 0} {
|
|
set parts [split "$rdFunc" "."]
|
|
if { [llength $parts] == 2 } {
|
|
set func_name [lindex $parts 0]
|
|
set next_state [lindex $parts 1]
|
|
hsetprop $nodeName read ${ns}::$func_name $scobj_hpath $next_state $rdCmd
|
|
hsetprop $nodeName $next_state ${ns}::$next_state $scobj_hpath
|
|
} else {
|
|
if {$rdFunc == "getPV"} {
|
|
set func_name "$rdFunc"
|
|
} elseif {$rdFunc == "getSP"} {
|
|
set func_name "$rdFunc"
|
|
} elseif {$rdFunc == "getHP"} {
|
|
set func_name "$rdFunc"
|
|
} elseif {$rdFunc == "rdFloat"} {
|
|
set func_name "getFloat"
|
|
} elseif {$rdFunc == "rdTemp"} {
|
|
set func_name "getTemp"
|
|
} else {
|
|
set func_name "getValue"
|
|
}
|
|
hsetprop $nodeName read ${ns}::$func_name $scobj_hpath $rdFunc $rdCmd
|
|
hsetprop $nodeName $rdFunc ${ns}::$rdFunc $scobj_hpath
|
|
}
|
|
set poll_period 30
|
|
if { $readable >= 0 && $readable <= 9 } {
|
|
set poll_period [lindex [list 0 1 2 3 4 5 10 15 20 30] $readable]
|
|
}
|
|
debug_log "Registering node $nodeName for poll at $poll_period seconds"
|
|
$sct_controller poll $nodeName $poll_period
|
|
}
|
|
if {$writable == 1} {
|
|
set parts [split "$wrFunc" "."]
|
|
if { [llength $parts] == 2 } {
|
|
set func_name [lindex $parts 0]
|
|
set next_state [lindex $parts 1]
|
|
hsetprop $nodeName write ${ns}::$func_name $scobj_hpath $next_state $wrCmd
|
|
hsetprop $nodeName $next_state ${ns}::$next_state $scobj_hpath
|
|
} else {
|
|
hsetprop $nodeName write ${ns}::$wrFunc $scobj_hpath noResponse $wrCmd
|
|
hsetprop $nodeName noResponse ${ns}::noResponse
|
|
}
|
|
hsetprop $nodeName writestatus UNKNOWN
|
|
debug_log "Registering node $nodeName for write callback"
|
|
$sct_controller write $nodeName
|
|
}
|
|
switch -exact $dataType {
|
|
"none" { }
|
|
"int" { hsetprop $nodeName oldval -1 }
|
|
"float" { hsetprop $nodeName oldval -1.0 }
|
|
default { hsetprop $nodeName oldval UNKNOWN }
|
|
}
|
|
if {1 < [string length $allowedValues]} {
|
|
hsetprop $nodeName values $allowedValues
|
|
}
|
|
# Drive adapter interface
|
|
if {$drivable == 1} {
|
|
hsetprop $nodeName check ${ns}::check $scobj_hpath
|
|
hsetprop $nodeName driving 0
|
|
hsetprop $nodeName checklimits ${ns}::check $scobj_hpath
|
|
hsetprop $nodeName checkstatus ${ns}::drivestatus $scobj_hpath
|
|
hsetprop $nodeName halt ${ns}::halt $scobj_hpath
|
|
}
|
|
} message ]
|
|
if {$catch_status != 0} {
|
|
return -code error "in createNode $message"
|
|
}
|
|
return OK
|
|
}
|
|
|
|
proc mk_sct_watlow_rm {sct_controller klass tempobj dev_id tol CID CTYPE} {
|
|
set catch_status [ catch {
|
|
set ns "[namespace current]"
|
|
|
|
MakeSICSObj $tempobj SCT_OBJECT
|
|
sicslist setatt $tempobj klass $klass
|
|
sicslist setatt $tempobj long_name $tempobj
|
|
|
|
set scobj_hpath /sics/$tempobj
|
|
|
|
#
|
|
# These addresses are modbus addresses on the RUI/gateway over two devices
|
|
# The RMC is at address 1 and the modbus offset on the RUI for gateway 1
|
|
# is zero, so these addresses are as specified in the manual.
|
|
# The RMS is at address 2 and the modbus offset on the RUI for gateway 1
|
|
# is 5000, so these addresses have 5000 added to those specified in the manual.
|
|
#
|
|
set deviceCommand {\
|
|
{} setpoint 1 1 1 float user {0} {getSP} {0} {setSP} {}\
|
|
sensor value 1 0 0 float internal {0} {getPV} {0} {} {}\
|
|
{} power 1 0 0 float internal {0} {getHP} {0} {} {}\
|
|
Loop1 setpoint 1 1 0 float user {2500} {rdTemp} {2500} {setTemp} {}\
|
|
Loop1 sensor 1 0 0 float internal {3430} {rdTemp} {3430} {} {}\
|
|
Loop1 PV 1 0 0 float internal {3442} {rdTemp} {3442} {} {}\
|
|
Loop1 power 1 0 0 float internal {2248} {rdFloat} {2248} {} {}\
|
|
Loop1 sensorerror 1 0 0 int internal {3452} {rdValue} {3452} {} {}\
|
|
Loop1 looperror 1 0 0 int internal {2268} {rdValue} {2268} {} {}\
|
|
Analog Input01 1 0 0 float internal {360} {rdTemp} {360} {} {}\
|
|
Analog Input02 1 0 0 float internal {450} {rdTemp} {450} {} {}\
|
|
Analog Input03 1 0 0 float internal {5380} {rdTemp} {5380} {} {}\
|
|
Analog Input04 1 0 0 float internal {5470} {rdTemp} {5470} {} {}\
|
|
Analog Input05 1 0 0 float internal {5560} {rdTemp} {5560} {} {}\
|
|
Analog Input06 1 0 0 float internal {5650} {rdTemp} {5650} {} {}\
|
|
Analog Input07 1 0 0 float internal {5740} {rdTemp} {5740} {} {}\
|
|
Analog Input08 1 0 0 float internal {5830} {rdTemp} {5830} {} {}\
|
|
Analog Input09 1 0 0 float internal {5920} {rdTemp} {5920} {} {}\
|
|
Analog Input10 1 0 0 float internal {6010} {rdTemp} {6010} {} {}\
|
|
}
|
|
|
|
hfactory $scobj_hpath/sensor plain spy none
|
|
hfactory $scobj_hpath/Analog plain spy none
|
|
hfactory $scobj_hpath/Loop1 plain spy none
|
|
|
|
foreach {cmdGroup varName readable writable drivable dataType permission rdCmd rdFunc wrCmd wrFunc allowedValues} $deviceCommand {
|
|
createNode $scobj_hpath $sct_controller $cmdGroup $varName $readable $writable $drivable $dataType $permission $rdCmd $rdFunc $wrCmd $wrFunc $allowedValues $klass
|
|
}
|
|
|
|
hsetprop $scobj_hpath/sensor/value lowerlimit 0
|
|
hsetprop $scobj_hpath/sensor/value upperlimit 500
|
|
hsetprop $scobj_hpath/sensor/value units "C"
|
|
hsetprop $scobj_hpath/sensor/value permlink data_set ${CTYPE}${CID}S1
|
|
hsetprop $scobj_hpath/setpoint permlink data_set ${CTYPE}${CID}SP1
|
|
|
|
hfactory $scobj_hpath/apply_tolerance plain user int
|
|
hsetprop $scobj_hpath/apply_tolerance values 0,1
|
|
hset $scobj_hpath/apply_tolerance 1
|
|
|
|
hfactory $scobj_hpath/dev_id plain user int
|
|
hsetprop $scobj_hpath/dev_id values 0,1,2,3,4,5,6,7,8,9
|
|
hset $scobj_hpath/dev_id $dev_id
|
|
|
|
hfactory $scobj_hpath/tolerance plain user float
|
|
hsetprop $scobj_hpath/tolerance units "C"
|
|
hfactory $scobj_hpath/tolerance/settletime plain user float
|
|
hset $scobj_hpath/tolerance/settletime 5.0
|
|
hsetprop $scobj_hpath/tolerance/settletime units "s"
|
|
hset $scobj_hpath/tolerance $tol
|
|
|
|
hfactory $scobj_hpath/status plain spy text
|
|
hset $scobj_hpath/status "idle"
|
|
hsetprop $scobj_hpath/status values busy,idle
|
|
|
|
hfactory $scobj_hpath/device_state plain spy text
|
|
hsetprop $scobj_hpath/device_state read ${ns}::getState $scobj_hpath rdState "362"
|
|
hsetprop $scobj_hpath/device_state rdState ${ns}::rdState $scobj_hpath
|
|
hsetprop $scobj_hpath/device_state oldval UNKNOWN
|
|
|
|
hfactory $scobj_hpath/remote_ctrl plain spy text
|
|
hset $scobj_hpath/remote_ctrl UNKNOWN
|
|
|
|
hfactory $scobj_hpath/device_lasterror plain user text
|
|
hset $scobj_hpath/device_lasterror ""
|
|
|
|
hfactory $scobj_hpath/lowerlimit plain mugger float
|
|
hsetprop $scobj_hpath/lowerlimit units "C"
|
|
hset $scobj_hpath/lowerlimit 0
|
|
|
|
hfactory $scobj_hpath/upperlimit plain mugger float
|
|
hsetprop $scobj_hpath/upperlimit units "C"
|
|
hset $scobj_hpath/upperlimit 500
|
|
|
|
hfactory $scobj_hpath/emon plain spy none
|
|
hfactory $scobj_hpath/emon/monmode plain user text
|
|
hsetprop $scobj_hpath/emon/monmode values idle,drive,monitor,error
|
|
hset $scobj_hpath/emon/monmode "idle"
|
|
hfactory $scobj_hpath/emon/isintol plain user int
|
|
hset $scobj_hpath/emon/isintol 1
|
|
hfactory $scobj_hpath/emon/errhandler plain user text
|
|
hset $scobj_hpath/emon/errhandler "pause"
|
|
|
|
if {[SplitReply [environment_simulation]]=="false"} {
|
|
$sct_controller poll $scobj_hpath/device_state 1 halt read
|
|
}
|
|
|
|
::scobj::hinitprops $tempobj
|
|
hsetprop $scobj_hpath klass environment
|
|
::scobj::set_required_props $scobj_hpath
|
|
foreach {rootpath hpath klass priv} "
|
|
$scobj_hpath sensor NXsensor spy
|
|
$scobj_hpath sensor/value sensor user
|
|
" {
|
|
hsetprop $rootpath/$hpath klass $klass
|
|
hsetprop $rootpath/$hpath privilege $priv
|
|
hsetprop $rootpath/$hpath control true
|
|
hsetprop $rootpath/$hpath data true
|
|
hsetprop $rootpath/$hpath nxsave true
|
|
}
|
|
hsetprop $scobj_hpath type part
|
|
hsetprop $scobj_hpath/sensor type part
|
|
hsetprop $scobj_hpath/sensor/value nxalias tc1_sensor_value
|
|
hsetprop $scobj_hpath/sensor/value mutable true
|
|
hsetprop $scobj_hpath/sensor/value sdsinfo ::nexus::scobj::sdsinfo
|
|
|
|
hsetprop $scobj_hpath privilege spy
|
|
::scobj::hinitprops $tempobj setpoint
|
|
hsetprop $scobj_hpath/setpoint data true
|
|
hsetprop $scobj_hpath/setpoint type drivable
|
|
if {[SplitReply [environment_simulation]]=="false"} {
|
|
ansto_makesctdrive ${tempobj}_driveable $scobj_hpath/setpoint $scobj_hpath/sensor/value $sct_controller
|
|
}
|
|
} catch_message ]
|
|
if {$catch_status != 0} {
|
|
return -code error $catch_message
|
|
}
|
|
}
|
|
namespace export mk_sct_watlow_rm
|
|
}
|
|
|
|
##
|
|
# @brief Create a Watlow RM temperature controller
|
|
#
|
|
# @param name, the name of the temperature controller (eg tc1)
|
|
# @param IP, the IP address of the device, this can be a hostname, (eg ca5-kowari)
|
|
# @param port, the IP protocol port number of the device (502 for modbus)
|
|
# @param _tol (optional), this is the initial tolerance setting
|
|
proc add_watlow_rm {name IP port dev_id {_tol 5.0} {CID 1} {CTYPE T}} {
|
|
set fd [open "/tmp/watlow_rm.log" a]
|
|
if {[SplitReply [environment_simulation]]=="false"} {
|
|
puts $fd "makesctcontroller sct_${name} modbus ${IP}:$port"
|
|
makesctcontroller sct_${name} modbus ${IP}:$port
|
|
}
|
|
puts $fd "mk_sct_watlow_rm sct_${name} environment $name $dev_id $_tol"
|
|
mk_sct_watlow_rm sct_${name} environment $name $dev_id $_tol $CID $CTYPE
|
|
puts $fd "makesctemon $name /sics/$name/emon/monmode /sics/$name/emon/isintol /sics/$name/emon/errhandler"
|
|
makesctemon $name /sics/$name/emon/monmode /sics/$name/emon/isintol /sics/$name/emon/errhandler
|
|
close $fd
|
|
}
|
|
|
|
puts stdout "file evaluation of sct_watlow_rm.tcl"
|
|
set fd [open "/tmp/watlow_rm.log" w]
|
|
puts $fd "file evaluation of sct_watlow_rm.tcl"
|
|
close $fd
|
|
|
|
if {[ catch {
|
|
if { [ info exists ::config_dict ] } {
|
|
dict for {secname secinfo} $::config_dict {
|
|
if { [dict exists $secinfo "driver"] && ([dict get $secinfo "driver"] == "watlow_rm") } {
|
|
if { [ dict get $::secinfo enabled ] } {
|
|
set name [dict get $::secinfo name]
|
|
set IP [dict get $::secinfo ip]
|
|
set PORT [dict get $::secinfo port]
|
|
set sensor [dict get $::secinfo sensor]
|
|
set tol [dict get $::secinfo tol]
|
|
set cid [dict get $::secinfo id]
|
|
set ctype [dict get $::secinfo type]
|
|
add_watlow_rm $name $IP $PORT $devid $tol $cid $ctype
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} message ]} {
|
|
puts "ERROR: $message"
|
|
}
|
|
|
|
namespace import ::scobj::watlow_rm::*
|