Better checks and state machine for Knauer pump

This commit is contained in:
Douglas Clowes
2014-10-07 14:59:21 +11:00
parent 91b7c0b6eb
commit b0e4c3a85b
2 changed files with 175 additions and 24 deletions

View File

@ -39,6 +39,7 @@ driver knauer_pump = {
readable = 1;
read_command = ' ';
fetch_function = volume_fetch;
read_function = volume_read;
property 'units' = 'mL';
}
var setp = {
@ -46,6 +47,7 @@ driver knauer_pump = {
writeable = 1;
write_command = ' ';
write_function = volume_write;
check_function = volume_check;
driveable = pump/volume/pval;
checkstatus_function = volume_checkstatus;
halt_function = volume_halt;
@ -53,6 +55,7 @@ driver knauer_pump = {
readable = 1;
read_command = ' ';
fetch_function = volume_fsm;
read_function = volume_store;
property 'units' = 'mL';
property this_state = 0;
}
@ -90,7 +93,7 @@ driver knauer_pump = {
# Ensure the pump starts up in REMOTE mode
#
code mkDriver = {%%
hset ${scobj_hpath}/pump/remote 1
#hset ${scobj_hpath}/pump/remote 1
%%}
#
# These functions handle the real_data returned by the pump for the GLP? command
@ -194,9 +197,21 @@ driver knauer_pump = {
sct geterror "${setpoint} has [llength ${rlist}] components, needs 4"
error [sct geterror]
}
set sum [expr [lindex ${rlist} 0] + [lindex ${rlist} 1] + [lindex ${rlist} 2] + [lindex ${rlist} 3]]
set sum 0
for {set i 0} {$i < 4} {incr i} {
set cmp [lindex ${rlist} ${i}]
if { ![string is integer -strict ${cmp}] } {
sct geterror "component [expr {${i} + 1}] is not integer: \"${cmp}\""
error [sct geterror]
}
if { !(${cmp} >= 0 && ${cmp} <= 100) } {
sct geterror "component [expr {${i} + 1}] is not between 0 and 100: \"${cmp}\""
error [sct geterror]
}
set sum [expr {${sum} + ${cmp}}]
}
if { ${sum} != 100 } {
sct geterror "sum is ${sum}, must be 100"
sct geterror "sum of components is ${sum}, must be 100"
error [sct geterror]
}
%%}
@ -262,7 +277,6 @@ driver knauer_pump = {
%%}
code volume_write = {%%
hsetprop ${tc_root}/[sct driveable] base_volume [hgetpropval ${tc_root}/[sct driveable] raw_volume]
hset ${tc_root}/[sct driveable] 0.0
set cmd "REMOTE"
sct this_state 1
@ -283,20 +297,25 @@ driver knauer_pump = {
set time_tgt [expr {int(60000.0 * 1000.0 * [sct target] / ${flow_tgt})}]
set time_1 [expr {${time_tgt} - 500}]
set time_2 [expr {${time_tgt} + 500}]
set nextState noResponse
set saveState ${nextState}
set nextState "noResponse"
if { [sct this_state] == 1 } {
set cmd "TT_LOAD:1"
set cmd "GLP?"
set nextState ${saveState}
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 2 } {
set cmd "TT_SET:0,0,${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0"
set cmd "TT_LOAD:1"
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 3 } {
set cmd "TT_SET:1,${time_1},${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0"
set cmd "TT_SET:0,0,${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0"
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 4 } {
set cmd "TT_SET:2,${time_2},0,${ratio_tgt},0,0,0,0,0,0,0,0"
set cmd "TT_SET:1,${time_1},${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0"
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 5 } {
set cmd "TT_SET:2,${time_2},0,${ratio_tgt},0,0,0,0,0,0,0,0"
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 6 } {
set cmd "START:1,0"
sct this_state 0
} elseif { [sct this_state] == 91 } {
@ -304,6 +323,13 @@ driver knauer_pump = {
sct this_state 92
} elseif { [sct this_state] == 92 } {
set cmd "STOP:0,0"
sct this_state 93
} elseif { [sct this_state] == 93 } {
if { !([hpropexists ${tc_root}/pump/remote target] && [hgetpropval ${tc_root}/pump/remote target] == 1) } {
set cmd "LOCAL"
} else {
set cmd "@@NOSEND@@"
}
sct this_state 0
} else {
sct this_state 0
@ -331,6 +357,25 @@ driver knauer_pump = {
}
%%}
code volume_store = {%%
if { [sct this_state] == 2 } {
set ns [namespace current]
# store the GLP result
hsetprop ${tc_root}/dummy/glp result "${data}"
sct with ${tc_root}/dummy/glp "${ns}::read_glp ${tc_root}"
# extract the volume
sct with ${tc_root}/[sct driveable] "${ns}::volume_fetch ${tc_root} ${nextState} @@NOSEND@@"
sct with ${tc_root}/[sct driveable] "${ns}::volume_read ${tc_root}"
# copy it to base_volume
hsetprop ${tc_root}/[sct driveable] base_volume [hgetpropval ${tc_root}/[sct driveable] raw_volume]
}
if { [hpropexists [sct] target] } {
set data [sct target]
} else {
set data 0.0
}
%%}
code volume_halt = {%%
set cmd "STOP:0,0"
sct this_state 91

View File

@ -202,9 +202,21 @@ proc ::scobj::knauer_pump::ratio_check {tc_root} {
sct geterror "${setpoint} has [llength ${rlist}] components, needs 4"
error [sct geterror]
}
set sum [expr [lindex ${rlist} 0] + [lindex ${rlist} 1] + [lindex ${rlist} 2] + [lindex ${rlist} 3]]
set sum 0
for {set i 0} {$i < 4} {incr i} {
set cmp [lindex ${rlist} ${i}]
if { ![string is integer -strict ${cmp}] } {
sct geterror "component [expr {${i} + 1}] is not integer: \"${cmp}\""
error [sct geterror]
}
if { !(${cmp} >= 0 && ${cmp} <= 100) } {
sct geterror "component [expr {${i} + 1}] is not between 0 and 100: \"${cmp}\""
error [sct geterror]
}
set sum [expr {${sum} + ${cmp}}]
}
if { ${sum} != 100 } {
sct geterror "sum is ${sum}, must be 100"
sct geterror "sum of components is ${sum}, must be 100"
error [sct geterror]
}
# ratio_check hook code ends
@ -555,6 +567,16 @@ proc ::scobj::knauer_pump::status_fetch {tc_root nextState cmd_str} {
handle_exception ${catch_status} ${catch_message}
}
# function to check the write parameter on a device
proc ::scobj::knauer_pump::volume_check {tc_root} {
set catch_status [ catch {
debug_log ${tc_root} 1 "volume_check tc_root=${tc_root} sct=[sct] resp=[sct result]"
# volume_check hook code goes here
return "idle"
} catch_message ]
handle_exception ${catch_status} ${catch_message}
}
# checkstatus function for driveable interface
proc ::scobj::knauer_pump::volume_checkstatus {tc_root} {
set catch_status [ catch {
@ -644,20 +666,25 @@ proc ::scobj::knauer_pump::volume_fsm {tc_root nextState cmd_str} {
set time_tgt [expr {int(60000.0 * 1000.0 * [sct target] / ${flow_tgt})}]
set time_1 [expr {${time_tgt} - 500}]
set time_2 [expr {${time_tgt} + 500}]
set nextState noResponse
set saveState ${nextState}
set nextState "noResponse"
if { [sct this_state] == 1 } {
set cmd "TT_LOAD:1"
set cmd "GLP?"
set nextState ${saveState}
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 2 } {
set cmd "TT_SET:0,0,${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0"
set cmd "TT_LOAD:1"
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 3 } {
set cmd "TT_SET:1,${time_1},${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0"
set cmd "TT_SET:0,0,${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0"
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 4 } {
set cmd "TT_SET:2,${time_2},0,${ratio_tgt},0,0,0,0,0,0,0,0"
set cmd "TT_SET:1,${time_1},${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0"
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 5 } {
set cmd "TT_SET:2,${time_2},0,${ratio_tgt},0,0,0,0,0,0,0,0"
sct this_state [expr {[sct this_state] + 1}]
} elseif { [sct this_state] == 6 } {
set cmd "START:1,0"
sct this_state 0
} elseif { [sct this_state] == 91 } {
@ -665,6 +692,13 @@ proc ::scobj::knauer_pump::volume_fsm {tc_root nextState cmd_str} {
sct this_state 92
} elseif { [sct this_state] == 92 } {
set cmd "STOP:0,0"
sct this_state 93
} elseif { [sct this_state] == 93 } {
if { !([hpropexists ${tc_root}/pump/remote target] && [hgetpropval ${tc_root}/pump/remote target] == 1) } {
set cmd "LOCAL"
} else {
set cmd "@@NOSEND@@"
}
sct this_state 0
} else {
sct this_state 0
@ -721,6 +755,79 @@ proc ::scobj::knauer_pump::volume_halt {tc_root} {
handle_exception ${catch_status} ${catch_message}
}
# function to parse the read of a parameter on a device
proc ::scobj::knauer_pump::volume_read {tc_root} {
set catch_status [ catch {
debug_log ${tc_root} 1 "volume_read 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]"
}
# volume_read 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::knauer_pump::volume_store {tc_root} {
set catch_status [ catch {
debug_log ${tc_root} 1 "volume_store 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]"
}
# volume_store hook code starts
if { [sct this_state] == 2 } {
set ns [namespace current]
# store the GLP result
hsetprop ${tc_root}/dummy/glp result "${data}"
sct with ${tc_root}/dummy/glp "${ns}::read_glp ${tc_root}"
# extract the volume
sct with ${tc_root}/[sct driveable] "${ns}::volume_fetch ${tc_root} ${nextState} @@NOSEND@@"
sct with ${tc_root}/[sct driveable] "${ns}::volume_read ${tc_root}"
# copy it to base_volume
hsetprop ${tc_root}/[sct driveable] base_volume [hgetpropval ${tc_root}/[sct driveable] raw_volume]
}
if { [hpropexists [sct] target] } {
set data [sct target]
} else {
set data 0.0
}
# volume_store 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::knauer_pump::volume_write {tc_root nextState cmd_str} {
set catch_status [ catch {
@ -731,7 +838,6 @@ proc ::scobj::knauer_pump::volume_write {tc_root nextState cmd_str} {
set par [sct target]
set cmd "${cmd_str}${par}"
# volume_write hook code starts
hsetprop ${tc_root}/[sct driveable] base_volume [hgetpropval ${tc_root}/[sct driveable] raw_volume]
hset ${tc_root}/[sct driveable] 0.0
set cmd "REMOTE"
sct this_state 1
@ -961,8 +1067,8 @@ proc ::scobj::knauer_pump::mkDriver { sct_controller name device_class simulatio
hsetprop ${scobj_hpath}/pump/volume type "part"
hfactory ${scobj_hpath}/pump/volume/pval plain user float
hsetprop ${scobj_hpath}/pump/volume/pval read ${ns}::volume_fetch ${scobj_hpath} rdValue { }
hsetprop ${scobj_hpath}/pump/volume/pval rdValue ${ns}::rdValue ${scobj_hpath}
hsetprop ${scobj_hpath}/pump/volume/pval read ${ns}::volume_fetch ${scobj_hpath} volume_read { }
hsetprop ${scobj_hpath}/pump/volume/pval volume_read ${ns}::volume_read ${scobj_hpath}
hsetprop ${scobj_hpath}/pump/volume/pval control true
hsetprop ${scobj_hpath}/pump/volume/pval data true
hsetprop ${scobj_hpath}/pump/volume/pval mutable true
@ -975,10 +1081,10 @@ proc ::scobj::knauer_pump::mkDriver { sct_controller name device_class simulatio
hsetprop ${scobj_hpath}/pump/volume/pval nxalias "${name}_pump_volume_pval"
hfactory ${scobj_hpath}/pump/volume/setp plain user float
hsetprop ${scobj_hpath}/pump/volume/setp read ${ns}::volume_fsm ${scobj_hpath} rdValue { }
hsetprop ${scobj_hpath}/pump/volume/setp rdValue ${ns}::rdValue ${scobj_hpath}
hsetprop ${scobj_hpath}/pump/volume/setp write ${ns}::volume_write ${scobj_hpath} noResponse { }
hsetprop ${scobj_hpath}/pump/volume/setp noResponse ${ns}::noResponse ${scobj_hpath}
hsetprop ${scobj_hpath}/pump/volume/setp read ${ns}::volume_fsm ${scobj_hpath} volume_store { }
hsetprop ${scobj_hpath}/pump/volume/setp volume_store ${ns}::volume_store ${scobj_hpath}
hsetprop ${scobj_hpath}/pump/volume/setp write ${ns}::volume_write ${scobj_hpath} volume_check { }
hsetprop ${scobj_hpath}/pump/volume/setp volume_check ${ns}::volume_check ${scobj_hpath}
hsetprop ${scobj_hpath}/pump/volume/setp check ${ns}::checkrange ${scobj_hpath}
hsetprop ${scobj_hpath}/pump/volume/setp driving 0
hsetprop ${scobj_hpath}/pump/volume/setp checklimits ${ns}::checklimits ${scobj_hpath}
@ -1014,7 +1120,7 @@ proc ::scobj::knauer_pump::mkDriver { sct_controller name device_class simulatio
ansto_makesctdrive ${name}_pump_volume_setp ${scobj_hpath}/pump/volume/setp ${scobj_hpath}/pump/volume/pval ${sct_controller}
}
# mkDriver hook code starts
hset ${scobj_hpath}/pump/remote 1
#hset ${scobj_hpath}/pump/remote 1
# mkDriver hook code ends
} catch_message ]
handle_exception ${catch_status} ${catch_message}