Oxford ITC502 and ITC503 Temperature Controllers
r2913 | dcl | 2010-05-10 10:02:42 +1000 (Mon, 10 May 2010) | 2 lines
This commit is contained in:
110
site_ansto/hardsup/sct_oxfordprot.c
Normal file
110
site_ansto/hardsup/sct_oxfordprot.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/** @file Oxford protocol handler for script-context based controllers.
|
||||
*
|
||||
* If you 'send' commands to a oxford controller using this protocol you
|
||||
* will get one of three possible responses,
|
||||
* 1. A value
|
||||
* eg
|
||||
* 2. An acknowledgement (ie 'OK')
|
||||
* eg
|
||||
* sct_mc2 send "MOG"
|
||||
* OK
|
||||
* 3. An error message
|
||||
* eg
|
||||
* sct_mc2 send "BGG"
|
||||
* ASCERR: 20 Begin not valid with motor off (during read finished)
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <ascon.h>
|
||||
#include <ascon.i>
|
||||
#include <dynstring.h>
|
||||
|
||||
/** @brief Set line terminator before sending command
|
||||
*/
|
||||
int OxfordWriteStart(Ascon *a) {
|
||||
DynStringConcat(a->wrBuffer,"\r");
|
||||
a->state = AsconWriting;
|
||||
a->wrPos = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @brief Map oxford replies to OK, ASCERR:..., value.
|
||||
* You can use the first character to sort replies from a oxford controller
|
||||
* into four categories
|
||||
* First character is,
|
||||
* 'SPACE' This is followed by a value
|
||||
* '?' Error, use 'TC 1' to get error code and message.
|
||||
* ':' Command received, in response to commands which don't request data.
|
||||
* '1-9' First digit of error-code followed by error message. (in response to 'TC 1')
|
||||
*/
|
||||
int OxfordReading(Ascon *a) {
|
||||
int ret;
|
||||
char chr, ch[2];
|
||||
char* cp = NULL;
|
||||
|
||||
ret = AsconReadChar(a->fd, &chr);
|
||||
while (ret > 0) {
|
||||
if (chr != '\r') {
|
||||
DynStringConcatChar(a->rdBuffer, chr);
|
||||
ret = AsconReadChar(a->fd, &chr);
|
||||
}
|
||||
else {
|
||||
cp = GetCharArray(a->rdBuffer);
|
||||
chr = *cp;
|
||||
if (*cp == '?') { /* command was in error */
|
||||
a->state = AsconIdle;
|
||||
#if 0
|
||||
AsconError(a, GetCharArray(a->rdBuffer), 0);
|
||||
#else
|
||||
DynStringInsert(a->rdBuffer, "ASCERR:", 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
else if (GetDynStringLength(a->rdBuffer) == 1) { /* command was successful */
|
||||
DynStringReplace(a->rdBuffer, "OK", 0);
|
||||
a->state = AsconReadDone;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
a->state = AsconReadDone;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** brief Oxford protocol handler.
|
||||
* This handler formats commands (ie adds cr line terminator) and
|
||||
* sorts replies into standard responses of
|
||||
* <value>
|
||||
* OK
|
||||
* ASCERR:...
|
||||
*/
|
||||
int OxfordProtHandler(Ascon *a) {
|
||||
int ret;
|
||||
|
||||
switch(a->state){
|
||||
case AsconWriteStart:
|
||||
ret = OxfordWriteStart(a);
|
||||
return ret;
|
||||
break;
|
||||
case AsconReading:
|
||||
ret = OxfordReading(a);
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
ret = AsconStdHandler(a);
|
||||
return ret;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void AddOxfordProtocoll(){
|
||||
AsconProtocol *prot = NULL;
|
||||
|
||||
prot = calloc(sizeof(AsconProtocol), 1);
|
||||
prot->name = strdup("oxford");
|
||||
prot->init = AsconStdInit;
|
||||
prot->handler = OxfordProtHandler;
|
||||
AsconInsertProtocol(prot);
|
||||
}
|
||||
@@ -0,0 +1,519 @@
|
||||
# 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::itc500 {
|
||||
# Temperature controllers must have at least the following nodes
|
||||
# /tempcont/setpoint
|
||||
# /tempcont/sensor/value
|
||||
proc debug_log {args} {
|
||||
set fd [open "/tmp/itc500.log" a]
|
||||
puts $fd $args
|
||||
close $fd
|
||||
}
|
||||
|
||||
proc getValue {nextState cmd} {
|
||||
sct send $cmd
|
||||
return $nextState
|
||||
}
|
||||
proc setValue {nextState cmd} {
|
||||
set par [expr int(18 * [sct target])]
|
||||
sct send "$cmd $par"
|
||||
debug_log "setValue $cmd $par"
|
||||
return $nextState
|
||||
}
|
||||
|
||||
proc setPoint {tc_root nextState cmd} {
|
||||
set my_model "[SplitReply [hgetprop $tc_root/itc500_state my_model]]"
|
||||
if {$my_model == "ITC502"} {
|
||||
set par [expr int(10 * [sct target])]
|
||||
} else {
|
||||
set par "[sct target]"
|
||||
}
|
||||
hset $tc_root/status "busy"
|
||||
if {[sct writestatus] == "start"} {
|
||||
# Called by drive adapter
|
||||
hsetprop $tc_root/setpoint driving 1
|
||||
}
|
||||
sct send "$cmd$par"
|
||||
debug_log "setPoint $cmd$par"
|
||||
return $nextState
|
||||
}
|
||||
|
||||
proc rdValue {tc_root} {
|
||||
set data [sct result]
|
||||
if [ catch {
|
||||
debug_log "rdValue $tc_root [sct] result=$data"
|
||||
} message ] {
|
||||
debug_log "rdValue $tc_root failure"
|
||||
}
|
||||
switch -glob -- $data {
|
||||
"ASCERR:*" {
|
||||
sct geterror $data
|
||||
}
|
||||
default {
|
||||
set my_model "[SplitReply [hgetprop $tc_root/itc500_state my_model]]"
|
||||
if {[string index $data 0] == "R"} {
|
||||
set data [string range $data 1 end]
|
||||
if {$my_model == "ITC502"} {
|
||||
debug_log "rdValue $tc_root ITC502-a result=$data"
|
||||
set rslt [scan $data %d data]
|
||||
set data [expr $data / 10.0]
|
||||
debug_log "rdValue $tc_root ITC502-b result=$data"
|
||||
} elseif {$my_model == "ITC503"} {
|
||||
debug_log "rdValue $tc_root ITC503-a result=$data"
|
||||
set rslt [scan $data %f data]
|
||||
debug_log "rdValue $tc_root ITC503-b result=$data"
|
||||
}
|
||||
if {$data != [sct oldval]} {
|
||||
sct oldval $data
|
||||
sct update $data
|
||||
sct utime readtime
|
||||
debug_log "rdValue new data for $tc_root [sct] $my_model result=$data"
|
||||
}
|
||||
} else {
|
||||
sct geterror "SYNERR:$data"
|
||||
}
|
||||
}
|
||||
}
|
||||
return idle
|
||||
}
|
||||
|
||||
proc getState {tc_root nextState cmd} {
|
||||
set my_state "[SplitReply [hgetprop $tc_root/itc500_state my_state]]"
|
||||
if {$my_state == "STATE_V"} {
|
||||
set my_cmd "V"
|
||||
} elseif {$my_state == "STATE_X"} {
|
||||
set my_cmd "X"
|
||||
} elseif {$my_state == "STATE_C"} {
|
||||
set my_cmd "C1"
|
||||
} elseif {$my_state == "STATE_A0"} {
|
||||
set my_cmd "A0"
|
||||
} elseif {$my_state == "STATE_A"} {
|
||||
set auto 0
|
||||
if {[hval $tc_root/heater_auto] > 0} {
|
||||
set auto [expr $auto + 1]
|
||||
}
|
||||
if {[hval $tc_root/cooler_auto] > 0} {
|
||||
set auto [expr $auto + 2]
|
||||
}
|
||||
set my_cmd "A$auto"
|
||||
} elseif {$my_state == "STATE_H"} {
|
||||
set my_cmd "H[hval $tc_root/control_sensor]"
|
||||
} elseif {$my_state == "STATE_T0" || $my_state == "STATE_T"} {
|
||||
set my_cmd "T[SplitReply [hgetprop $tc_root/setpoint target]]"
|
||||
} elseif {$my_state == "STATE_F"} {
|
||||
set my_cmd "F[hval $tc_root/control_sensor]"
|
||||
} else {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_X"
|
||||
set my_cmd "X"
|
||||
}
|
||||
sct send "$my_cmd"
|
||||
debug_log "getState end $tc_root state=$my_state, cmd=$my_cmd"
|
||||
return $nextState
|
||||
}
|
||||
|
||||
proc checktol {tc_root currtime timecheck} {
|
||||
debug_log "checktol $tc_root $currtime $timecheck"
|
||||
set temp [hval $tc_root/sensor/value]
|
||||
set lotemp [expr [$tc_root/setpoint] - [hval $tc_root/tolerance]]
|
||||
set hitemp [expr [$tc_root/setpoint] + [hval $tc_root/tolerance]]
|
||||
if { $temp < $lotemp || $temp > $hitemp} {
|
||||
hset $tc_root/emon/isintol 0
|
||||
return 0
|
||||
} else {
|
||||
set timeout [hval $tc_root/tolerance/settletime]
|
||||
if {[expr $currtime - $timecheck] > $timeout} {
|
||||
hset $tc_root/emon/isintol 1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
##
|
||||
# @brief Reads the current itc500 state and error messages.
|
||||
proc rdState {tc_root} {
|
||||
set my_state "[SplitReply [hgetprop $tc_root/itc500_state my_state]]"
|
||||
set my_model "[SplitReply [hgetprop $tc_root/itc500_state my_model]]"
|
||||
debug_log "rdState $tc_root state=$my_state, response=[sct result], version=$my_model"
|
||||
if {$my_state == "STATE_V"} {
|
||||
set my_version "[sct result]"
|
||||
hsetprop $tc_root/itc500_state my_version "$my_version"
|
||||
if {[string range $my_version 0 5] == "ITC502"} {
|
||||
hsetprop $tc_root/itc500_state my_model "ITC502"
|
||||
} elseif {[string range $my_version 0 5] == "ITC503"} {
|
||||
hsetprop $tc_root/itc500_state my_model "ITC503"
|
||||
}
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_X"
|
||||
set my_model "[SplitReply [hgetprop $tc_root/itc500_state my_model]]"
|
||||
debug_log "rdState $tc_root state=$my_state, version=$my_model"
|
||||
# return idle
|
||||
return getState
|
||||
} elseif {$my_state == "STATE_X"} {
|
||||
hsetprop $tc_root/itc500_state my_status "[sct result]"
|
||||
set my_status "[SplitReply [hgetprop $tc_root/itc500_state my_status]]"
|
||||
debug_log "rdState my_status=$my_status"
|
||||
set rslt [scan $my_status "X%dA%dC%dS%dH%dL%d" the_x the_a the_c the_s the_h the_l]
|
||||
debug_log "rdState $tc_root status($rslt)= X$the_x A$the_a C$the_c S[format %02d $the_s] H$the_h L$the_l"
|
||||
set auto 0
|
||||
if {[hval $tc_root/heater_auto] > 0} {
|
||||
set auto [expr $auto + 1]
|
||||
}
|
||||
if {[hval $tc_root/cooler_auto] > 0} {
|
||||
set auto [expr $auto + 2]
|
||||
}
|
||||
if {$the_c != 1} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_C"
|
||||
} elseif {$the_h != [hval $tc_root/control_sensor]} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_A0"
|
||||
} elseif {$the_a != $auto} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_A"
|
||||
} elseif {[hpropexists $tc_root/setpoint target] && [SplitReply [hgetprop $tc_root/setpoint target]] != [hval $tc_root/setpoint]} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_T"
|
||||
} else {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_F"
|
||||
}
|
||||
hsetprop $tc_root/control_sensor oldval $the_h
|
||||
return getState
|
||||
} elseif {$my_state == "STATE_C"} {
|
||||
set my_status "[SplitReply [hgetprop $tc_root/itc500_state my_status]]"
|
||||
set rslt [scan $my_status "X%dA%dC%dS%dH%dL%d" the_x the_a the_c the_s the_h the_l]
|
||||
set auto 0
|
||||
if {[hval $tc_root/heater_auto] > 0} {
|
||||
set auto [expr $auto + 1]
|
||||
}
|
||||
if {[hval $tc_root/cooler_auto] > 0} {
|
||||
set auto [expr $auto + 2]
|
||||
}
|
||||
if {[hval $tc_root/control_sensor] != $the_h} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_A0"
|
||||
} elseif {$the_a != $auto} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_A"
|
||||
} elseif {[hpropexists $tc_root/setpoint target] && [SplitReply [hgetprop $tc_root/setpoint target]] != [hval $tc_root/setpoint]} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_T"
|
||||
} else {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_F"
|
||||
}
|
||||
return getState
|
||||
} elseif {$my_state == "STATE_A0"} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_H"
|
||||
return getState
|
||||
} elseif {$my_state == "STATE_H"} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_T0"
|
||||
return getState
|
||||
} elseif {$my_state == "STATE_T0"} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_A"
|
||||
return getState
|
||||
} elseif {$my_state == "STATE_T"} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_F"
|
||||
return getState
|
||||
} elseif {$my_state == "STATE_A"} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_F"
|
||||
return getState
|
||||
} elseif {$my_state == "STATE_F"} {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_X"
|
||||
} else {
|
||||
hsetprop $tc_root/itc500_state my_state "STATE_X"
|
||||
}
|
||||
set my_status "[SplitReply [hgetprop $tc_root/itc500_state my_status]]"
|
||||
debug_log "rdState my_status=$my_status"
|
||||
set rslt [scan $my_status "X%dA%dC%dS%dH%dL%d" the_x the_a the_c the_s the_h the_l]
|
||||
debug_log "rdState $tc_root status($rslt)= X$the_x A$the_a C$the_c S[format %02d $the_s] H$the_h L$the_l"
|
||||
set my_driving [SplitReply [hgetprop $tc_root/setpoint driving]]
|
||||
debug_log "rdState $tc_root: driving=$my_driving"
|
||||
if [ catch {
|
||||
set val "[hval $tc_root/setpoint]"
|
||||
} message ] {
|
||||
set val 0
|
||||
debug_log "rdState $tc_root: setpoint=failure"
|
||||
}
|
||||
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} {
|
||||
if {[hval $tc_root/control_sensor] == "3"} {
|
||||
set temp [hval $tc_root/sensor3/value]
|
||||
} elseif {[hval $tc_root/control_sensor] == "2"} {
|
||||
set temp [hval $tc_root/sensor2/value]
|
||||
} else {
|
||||
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
|
||||
debug_log "rdState driving $tc_root finished at $temp in ($lotemp, $hitemp)"
|
||||
}
|
||||
}
|
||||
return idle
|
||||
}
|
||||
|
||||
proc noResponse {} {
|
||||
return idle
|
||||
}
|
||||
proc wrtValue {wcmd args} {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
##
|
||||
# @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 {
|
||||
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
|
||||
}
|
||||
|
||||
proc mk_sct_oxford_itc500 {sct_controller klass tempobj tol} {
|
||||
if [ catch {
|
||||
set ns ::scobj::itc500
|
||||
|
||||
MakeSICSObj $tempobj SCT_OBJECT
|
||||
sicslist setatt $tempobj klass $klass
|
||||
sicslist setatt $tempobj long_name $tempobj
|
||||
|
||||
set scobj_hpath /sics/$tempobj
|
||||
hfactory $scobj_hpath/setpoint plain user float
|
||||
hsetprop $scobj_hpath/setpoint read ${ns}::getValue rdValue "R0"
|
||||
hsetprop $scobj_hpath/setpoint write ${ns}::setPoint $scobj_hpath noResponse "T"
|
||||
hsetprop $scobj_hpath/setpoint check ${ns}::check $scobj_hpath
|
||||
hsetprop $scobj_hpath/setpoint rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/setpoint noResponse ${ns}::noResponse
|
||||
hsetprop $scobj_hpath/setpoint oldval UNKNOWN
|
||||
hsetprop $scobj_hpath/setpoint driving 0
|
||||
hsetprop $scobj_hpath/setpoint writestatus UNKNOWN
|
||||
# Drive adapter interface
|
||||
hsetprop $scobj_hpath/setpoint checklimits ${ns}::check $scobj_hpath
|
||||
hsetprop $scobj_hpath/setpoint checkstatus ${ns}::drivestatus $scobj_hpath
|
||||
hsetprop $scobj_hpath/setpoint halt ${ns}::halt $scobj_hpath
|
||||
|
||||
hfactory $scobj_hpath/sensor plain spy none
|
||||
hfactory $scobj_hpath/sensor/value plain internal float
|
||||
hsetprop $scobj_hpath/sensor/value read ${ns}::getValue rdValue "R1"
|
||||
hsetprop $scobj_hpath/sensor/value rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/sensor/value oldval UNKNOWN
|
||||
hsetprop $scobj_hpath/sensor/value lowerlimit 1.5
|
||||
hsetprop $scobj_hpath/sensor/value upperlimit 250
|
||||
hsetprop $scobj_hpath/sensor/value units "K"
|
||||
|
||||
hfactory $scobj_hpath/sensor2 plain spy none
|
||||
hfactory $scobj_hpath/sensor2/value plain internal float
|
||||
hsetprop $scobj_hpath/sensor2/value read ${ns}::getValue rdValue "R2"
|
||||
hsetprop $scobj_hpath/sensor2/value rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/sensor2/value oldval UNKNOWN
|
||||
hsetprop $scobj_hpath/sensor2/value lowerlimit 0.25
|
||||
hsetprop $scobj_hpath/sensor2/value upperlimit 7
|
||||
hsetprop $scobj_hpath/sensor2/value units "K"
|
||||
|
||||
hfactory $scobj_hpath/sensor3 plain spy none
|
||||
hfactory $scobj_hpath/sensor3/value plain internal float
|
||||
hsetprop $scobj_hpath/sensor3/value read ${ns}::getValue rdValue "R3"
|
||||
hsetprop $scobj_hpath/sensor3/value rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/sensor3/value oldval UNKNOWN
|
||||
hsetprop $scobj_hpath/sensor3/value lowerlimit 1.0
|
||||
hsetprop $scobj_hpath/sensor3/value upperlimit 300
|
||||
hsetprop $scobj_hpath/sensor3/value units "K"
|
||||
|
||||
hfactory $scobj_hpath/heating_power_percent plain internal float
|
||||
hsetprop $scobj_hpath/heating_power_percent read ${ns}::getValue rdValue "R5"
|
||||
hsetprop $scobj_hpath/heating_power_percent rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/heating_power_percent oldval UNKNOWN
|
||||
|
||||
hfactory $scobj_hpath/heating_power_volts plain internal float
|
||||
hsetprop $scobj_hpath/heating_power_volts read ${ns}::getValue rdValue "R6"
|
||||
hsetprop $scobj_hpath/heating_power_volts rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/heating_power_volts oldval UNKNOWN
|
||||
|
||||
hfactory $scobj_hpath/gas_flow plain internal float
|
||||
hsetprop $scobj_hpath/gas_flow read ${ns}::getValue rdValue "R7"
|
||||
hsetprop $scobj_hpath/gas_flow rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/gas_flow oldval UNKNOWN
|
||||
|
||||
hfactory $scobj_hpath/control_sensor plain user int
|
||||
hsetprop $scobj_hpath/control_sensor values 1,2,3
|
||||
hsetprop $scobj_hpath/control_sensor oldval 1
|
||||
hset $scobj_hpath/control_sensor 1
|
||||
|
||||
hfactory $scobj_hpath/heater_auto plain user int
|
||||
hsetprop $scobj_hpath/heater_auto values 0,1
|
||||
hsetprop $scobj_hpath/heater_auto oldval 0
|
||||
hset $scobj_hpath/heater_auto 0
|
||||
|
||||
hfactory $scobj_hpath/cooler_auto plain user int
|
||||
hsetprop $scobj_hpath/cooler_auto values 0,1
|
||||
hsetprop $scobj_hpath/cooler_auto oldval 0
|
||||
hset $scobj_hpath/cooler_auto 0
|
||||
|
||||
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/proportional_band plain user float
|
||||
hsetprop $scobj_hpath/proportional_band read ${ns}::getValue rdValue "R8"
|
||||
hsetprop $scobj_hpath/proportional_band rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/proportional_band oldval 30.0
|
||||
hset $scobj_hpath/proportional_band 30.0
|
||||
|
||||
hfactory $scobj_hpath/integral_time plain user float
|
||||
hsetprop $scobj_hpath/integral_time read ${ns}::getValue rdValue "R9"
|
||||
hsetprop $scobj_hpath/integral_time rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/integral_time oldval 2.0
|
||||
hset $scobj_hpath/integral_time 2.0
|
||||
|
||||
hfactory $scobj_hpath/derivative_time plain user float
|
||||
hsetprop $scobj_hpath/derivative_time read ${ns}::getValue rdValue "R10"
|
||||
hsetprop $scobj_hpath/derivative_time rdValue ${ns}::rdValue $scobj_hpath
|
||||
hsetprop $scobj_hpath/derivative_time oldval 0.0
|
||||
hset $scobj_hpath/derivative_time 0.0
|
||||
|
||||
hfactory $scobj_hpath/tolerance plain user float
|
||||
hsetprop $scobj_hpath/tolerance units "K"
|
||||
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/itc500_state plain spy text
|
||||
hsetprop $scobj_hpath/itc500_state read ${ns}::getState $scobj_hpath rdState "X"
|
||||
hsetprop $scobj_hpath/itc500_state rdState ${ns}::rdState $scobj_hpath
|
||||
hsetprop $scobj_hpath/itc500_state oldval UNKNOWN
|
||||
hsetprop $scobj_hpath/itc500_state my_state "STATE_V"
|
||||
hsetprop $scobj_hpath/itc500_state my_status "UNKNOWN"
|
||||
hsetprop $scobj_hpath/itc500_state my_version UNKNOWN
|
||||
hsetprop $scobj_hpath/itc500_state my_model UNKNOWN
|
||||
|
||||
hfactory $scobj_hpath/remote_ctrl plain spy text
|
||||
hset $scobj_hpath/remote_ctrl UNKNOWN
|
||||
|
||||
hfactory $scobj_hpath/itc500_lasterror plain user text
|
||||
hset $scobj_hpath/itc500_lasterror ""
|
||||
|
||||
hfactory $scobj_hpath/lowerlimit plain mugger float
|
||||
hsetprop $scobj_hpath/lowerlimit units "K"
|
||||
hset $scobj_hpath/lowerlimit 0
|
||||
|
||||
hfactory $scobj_hpath/upperlimit plain mugger float
|
||||
hsetprop $scobj_hpath/upperlimit units "K"
|
||||
hset $scobj_hpath/upperlimit 300
|
||||
|
||||
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/setpoint
|
||||
$sct_controller write $scobj_hpath/setpoint
|
||||
$sct_controller poll $scobj_hpath/sensor/value
|
||||
$sct_controller poll $scobj_hpath/sensor2/value
|
||||
$sct_controller poll $scobj_hpath/sensor3/value
|
||||
$sct_controller poll $scobj_hpath/heating_power_percent
|
||||
$sct_controller poll $scobj_hpath/heating_power_volts
|
||||
$sct_controller poll $scobj_hpath/gas_flow
|
||||
$sct_controller poll $scobj_hpath/proportional_band
|
||||
$sct_controller poll $scobj_hpath/integral_time
|
||||
$sct_controller poll $scobj_hpath/derivative_time
|
||||
$sct_controller poll $scobj_hpath/itc500_state 5 halt read
|
||||
}
|
||||
|
||||
::scobj::hinitprops $tempobj
|
||||
hsetprop $scobj_hpath klass NXenvironment
|
||||
::scobj::set_required_props $scobj_hpath
|
||||
hsetprop $scobj_hpath type part
|
||||
foreach snsr {sensor sensor2 sensor3} {
|
||||
foreach {rootpath hpath klass priv} "
|
||||
$scobj_hpath $snsr NXsensor spy
|
||||
$scobj_hpath $snsr/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/$snsr type part
|
||||
hsetprop $scobj_hpath/$snsr/value nxalias tc1_${snsr}_value
|
||||
hsetprop $scobj_hpath/$snsr/value mutable true
|
||||
hsetprop $scobj_hpath/$snsr/value sdsinfo ::nexus::scobj::sdsinfo
|
||||
}
|
||||
hsetprop $scobj_hpath privilege spy
|
||||
::scobj::hinitprops $tempobj setpoint
|
||||
if {[SplitReply [environment_simulation]]=="false"} {
|
||||
ansto_makesctdrive ${tempobj}_driveable $scobj_hpath/setpoint $scobj_hpath/sensor/value $sct_controller
|
||||
}
|
||||
} message ] {
|
||||
return -code error $message
|
||||
}
|
||||
}
|
||||
namespace export mk_sct_oxford_itc500
|
||||
}
|
||||
|
||||
##
|
||||
# @brief Create a Oxford itc500 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 ca1-kowari)
|
||||
# @param port, the IP protocol port number of the device
|
||||
# @param _tol (optional), this is the initial tolerance setting
|
||||
proc add_itc500 {name IP port {_tol 5.0}} {
|
||||
set fd [open "/tmp/itc500.log" a]
|
||||
if {[SplitReply [environment_simulation]]=="false"} {
|
||||
puts $fd "makesctcontroller sct_itc500 oxford ${IP}:$port"
|
||||
makesctcontroller sct_itc500 oxford ${IP}:$port
|
||||
}
|
||||
puts $fd "mk_sct_oxford_itc500 sct_itc500 environment $name $_tol"
|
||||
mk_sct_oxford_itc500 sct_itc500 environment $name $_tol
|
||||
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_oxford_500.tcl"
|
||||
set fd [open "/tmp/itc500.log" w]
|
||||
puts $fd "file evaluation of sct_oxford_500.tcl"
|
||||
close $fd
|
||||
|
||||
namespace import ::scobj::itc500::*
|
||||
|
||||
#add_itc500 itc500 137.157.201.213 502 5
|
||||
add_itc500 itc500 localhost 30509 5
|
||||
Reference in New Issue
Block a user