SCT driver for Lakeshore 218S Temperature Monitor
This commit is contained in:
@ -0,0 +1,43 @@
|
|||||||
|
driver lakeshore_218 = {
|
||||||
|
vendor = lakeshore; device = ls218; protocol = std;
|
||||||
|
class = environment; simulation_group = environment_simulation;
|
||||||
|
|
||||||
|
group = {
|
||||||
|
data = false;
|
||||||
|
nxsave = false;
|
||||||
|
control = false;
|
||||||
|
readable = 1;
|
||||||
|
|
||||||
|
var krdg = {
|
||||||
|
type = text;
|
||||||
|
read_command = "KRDG? 0";
|
||||||
|
read_function = read_temps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group sensor = {
|
||||||
|
priv = user;
|
||||||
|
type = float;
|
||||||
|
mutable = true;
|
||||||
|
var ch1 = { type = float; units = 'K'; }
|
||||||
|
var ch2 = { type = float; units = 'K'; }
|
||||||
|
var ch3 = { type = float; units = 'K'; }
|
||||||
|
var ch4 = { type = float; units = 'K'; }
|
||||||
|
var ch5 = { type = float; units = 'K'; }
|
||||||
|
var ch6 = { type = float; units = 'K'; }
|
||||||
|
var ch7 = { type = float; units = 'K'; }
|
||||||
|
var ch8 = { type = float; units = 'K'; }
|
||||||
|
}
|
||||||
|
|
||||||
|
code read_temps = {%%
|
||||||
|
set temps [split "${data}" ","]
|
||||||
|
hupdate ${tc_root}/sensor/ch1 [lindex ${temps} 0]
|
||||||
|
hupdate ${tc_root}/sensor/ch2 [lindex ${temps} 1]
|
||||||
|
hupdate ${tc_root}/sensor/ch3 [lindex ${temps} 2]
|
||||||
|
hupdate ${tc_root}/sensor/ch4 [lindex ${temps} 3]
|
||||||
|
hupdate ${tc_root}/sensor/ch5 [lindex ${temps} 4]
|
||||||
|
hupdate ${tc_root}/sensor/ch6 [lindex ${temps} 5]
|
||||||
|
hupdate ${tc_root}/sensor/ch7 [lindex ${temps} 6]
|
||||||
|
hupdate ${tc_root}/sensor/ch8 [lindex ${temps} 7]
|
||||||
|
%%}
|
||||||
|
}
|
@ -1,635 +1,375 @@
|
|||||||
# Define procs in ::scobj::xxx namespace
|
# Generated driver for lakeshore_218
|
||||||
# MakeSICSObj $obj SCT_<class>
|
# vim: ft=tcl tabstop=8 softtabstop=2 shiftwidth=2 nocindent smartindent
|
||||||
# The MakeSICSObj cmd adds a /sics/$obj node. NOTE the /sics node is not browsable.
|
#
|
||||||
|
|
||||||
##
|
namespace eval ::scobj::lakeshore_218 {
|
||||||
# /*--------------------------------------------------------------------------
|
set debug_threshold 5
|
||||||
# L A K E S H O R E 3 x x S E R I E S D R I V E R
|
|
||||||
#
|
|
||||||
# This file contains the implementation of a driver for the Lakeshore 218
|
|
||||||
# controller implemented as a scriptcontext object in TCL.
|
|
||||||
# object in TCL.
|
|
||||||
#
|
|
||||||
# @author: Jing Chen, ANSTO, 2012-08-22
|
|
||||||
# @brief: SICS driver for Lakeshore 218 Temperature Controller (in TCL)
|
|
||||||
#
|
|
||||||
# ----------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
proc debug_log {args} {
|
|
||||||
set d1 [clock format [clock seconds] -format %d%h%Y]
|
|
||||||
set fd [open "../log/ls218Temp$d1.log" a]
|
|
||||||
puts $fd "[clock format [clock seconds] -format "%D %T "] [string trim $args "{}"]"
|
|
||||||
close $fd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Default temperature controller parameters
|
proc ::scobj::lakeshore_218::debug_log {tc_root debug_level debug_string} {
|
||||||
namespace eval ::scobj::ls218 {
|
set catch_status [ catch {
|
||||||
#variable logString ""
|
set debug_threshold [hgetpropval ${tc_root} debug_threshold]
|
||||||
|
if {${debug_level} >= ${debug_threshold}} {
|
||||||
|
set fd [open "../log/lakeshore_218_[basename ${tc_root}].log" "a"]
|
||||||
|
set line "[clock format [clock seconds] -format "%T"] ${debug_string}"
|
||||||
|
puts ${fd} "${line}"
|
||||||
|
close ${fd}
|
||||||
|
}
|
||||||
|
} catch_message ]
|
||||||
}
|
}
|
||||||
|
|
||||||
############# Reading polled nodes ###################################
|
proc ::scobj::lakeshore_218::sics_log {debug_level debug_string} {
|
||||||
|
set catch_status [ catch {
|
||||||
|
set debug_threshold ${::scobj::lakeshore_218::debug_threshold}
|
||||||
|
if {${debug_level} >= ${debug_threshold}} {
|
||||||
|
sicslog "::scobj::lakeshore_218::${debug_string}"
|
||||||
|
}
|
||||||
|
} catch_message ]
|
||||||
|
}
|
||||||
|
|
||||||
##
|
# check function for hset change
|
||||||
# @brief Sends a query command to the device via a read node formalism
|
proc ::scobj::lakeshore_218::checkrange {tc_root} {
|
||||||
# @param tc_root The path to the root of the node
|
set catch_status [ catch {
|
||||||
# @param nextState The next function to call after this one (typically 'rdValue'
|
debug_log ${tc_root} 1 "checkrange tc_root=${tc_root} sct=[sct] target=[sct target]"
|
||||||
# to read the response from the device)
|
set setpoint [sct target]
|
||||||
# @param cmd The query command to be send to the device (written to the
|
if { [hpropexists [sct] lowerlimit] } {
|
||||||
# node data value)
|
set lolimit [sct lowerlimit]
|
||||||
# @param idx indicates which control loop or which input channel
|
} else {
|
||||||
# the command belongs to
|
# lowerlimit not set, use target
|
||||||
# @return nextState The next function to call after this one (typically 'rdValue')
|
set lolimit [sct target]
|
||||||
proc ::scobj::ls218::getValue {idx cmd chID nextState} {
|
}
|
||||||
if {[ catch {
|
if { [hpropexists [sct] upperlimit] } {
|
||||||
if {[hpropexists [sct] geterror]} {
|
set hilimit [sct upperlimit]
|
||||||
|
} else {
|
||||||
|
# upperlimit not set, use target
|
||||||
|
set hilimit [sct target]
|
||||||
|
}
|
||||||
|
# checkrange hook code goes here
|
||||||
|
if { ${setpoint} < ${lolimit} || ${setpoint} > ${hilimit} } {
|
||||||
|
error "setpoint ${setpoint} violates limits (${lolimit}..${hilimit}) on [sct]"
|
||||||
|
}
|
||||||
|
return OK
|
||||||
|
} catch_message ]
|
||||||
|
handle_exception ${catch_status} ${catch_message}
|
||||||
|
}
|
||||||
|
|
||||||
|
# function to request the read of a parameter on a device
|
||||||
|
proc ::scobj::lakeshore_218::getValue {tc_root nextState cmd_str} {
|
||||||
|
set catch_status [ catch {
|
||||||
|
debug_log ${tc_root} 1 "getValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}"
|
||||||
|
if { [hpropexists [sct] geterror] } {
|
||||||
hdelprop [sct] geterror
|
hdelprop [sct] geterror
|
||||||
}
|
}
|
||||||
|
set cmd "${cmd_str}"
|
||||||
|
# getValue hook code goes here
|
||||||
|
debug_log ${tc_root} 1 "getValue sct send ${cmd}"
|
||||||
|
if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} {
|
||||||
|
sct send "${cmd}"
|
||||||
|
}
|
||||||
|
return ${nextState}
|
||||||
|
} catch_message ]
|
||||||
|
handle_exception ${catch_status} ${catch_message}
|
||||||
|
}
|
||||||
|
|
||||||
if {$chID == 1} {
|
# function to check the write parameter on a device
|
||||||
set comm "$cmd $idx"
|
proc ::scobj::lakeshore_218::noResponse {tc_root} {
|
||||||
} elseif {$chID == 0} {
|
set catch_status [ catch {
|
||||||
set comm $cmd
|
debug_log ${tc_root} 1 "noResponse tc_root=${tc_root} sct=[sct] resp=[sct result]"
|
||||||
} elseif {$chID == "G"} {
|
# noResponse hook code goes here
|
||||||
if {1 <= $idx <= 4} {
|
return "idle"
|
||||||
set comm "$cmd A"
|
} catch_message ]
|
||||||
|
handle_exception ${catch_status} ${catch_message}
|
||||||
|
}
|
||||||
|
|
||||||
|
# function to parse the read of a parameter on a device
|
||||||
|
proc ::scobj::lakeshore_218::rdValue {tc_root} {
|
||||||
|
set catch_status [ catch {
|
||||||
|
debug_log ${tc_root} 1 "rdValue tc_root=${tc_root} sct=[sct] result=[sct result]"
|
||||||
|
if { [hpropexists [sct] geterror] } {
|
||||||
|
hdelprop [sct] geterror
|
||||||
|
}
|
||||||
|
set data [sct result]
|
||||||
|
set nextState "idle"
|
||||||
|
if {[string equal -nocase -length 7 ${data} "ASCERR:"]} {
|
||||||
|
# the protocol driver has reported an error
|
||||||
|
sct geterror "${data}"
|
||||||
|
error "[sct geterror]"
|
||||||
|
}
|
||||||
|
# rdValue hook code goes here
|
||||||
|
if { ${data} != [sct oldval] } {
|
||||||
|
debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]"
|
||||||
|
sct oldval ${data}
|
||||||
|
sct update ${data}
|
||||||
|
sct utime readtime
|
||||||
|
}
|
||||||
|
return ${nextState}
|
||||||
|
} catch_message ]
|
||||||
|
handle_exception ${catch_status} ${catch_message}
|
||||||
|
}
|
||||||
|
|
||||||
|
# function to parse the read of a parameter on a device
|
||||||
|
proc ::scobj::lakeshore_218::read_temps {tc_root} {
|
||||||
|
set catch_status [ catch {
|
||||||
|
debug_log ${tc_root} 1 "read_temps tc_root=${tc_root} sct=[sct] result=[sct result]"
|
||||||
|
if { [hpropexists [sct] geterror] } {
|
||||||
|
hdelprop [sct] geterror
|
||||||
|
}
|
||||||
|
set data [sct result]
|
||||||
|
set nextState "idle"
|
||||||
|
if {[string equal -nocase -length 7 ${data} "ASCERR:"]} {
|
||||||
|
# the protocol driver has reported an error
|
||||||
|
sct geterror "${data}"
|
||||||
|
error "[sct geterror]"
|
||||||
|
}
|
||||||
|
# read_temps hook code starts
|
||||||
|
set temps [split "${data}" ","]
|
||||||
|
hupdate ${tc_root}/sensor/ch1 [lindex ${temps} 0]
|
||||||
|
hupdate ${tc_root}/sensor/ch2 [lindex ${temps} 1]
|
||||||
|
hupdate ${tc_root}/sensor/ch3 [lindex ${temps} 2]
|
||||||
|
hupdate ${tc_root}/sensor/ch4 [lindex ${temps} 3]
|
||||||
|
hupdate ${tc_root}/sensor/ch5 [lindex ${temps} 4]
|
||||||
|
hupdate ${tc_root}/sensor/ch6 [lindex ${temps} 5]
|
||||||
|
hupdate ${tc_root}/sensor/ch7 [lindex ${temps} 6]
|
||||||
|
hupdate ${tc_root}/sensor/ch8 [lindex ${temps} 7]
|
||||||
|
# read_temps hook code ends
|
||||||
|
if { [hpropexists [sct] geterror] } {
|
||||||
|
debug_log ${tc_root} 9 "[sct] error: [sct geterror]"
|
||||||
|
error "[sct geterror]"
|
||||||
|
}
|
||||||
|
if { ${data} != [sct oldval] } {
|
||||||
|
debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]"
|
||||||
|
sct oldval ${data}
|
||||||
|
sct update ${data}
|
||||||
|
sct utime readtime
|
||||||
|
}
|
||||||
|
return ${nextState}
|
||||||
|
} catch_message ]
|
||||||
|
handle_exception ${catch_status} ${catch_message}
|
||||||
|
}
|
||||||
|
|
||||||
|
# function to write a parameter value on a device
|
||||||
|
proc ::scobj::lakeshore_218::setValue {tc_root nextState cmd_str} {
|
||||||
|
set catch_status [ catch {
|
||||||
|
debug_log ${tc_root} 1 "setValue tc_root=${tc_root} sct=[sct] cmd=${cmd_str}"
|
||||||
|
if { [hpropexists [sct] geterror] } {
|
||||||
|
hdelprop [sct] geterror
|
||||||
|
}
|
||||||
|
set par [sct target]
|
||||||
|
set cmd "${cmd_str}${par}"
|
||||||
|
# setValue hook code goes here
|
||||||
|
if { [hpropexists [sct] driving] } {
|
||||||
|
if { [hpropexists [sct] writestatus] && [sct writestatus] == "start" } {
|
||||||
|
sct driving 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug_log ${tc_root} 1 "setValue sct send ${cmd}"
|
||||||
|
if {![string equal -nocase -length 10 ${cmd} "@@NOSEND@@"]} {
|
||||||
|
sct send "${cmd}"
|
||||||
|
}
|
||||||
|
return ${nextState}
|
||||||
|
} catch_message ]
|
||||||
|
handle_exception ${catch_status} ${catch_message}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc ::scobj::lakeshore_218::mkDriver { sct_controller name } {
|
||||||
|
::scobj::lakeshore_218::sics_log 9 "::scobj::lakeshore_218::mkDriver for ${name}"
|
||||||
|
set ns "[namespace current]"
|
||||||
|
set catch_status [ catch {
|
||||||
|
|
||||||
|
MakeSICSObj ${name} SCT_OBJECT
|
||||||
|
|
||||||
|
sicslist setatt ${name} klass environment
|
||||||
|
sicslist setatt ${name} long_name ${name}
|
||||||
|
|
||||||
|
set scobj_hpath /sics/${name}
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/krdg plain user text
|
||||||
|
hsetprop ${scobj_hpath}/krdg read ${ns}::getValue ${scobj_hpath} read_temps {KRDG? 0}
|
||||||
|
hsetprop ${scobj_hpath}/krdg read_temps ${ns}::read_temps ${scobj_hpath}
|
||||||
|
hsetprop ${scobj_hpath}/krdg control false
|
||||||
|
hsetprop ${scobj_hpath}/krdg data false
|
||||||
|
hsetprop ${scobj_hpath}/krdg mutable false
|
||||||
|
hsetprop ${scobj_hpath}/krdg nxsave false
|
||||||
|
hsetprop ${scobj_hpath}/krdg oldval UNKNOWN
|
||||||
|
hsetprop ${scobj_hpath}/krdg sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/krdg type "part"
|
||||||
|
hsetprop ${scobj_hpath}/krdg nxalias "${name}_krdg"
|
||||||
|
|
||||||
|
if {[string equal -nocase [SplitReply [environment_simulation]] "false"]} {
|
||||||
|
${sct_controller} poll ${scobj_hpath}/krdg 1
|
||||||
|
} else {
|
||||||
|
::scobj::lakeshore_218::sics_log 9 "[environment_simulation] => No poll/write for lakeshore_218"
|
||||||
|
}
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor plain spy none
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor/ch1 plain user float
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 control true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 data true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 mutable true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 nxsave true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 units K
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 oldval 0.0
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 type "part"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch1 nxalias "${name}_sensor_ch1"
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor/ch2 plain user float
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 control true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 data true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 mutable true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 nxsave true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 units K
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 oldval 0.0
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 type "part"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch2 nxalias "${name}_sensor_ch2"
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor/ch3 plain user float
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 control true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 data true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 mutable true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 nxsave true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 units K
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 oldval 0.0
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 type "part"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch3 nxalias "${name}_sensor_ch3"
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor/ch4 plain user float
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 control true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 data true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 mutable true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 nxsave true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 units K
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 oldval 0.0
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 type "part"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch4 nxalias "${name}_sensor_ch4"
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor/ch5 plain user float
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 control true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 data true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 mutable true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 nxsave true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 units K
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 oldval 0.0
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 type "part"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch5 nxalias "${name}_sensor_ch5"
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor/ch6 plain user float
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 control true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 data true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 mutable true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 nxsave true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 units K
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 oldval 0.0
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 type "part"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch6 nxalias "${name}_sensor_ch6"
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor/ch7 plain user float
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 control true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 data true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 mutable true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 nxsave true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 units K
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 oldval 0.0
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 type "part"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch7 nxalias "${name}_sensor_ch7"
|
||||||
|
|
||||||
|
hfactory ${scobj_hpath}/sensor/ch8 plain user float
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 control true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 data true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 mutable true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 nxsave true
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 units K
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 oldval 0.0
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 sdsinfo "::nexus::scobj::sdsinfo"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 type "part"
|
||||||
|
hsetprop ${scobj_hpath}/sensor/ch8 nxalias "${name}_sensor_ch8"
|
||||||
|
hsetprop ${scobj_hpath} klass environment
|
||||||
|
hsetprop ${scobj_hpath} debug_threshold 5
|
||||||
|
# mkDriver hook code goes here
|
||||||
|
} catch_message ]
|
||||||
|
handle_exception ${catch_status} ${catch_message}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace eval ::scobj::lakeshore_218 {
|
||||||
|
namespace export debug_threshold
|
||||||
|
namespace export debug_log
|
||||||
|
namespace export sics_log
|
||||||
|
namespace export mkDriver
|
||||||
|
}
|
||||||
|
|
||||||
|
proc add_lakeshore_218 {name IP port} {
|
||||||
|
set catch_status [ catch {
|
||||||
|
::scobj::lakeshore_218::sics_log 9 "add_lakeshore_218 ${name} ${IP} ${port}"
|
||||||
|
if {[string equal -nocase [SplitReply [environment_simulation]] "false"]} {
|
||||||
|
if {[string equal -nocase "aqadapter" "${IP}"]} {
|
||||||
|
::scobj::lakeshore_218::sics_log 9 "makesctcontroller sct_${name} aqadapter ${port}"
|
||||||
|
makesctcontroller sct_${name} aqadapter ${port}
|
||||||
} else {
|
} else {
|
||||||
set comm "$cmd B"
|
::scobj::lakeshore_218::sics_log 9 "makesctcontroller sct_${name} std ${IP}:${port}"
|
||||||
|
makesctcontroller sct_${name} std ${IP}:${port}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return -code error "in getValue: error input Ch ID"
|
::scobj::lakeshore_218::sics_log 9 "[environment_simulation] => No sctcontroller for lakeshore_218"
|
||||||
}
|
}
|
||||||
sct send "$comm\r\n"
|
::scobj::lakeshore_218::sics_log 1 "::scobj::lakeshore_218::mkDriver sct_${name} ${name}"
|
||||||
} message ]} {
|
::scobj::lakeshore_218::mkDriver sct_${name} ${name}
|
||||||
return -code error "in getValue: $message"
|
} catch_message ]
|
||||||
}
|
handle_exception ${catch_status} ${catch_message}
|
||||||
after 1000
|
|
||||||
return $nextState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
##
|
puts stdout "file evaluation of sct_lakeshore_218.tcl"
|
||||||
# @brief Reads the value of a read-node typically following a query command sent to the device
|
::scobj::lakeshore_218::sics_log 9 "file evaluation of sct_lakeshore_218.tcl"
|
||||||
# rdValue is the default nextState for getValue() and setValue()
|
|
||||||
# @param idx indicates which control loop or which input channel the command belongs to
|
|
||||||
# @return idle Always returns system state idle - command sequence completed.
|
|
||||||
proc ::scobj::ls218::rdValue {nodeName varName idx} {
|
|
||||||
#variable logString
|
|
||||||
|
|
||||||
if {[ catch {
|
proc ::scobj::lakeshore_218::read_config {} {
|
||||||
set replyData [string trimright [sct result] " \r\n"]
|
set catch_status [ catch {
|
||||||
|
set ns "::scobj::lakeshore_218"
|
||||||
if {[string first "ASCERR" $replyData] != -1} {
|
dict for {k v} $::config_dict {
|
||||||
sct geterror $replyData
|
if { [dict exists $v "driver"] } {
|
||||||
return -code error "Error in LS218 Response: $replyData"
|
if { [dict get $v "driver"] == "lakeshore_218" } {
|
||||||
} elseif {[string length $replyData] < 1} {
|
if { [dict get $v enabled] } {
|
||||||
return -code error "Error in LS218: no message returned from device"
|
set name [dict get $v name]
|
||||||
} else {
|
if { ![string equal -nocase [SplitReply [environment_simulation]] "false"] } {
|
||||||
set fields [split $replyData ,]
|
set asyncqueue "null"
|
||||||
set curValue $replyData
|
${ns}::sics_log 9 "[environment_simulation] => using null asyncqueue"
|
||||||
}
|
} elseif { [dict exists $v "asyncqueue"] } {
|
||||||
|
set asyncqueue [dict get $v "asyncqueue"]
|
||||||
switch -exact $varName {
|
} else {
|
||||||
"alarm" { if {[lindex $fields 0] == 0} {
|
if { [dict exists $v "asyncprotocol"] } {
|
||||||
hset $nodeName/offOn off
|
set asyncprotocol [dict get $v "asyncprotocol"]
|
||||||
} else {
|
} else {
|
||||||
hset $nodeName/offOn on
|
set asyncprotocol ${name}_protocol
|
||||||
}
|
MakeAsyncProtocol ${asyncprotocol}
|
||||||
switch -exact [lindex $fields 1] {
|
if { [dict exists $v "terminator"] } {
|
||||||
1 {hset $nodeName/source Kelvin}
|
${asyncprotocol} sendterminator "[dict get $v "terminator"]"
|
||||||
2 {hset $nodeName/source Celsius}
|
${asyncprotocol} replyterminator "[dict get $v "terminator"]"
|
||||||
3 {hset $nodeName/source "Sensor Units"}
|
}
|
||||||
4 {hset $nodeName/source "Linear data"}
|
}
|
||||||
default {hset $nodeName/source UNKNOW}
|
set asyncqueue ${name}_queue
|
||||||
}
|
set IP [dict get $v ip]
|
||||||
hset $nodeName/highValue [lindex $fields 2]
|
set PORT [dict get $v port]
|
||||||
hset $nodeName/lowValue [lindex $fields 3]
|
MakeAsyncQueue ${asyncqueue} ${asyncprotocol} ${IP} ${PORT}
|
||||||
hset $nodeName/deadband [lindex $fields 4]
|
if { [dict exists $v "timeout"] } {
|
||||||
hset $nodeName/latchEnable [lindex $fields 5]
|
${asyncqueue} timeout "[dict get $v "timeout"]"
|
||||||
}
|
}
|
||||||
"aStatus" { if {[lindex $fields 0] == 0} {
|
}
|
||||||
hset $nodeName/highStatus Unactivated
|
add_lakeshore_218 ${name} "aqadapter" ${asyncqueue}
|
||||||
} else {
|
}
|
||||||
hset $nodeName/highStatus Activated
|
|
||||||
}
|
|
||||||
if {[lindex $fields 1] == 0} {
|
|
||||||
hset $nodeName/lowStatus Unactivated
|
|
||||||
} else {
|
|
||||||
hset $nodeName/lowStatus Activated
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Celsius" { hset $nodeName [lindex $fields 0]
|
|
||||||
set curValue [lindex $fields 0]
|
|
||||||
}
|
|
||||||
"CurveHd" { hset $nodeName/curve [lindex $fields 0]
|
|
||||||
hset $nodeName/name [lindex $fields 1]
|
|
||||||
hset $nodeName/SN [lindex $fields 2]
|
|
||||||
switch -exact [lindex $fields 3] {
|
|
||||||
2 {hset $nodeName/format V/K}
|
|
||||||
3 {hset $nodeName/format Ohm/K}
|
|
||||||
4 {hset $nodeName/format "log Ohm/K"}
|
|
||||||
default {}
|
|
||||||
}
|
|
||||||
hset $nodeName/limitValue [lindex $fields 4]
|
|
||||||
switch -exact [lindex $fields 5] {
|
|
||||||
1 {hset $nodeName/coefficient negative}
|
|
||||||
2 {hset $nodeName/coefficient positive}
|
|
||||||
default {hset $nodeName/coefficient UNKNOW}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"CurveID" { set ind [lindex $fields 0]
|
|
||||||
if {$ind == 0} {
|
|
||||||
hset $nodeName none
|
|
||||||
} elseif { 1 <= $ind <= 5} {
|
|
||||||
hset $nodeName "Standard Diode Curves"
|
|
||||||
} elseif { 6 <= $ind <= 9} {
|
|
||||||
hset $nodeName "Standard Platium Curves"
|
|
||||||
} elseif { 21 <= $ind <= 28 } {
|
|
||||||
hset $nodeName "User Curves"
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"control" { set ind [lindex $fields 0]
|
|
||||||
if {$ind == 0} {
|
|
||||||
hset $nodeName off
|
|
||||||
} elseif {$ind == 1} {
|
|
||||||
hset $nodeName on
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"inputType" { switch -exact [lindex $fields 0] {
|
|
||||||
0 { hset $nodeName "2.5V Diode"}
|
|
||||||
1 { hset $nodeName "7.5V Diode"}
|
|
||||||
2 { hset $nodeName "250 Ohms Platinum"}
|
|
||||||
3 { hset $nodeName "500 Ohms Platinum"}
|
|
||||||
4 { hset $nodeName "5K Ohms Platinum"}
|
|
||||||
5 { hset $nodeName "Cernox"}
|
|
||||||
default { hset $nodeName UNKNOW}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"Kelvin" { hset $nodeName $fields
|
|
||||||
#append $logString " Kelvin - $fields;"
|
|
||||||
set curValue $fields
|
|
||||||
}
|
|
||||||
"Linear" { hset $nodeName/varM [lindex $fields 0]
|
|
||||||
hset $nodeName/varB [lindex $fields 2]
|
|
||||||
switch -exact [lindex $fields 1] {
|
|
||||||
1 { hset $nodeName/xSource Kelvin}
|
|
||||||
2 { hset $nodeName/xSource Celsius}
|
|
||||||
3 { hset $nodeName/xSource "sensor units"}
|
|
||||||
default { hset $nodeName/xSource UNKNOW}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"LinearEquData" { hset $nodeName $fields
|
|
||||||
set curValue $fields
|
|
||||||
}
|
|
||||||
"mnmxSource" { switch -exact [lindex $fields 0] {
|
|
||||||
1 { hset $nodeName Kelvin}
|
|
||||||
2 { hset $nodeName Celsius}
|
|
||||||
3 { hset $nodeName "sensor units"}
|
|
||||||
4 { hset $nodeName "linear data"}
|
|
||||||
default { hset $nodeName UNKNOW}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"mnmxValue" { hset $nodeName "[lindex $fields 0] , [lindex $fields 1]"}
|
|
||||||
"status" {
|
|
||||||
# RDGST? chID Reads input status returns an integer with the following meaning
|
|
||||||
# Bit Weighting StatusIndicator
|
|
||||||
# 4 16 temp underrange
|
|
||||||
# 5 32 temp overrange
|
|
||||||
# 6 64 units under range
|
|
||||||
# 7 128 untis over range
|
|
||||||
set field [string trimleft $fields 0]
|
|
||||||
if {[string length $field] == 0} {
|
|
||||||
set field 0
|
|
||||||
}
|
|
||||||
|
|
||||||
set str ""
|
|
||||||
set i [format %x $field]
|
|
||||||
set i [expr 0x$i >> 4]
|
|
||||||
set bitValue [expr 0x$i & 0x01]
|
|
||||||
if {$bitValue == 1} { append str "temp underrange, " }
|
|
||||||
set i [expr 0x$i >> 1]
|
|
||||||
set bitValue [expr 0x$i & 0x01]
|
|
||||||
if {$bitValue == 1} { append str "temp overrange, " }
|
|
||||||
set i [expr 0x$i >> 1]
|
|
||||||
set bitValue [expr 0x$i & 0x01]
|
|
||||||
if {$bitValue == 1} { append str "units under range, " }
|
|
||||||
set i [expr 0x$i >> 1]
|
|
||||||
set bitValue [expr 0x$i & 0x01]
|
|
||||||
if {$bitValue == 1} { append str "untis over range" }
|
|
||||||
|
|
||||||
hset $nodeName $str
|
|
||||||
}
|
|
||||||
"SensorUnitValue" { hset $nodeName $fields
|
|
||||||
#append $logString " SensorUnitValue - $fields;"
|
|
||||||
set curValue $fields
|
|
||||||
}
|
|
||||||
"data" { hset $nodeName $fields
|
|
||||||
set curValue $fields
|
|
||||||
}
|
|
||||||
"aOutput" { switch -exact [lindex $fields 0] {
|
|
||||||
0 { hset $nodeName/bipolarEnable "positive only" }
|
|
||||||
1 { hset $nodeName/bipolarEnable "bipolar" }
|
|
||||||
default {}
|
|
||||||
}
|
|
||||||
switch -exact [lindex $fields 1] {
|
|
||||||
0 { hset $nodeName/monitorMode off }
|
|
||||||
1 { hset $nodeName/monitorMode input }
|
|
||||||
2 { hset $nodeName/monitorMode manual }
|
|
||||||
default { hset $nodeName/monitorMode UNKNOW }
|
|
||||||
}
|
|
||||||
hset $nodeName/inputChID [lindex $fields 2]
|
|
||||||
switch -exact [lindex $fields 3] {
|
|
||||||
1 { hset $nodeName/source Kelvin}
|
|
||||||
2 { hset $nodeName/source Celsius}
|
|
||||||
3 { hset $nodeName/source "sensor units"}
|
|
||||||
4 { hset $nodeName/source "linear data"}
|
|
||||||
default { hset $nodeName/source UNKNOW}
|
|
||||||
}
|
|
||||||
hset $nodeName/highValue [lindex $fields 4]
|
|
||||||
hset $nodeName/lowValue [lindex $fields 5]
|
|
||||||
hset $nodeName/manualValue [lindex $fields 6]
|
|
||||||
}
|
|
||||||
"IDN" { hset $nodeName/manufacturer [lindex $fields 0]
|
|
||||||
hset $nodeName/model [lindex $fields 1]
|
|
||||||
hset $nodeName/serialNumber [lindex $fields 2]
|
|
||||||
hset $nodeName/firmwareDate [lindex $fields 3]
|
|
||||||
}
|
|
||||||
"logStatus" { switch -exact [lindex $fields 0] {
|
|
||||||
0 { hset $nodeName off }
|
|
||||||
1 { hset $nodeName on }
|
|
||||||
default { hset $nodeName UNKNOW }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"relay" { switch -exact [lindex $fields 0] {
|
|
||||||
0 { hset $nodeName/mode off }
|
|
||||||
1 { hset $nodeName/mode on }
|
|
||||||
default { hset $nodeName/mode UNKNOW }
|
|
||||||
}
|
|
||||||
hset $nodeName/input [lindex $fields 1]
|
|
||||||
switch -exact [lindex $fields 2] {
|
|
||||||
0 { hset $nodeName/alarmType "low Alarm" }
|
|
||||||
1 { hset $nodeName/alarmType "High Alarm" }
|
|
||||||
2 { hset $nodeName/alarmType "Both Alarm" }
|
|
||||||
default { hset $nodeName/alarmType UNKNOW }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default { return -code error "in rdValue: wrong input parameter"}
|
|
||||||
}
|
|
||||||
if {$curValue != [sct oldval]} {
|
|
||||||
sct oldval $curValue
|
|
||||||
sct update $curValue
|
|
||||||
sct utime readtime
|
|
||||||
}
|
|
||||||
} message ]} {
|
|
||||||
return -code error "in rdValue: $message "
|
|
||||||
}
|
|
||||||
return idle
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
# @brief createNode() creates a node for the given nodename with the properties and virtual
|
|
||||||
# function names provided
|
|
||||||
# @param nodeType represent for sub-tree inputNode, outputNode and otherNode
|
|
||||||
# @param scobj_hpath string variable holding the path to the object's base node in sics (/sample/tc1)
|
|
||||||
# @param sct_controller name of the ls218 scriptcontext object (typically sct_ls218_tc1 or tc2)
|
|
||||||
# @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 pollEnabled set to 1 if the node property pollable is to be enabled (node gets read every 5 secs)
|
|
||||||
# @param idx indicates which control loop or which input channel the command corresponds to
|
|
||||||
# @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 hdbEnable set to 1 if need to create a HDB node, otherwise ignore all following parameters
|
|
||||||
# @param klasse Nexus class name (?)
|
|
||||||
# @param control attribute for HDB tree
|
|
||||||
# @param data attribute for HDB tree
|
|
||||||
# @param priv attribute for HDB tree
|
|
||||||
# @param type attribute for HDB tree
|
|
||||||
# @param nxsave attribute for HDB tree
|
|
||||||
# @param mutable attribute for HDB tree
|
|
||||||
# @param nxalias attribute for HDB tree
|
|
||||||
# @return OK
|
|
||||||
|
|
||||||
proc createNode {scobj_hpath idx sct_controller cmdGroup varName readable pollEnabled dataType permission rdCmd chID rdFunc} {
|
|
||||||
# It is a command that is supported by the device
|
|
||||||
if {[ catch {
|
|
||||||
set ns ::scobj::ls218
|
|
||||||
|
|
||||||
if {$idx > 0} {
|
|
||||||
set channel ch$idx
|
|
||||||
set basePath $scobj_hpath/$channel
|
|
||||||
} else {
|
|
||||||
set basePath $scobj_hpath
|
|
||||||
}
|
|
||||||
|
|
||||||
if {1 > [string length $cmdGroup]} {
|
|
||||||
set nodeName $basePath/$varName
|
|
||||||
} else {
|
|
||||||
set nodeName $basePath/$cmdGroup/$varName
|
|
||||||
}
|
|
||||||
|
|
||||||
hfactory $nodeName plain $permission $dataType
|
|
||||||
switch -exact $dataType {
|
|
||||||
"none" {hset $nodeName none}
|
|
||||||
"text" {hset $nodeName UNKNOWN}
|
|
||||||
"int" {hset $nodeName 0}
|
|
||||||
"float" {hset $nodeName 0.0}
|
|
||||||
default {hset $nodeName UNKNOWN}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$readable == 1} {
|
|
||||||
hsetprop $nodeName read ${ns}::getValue $idx $rdCmd $chID rdFuncState
|
|
||||||
hsetprop $nodeName rdFuncState ${ns}::rdValue $nodeName $varName $idx
|
|
||||||
hsetprop $nodeName oldval UNKNOW
|
|
||||||
}
|
|
||||||
if {$pollEnabled == 1} {
|
|
||||||
if {[SplitReply [environment_simulation]]=="false"} {
|
|
||||||
# puts "enabling polling for $nodeName"
|
|
||||||
$sct_controller poll $nodeName 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} message ]} {
|
|
||||||
return -code error "in createNode $message"
|
|
||||||
}
|
|
||||||
return OK
|
|
||||||
}
|
|
||||||
|
|
||||||
# create parent HDB nods
|
|
||||||
proc createParentHDBNode {hPath klass priv type control data} {
|
|
||||||
|
|
||||||
if {[ catch {
|
|
||||||
hsetprop $hPath klass $klass
|
|
||||||
hsetprop $hPath privilege $priv
|
|
||||||
hsetprop $hPath type $type
|
|
||||||
hsetprop $hPath control $control
|
|
||||||
hsetprop $hPath data $data
|
|
||||||
} message ]} {
|
|
||||||
return -code error "in createParentHDBNode $message"
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK
|
|
||||||
}
|
|
||||||
|
|
||||||
##
|
|
||||||
# @brief mkLS218() creates a scriptcontext object for a Lakeshore 218 temperature controller
|
|
||||||
# @param sct_controller name of the ls218 scriptcontext object (typically sct_ls218_tc1 or tc2)
|
|
||||||
# @param klasse Nexus class name (?), typically 'environment'
|
|
||||||
# @param tempobj short name for the temperature controller scriptcontext object (typ. tc1 or tc2)
|
|
||||||
# @param tol temperature tolerance in Kelvin (typ. 1)
|
|
||||||
# @return nothing (well, the sct object)
|
|
||||||
proc ::scobj::ls218::mkLS218 {argList} {
|
|
||||||
#variable logString
|
|
||||||
|
|
||||||
if {[ catch {
|
|
||||||
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)
|
|
||||||
|
|
||||||
set scobj_hpath /sics/$pa(NAME)
|
|
||||||
|
|
||||||
makesctcontroller sct_$pa(NAME) std $pa(IP):$pa(PORT)
|
|
||||||
|
|
||||||
# create parent nodes for input, output, and relay
|
|
||||||
foreach chanType {input output relay} {
|
|
||||||
switch -exact $chanType {
|
|
||||||
"input" {set chanList $pa(INPUTCHAN)}
|
|
||||||
"output" {set chanList $pa(OUTPUTCHAN)}
|
|
||||||
"relay" {set chanList $pa(RELAYCHAN)}
|
|
||||||
}
|
|
||||||
if {[string length $chanList] > 0} {
|
|
||||||
set hPath $scobj_hpath/$chanType
|
|
||||||
hfactory $hPath plain user none
|
|
||||||
hset $hPath UNKNOWN
|
|
||||||
foreach idx $chanList {
|
|
||||||
set hPath $scobj_hpath/$chanType/ch$idx
|
|
||||||
hfactory $hPath plain user none
|
|
||||||
hset $hPath UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# create parent node for other
|
|
||||||
set hPath $scobj_hpath/other
|
|
||||||
hfactory $hPath plain user none
|
|
||||||
hset $hPath UNKNOWN
|
|
||||||
|
|
||||||
# Create state machines for the following device commands (non-polled entries are place-holders
|
|
||||||
# for manually maintained nodes, like the selector for the input that provides the sample temperature
|
|
||||||
# 'sampleSensor', the sample tempreature reading 'Tsample', the input that provides for the controlLoop
|
|
||||||
# 'value', and the control loop parameters in human-rdadable form 'ctrl_Loop_x')
|
|
||||||
# Note that drivable nodes require the index of the control loop in their call to halt()
|
|
||||||
# Nodes appear in gumtree in the order in which they are created here.
|
|
||||||
#
|
|
||||||
# Initialise the model-dependent list of supported device commands
|
|
||||||
# RdWrPlDrIdx
|
|
||||||
# cmdGroup subdirectory (below /sample/tc*/) in which the node is to be created
|
|
||||||
# varName name of the actual node typically representing one device command
|
|
||||||
#
|
|
||||||
# readable set to 1 if the node represents a query command, 0 if it is not
|
|
||||||
# pollEnabled set to 1 if the node property pollable is to be enabled (node gets read every 5 secs)
|
|
||||||
#
|
|
||||||
# dataType data type of the node, must be one of none, int, float, text
|
|
||||||
# permission defines what user group may read/write to this node (is one of spy, user, manager)
|
|
||||||
# rdCmd actual device query command to be sent to the device
|
|
||||||
# chID set to 1 presenting a need to specify the ID of input (1-8) or output (1-2) channels
|
|
||||||
# rdFunc nextState Function to be called after the getValue function, typically rdValue()
|
|
||||||
# hdbTree set to 1 if a HDB needs to be created at the node
|
|
||||||
# klass type of klass of the HDB node
|
|
||||||
# control type of contrl of the HDB node
|
|
||||||
# data type of data of the HDB node
|
|
||||||
# priv type of previlige level of the HDB node
|
|
||||||
# type type of the HDB node
|
|
||||||
# nxsave save the node or not, values are true or false
|
|
||||||
# mutable mutable control or not, values are true or false
|
|
||||||
# nxalias alias name of the node in the HDB tree
|
|
||||||
###########################################################################################################
|
|
||||||
|
|
||||||
set inputNodes {
|
|
||||||
{} alarm 1 1 none user {ALARM?} 1 {rdValue}
|
|
||||||
alarm offOn 0 0 text user {} 0 {}
|
|
||||||
alarm source 0 0 text user {} 0 {}
|
|
||||||
alarm highValue 0 0 float user {} 0 {}
|
|
||||||
alarm lowValue 0 0 float user {} 0 {}
|
|
||||||
alarm deadband 0 0 float user {} 0 {}
|
|
||||||
alarm latchEnable 0 0 int user {} 0 {}
|
|
||||||
{} aStatus 1 1 none user {ALARMST?} 1 {rdValue}
|
|
||||||
aStatus highStatus 0 0 text user {} 0 {}
|
|
||||||
aStatus lowStatus 0 0 text user {} 0 {}
|
|
||||||
{} Celsius 1 1 float user {CRDG?} 1 {rdValue}
|
|
||||||
{} CurveHd 1 1 none user {CRVHDR?} 0 {rdValue}
|
|
||||||
CurveHd curve 0 0 text user {} 0 {}
|
|
||||||
CurveHd name 0 0 text user {} 0 {}
|
|
||||||
CurveHd SN 0 0 text user {} 0 {}
|
|
||||||
CurveHd format 0 0 text user {} 0 {}
|
|
||||||
CurveHd limitValue 0 0 float user {} 0 {}
|
|
||||||
CurveHd coefficient 0 0 text user {} 0 {}
|
|
||||||
{} CurveID 1 1 text user {INCRV?} 1 {rdValue}
|
|
||||||
{} control 1 1 text user {INPUT?} 1 {rdValue}
|
|
||||||
{} inputType 1 1 text user {INTYPE?} G {rdValue}
|
|
||||||
{} Kelvin 1 1 float user {KRDG?} 1 {rdValue}
|
|
||||||
{} Linear 1 1 none user {LINEAR?} 1 {rdValue}
|
|
||||||
Linear varM 0 0 float user {} 0 {}
|
|
||||||
Linear xSource 0 0 text user {} 0 {}
|
|
||||||
Linear varB 0 0 float user {} 0 {}
|
|
||||||
{} LinearEquData 1 1 float user {LRDG?} 1 {rdValue}
|
|
||||||
{} mnmxSource 1 1 text user {MNMX?} 1 {rdValue}
|
|
||||||
{} mnmxValue 1 1 text user {MNMXRDG?} 1 {rdValue}
|
|
||||||
{} status 1 1 text user {RDGST?} 1 {rdValue}
|
|
||||||
{} SensorUnitValue 1 1 float user {SRDG?} 1 {rdValue}
|
|
||||||
}
|
|
||||||
|
|
||||||
set outputNodes {
|
|
||||||
{} data 1 1 float user {AOUT?} 1 {rdValue}
|
|
||||||
{} aOutput 1 1 none user {ANALOG?} 1 {rdValue}
|
|
||||||
aOutput bipolarEnable 0 0 text user {} 0 {}
|
|
||||||
aOutput monitorMode 0 0 text user {} 0 {}
|
|
||||||
aOutput inputChID 0 0 int user {} 0 {}
|
|
||||||
aOutput source 0 0 text user {} 0 {}
|
|
||||||
aOutput highValue 0 0 float user {} 0 {}
|
|
||||||
aOutput lowValue 0 0 float user {} 0 {}
|
|
||||||
aOutput manualValue 0 0 int user {} 0 {}
|
|
||||||
}
|
|
||||||
|
|
||||||
set relayNodes {
|
|
||||||
{} relay 1 1 none user {RELAY?} 1 {rdValue}
|
|
||||||
relay mode 0 0 text user {} 0 {}
|
|
||||||
relay input 0 0 int user {} 0 {}
|
|
||||||
relay alarmType 0 0 text user {} 0 {}
|
|
||||||
}
|
|
||||||
|
|
||||||
set otherNodes {
|
|
||||||
{} IDN 1 1 none user {*IDN?} 0 {rdValue}
|
|
||||||
IDN manufacturer 0 0 text user {} 0 {}
|
|
||||||
IDN model 0 0 text user {} 0 {}
|
|
||||||
IDN serialNumber 0 0 text user {} 0 {}
|
|
||||||
IDN firmwareDate 0 0 text user {} 0 {}
|
|
||||||
{} logStatus 1 1 text user {LOG?} 0 {rdValue}
|
|
||||||
}
|
|
||||||
|
|
||||||
# create sub-tree for all 8 input channels
|
|
||||||
foreach idx $pa(INPUTCHAN) {
|
|
||||||
foreach {cmdGroup varName readable pollEnabled dataType permission rdCmd chID rdFunc} $inputNodes {
|
|
||||||
createNode $scobj_hpath/input $idx sct_$pa(NAME) $cmdGroup $varName $readable $pollEnabled $dataType $permission $rdCmd $chID $rdFunc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# create sub-tree for all 2 output channels
|
|
||||||
foreach idx $pa(OUTPUTCHAN) {
|
|
||||||
foreach {cmdGroup varName readable pollEnabled dataType permission rdCmd chID rdFunc} $outputNodes {
|
|
||||||
createNode $scobj_hpath/output $idx sct_$pa(NAME) $cmdGroup $varName $readable $pollEnabled $dataType $permission $rdCmd $chID $rdFunc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# create sub-tree for all 8 relay channels
|
|
||||||
foreach idx $pa(RELAYCHAN) {
|
|
||||||
foreach {cmdGroup varName readable pollEnabled dataType permission rdCmd chID rdFunc} $relayNodes {
|
|
||||||
createNode $scobj_hpath/relay $idx sct_$pa(NAME) $cmdGroup $varName $readable $pollEnabled $dataType $permission $rdCmd $chID $rdFunc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# create "other" sub-tree
|
|
||||||
foreach {cmdGroup varName readable pollEnabled dataType permission rdCmd chID rdFunc} $otherNodes {
|
|
||||||
createNode $scobj_hpath/other 0 sct_$pa(NAME) $cmdGroup $varName $readable $pollEnabled $dataType $permission $rdCmd $chID $rdFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
# create HDB tree
|
|
||||||
|
|
||||||
::scobj::set_required_props $scobj_hpath
|
|
||||||
|
|
||||||
foreach {hPath klass control data priv type} {
|
|
||||||
ls218 environment true true spy part
|
|
||||||
input NXsensor true true user NXsensor
|
|
||||||
output NXsensor true true user NXsensor
|
|
||||||
} {
|
|
||||||
switch -exact $hPath {
|
|
||||||
"ls218" { set curPath /sics/$hPath
|
|
||||||
createParentHDBNode $curPath $klass $priv $type $control $data
|
|
||||||
}
|
|
||||||
default { switch -exact $hPath {
|
|
||||||
"input" {set chanList $pa(INPUTCHAN)}
|
|
||||||
"output" {set chanList $pa(OUTPUTCHAN)}
|
|
||||||
}
|
|
||||||
if {[string length $chanList] > 0} {
|
|
||||||
set curPath /sics/ls218/$hPath
|
|
||||||
createParentHDBNode $curPath $klass $priv $type $control $data
|
|
||||||
foreach idx $chanList {
|
|
||||||
set curPath /sics/ls218/$hPath/ch$idx
|
|
||||||
createParentHDBNode $curPath $klass $priv $type $control $data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch_message ]
|
||||||
if {[string length $pa(INPUTCHAN)] > 0} {
|
handle_exception ${catch_status} ${catch_message}
|
||||||
foreach idx $pa(INPUTCHAN) {
|
|
||||||
foreach {item klass control data nxsave mutable priv alias} {
|
|
||||||
Celsius sensor true true true true user Celsius
|
|
||||||
Kelvin sensor true true true true user Kelvin
|
|
||||||
SensorUnitValue sensor true true true true user SensorUnitValue
|
|
||||||
} {
|
|
||||||
set hpath /sics/ls218/input/ch$idx/$item
|
|
||||||
hsetprop $hpath nxalias ls218-input-ch$idx-$alias
|
|
||||||
hsetprop $hpath klass $klass
|
|
||||||
hsetprop $hpath privilege $priv
|
|
||||||
hsetprop $hpath control $control
|
|
||||||
hsetprop $hpath data $data
|
|
||||||
hsetprop $hpath nxsave $nxsave
|
|
||||||
hsetprop $hpath mutable $mutable
|
|
||||||
hsetprop $hpath sdsinfo ::nexus::scobj::sdsinfo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if {[string length $pa(OUTPUTCHAN)] > 0} {
|
|
||||||
foreach idx $pa(OUTPUTCHAN) {
|
|
||||||
set hpath /sics/ls218/output/ch$idx/data
|
|
||||||
hsetprop $hpath nxalias ls218-output-ch$idx-data
|
|
||||||
hsetprop $hpath klass sensor
|
|
||||||
hsetprop $hpath privilege user
|
|
||||||
hsetprop $hpath control true
|
|
||||||
hsetprop $hpath data true
|
|
||||||
hsetprop $hpath nxsave true
|
|
||||||
hsetprop $hpath mutable true
|
|
||||||
hsetprop $hpath sdsinfo ::nexus::scobj::sdsinfo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::scobj::hinitprops $pa(NAME)
|
|
||||||
|
|
||||||
} message ]} {
|
|
||||||
return -code error "in mkLS218 $message"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# end of namespace ::scobj::ls218
|
if { [info exists ::config_dict] } {
|
||||||
|
::scobj::lakeshore_218::read_config
|
||||||
# Main process call
|
} else {
|
||||||
# @param name short name for the Lakeshore Temp controller 218
|
::scobj::lakeshore_218::sics_log 5 "No config dict"
|
||||||
# @param IP IP address of the device (e.g. IP of moxabox that hooks up to the AG1010)
|
|
||||||
# @param port port number on the moxabox (typ. 4001, 4002, 4003, or 4004)
|
|
||||||
# @param turning if the parameter is turnable and can be set from the Gumtree
|
|
||||||
# @internal time internal in polling the nodes
|
|
||||||
# @return nothing (well, the sct object)
|
|
||||||
|
|
||||||
MakeAsyncProtocol std
|
|
||||||
MakeAsyncQueue ls218 std 137.157.202.214 4002
|
|
||||||
::scobj::ls218::mkLS218 {
|
|
||||||
name ls218
|
|
||||||
IP aqadapter
|
|
||||||
PORT ls218
|
|
||||||
tuning 1
|
|
||||||
interval 5
|
|
||||||
inputChan {1 2 3 4 5 6 7 8}
|
|
||||||
outputChan {1 2}
|
|
||||||
relayChan {1 2 3 4 5 6 7 8}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user