initial commit
This commit is contained in:
405
tcl/drivers/nvstep.tcl
Normal file
405
tcl/drivers/nvstep.tcl
Normal file
@ -0,0 +1,405 @@
|
||||
namespace eval nvstep {
|
||||
}
|
||||
|
||||
proc stdConfig::nvstep {} {
|
||||
variable name
|
||||
|
||||
controller syncedprot
|
||||
pollperiod 1 1
|
||||
|
||||
obj NvStep wr
|
||||
prop write nvstep::write
|
||||
prop read "nvstep::read [silent 0 result instconfig sensirion]"
|
||||
prop enum fixed=0,controlled=1,automatic=2,close=3,open=4
|
||||
prop write nvstep::write
|
||||
prop lastpulse 0
|
||||
prop filter 0
|
||||
prop closetest 0
|
||||
prop amplitude 0
|
||||
prop t_after_delay 0
|
||||
prop fixed_to_auto 0
|
||||
prop initialize 0
|
||||
prop maxflow 0
|
||||
default 0
|
||||
|
||||
kids "needle value" {
|
||||
node flow upd
|
||||
|
||||
node motstat -text upd
|
||||
|
||||
node set out
|
||||
default 2.5
|
||||
prop check nvstep::checkset
|
||||
prop write stdSct::complete
|
||||
prop label "flow set"
|
||||
|
||||
node flowmax par 20
|
||||
prop label "flow maximum"
|
||||
|
||||
node flowp upd
|
||||
prop help "flow calculated from pressure before pump"
|
||||
|
||||
node ctrl -none
|
||||
kids "control parameters" {
|
||||
node prop par 10
|
||||
prop help bigger means higher feedback
|
||||
|
||||
node int par 15
|
||||
prop help bigger means reacting slower (unit: sec)
|
||||
|
||||
node delay par 5
|
||||
prop help minimum time to wait before next motor step
|
||||
|
||||
node tol par 0.1
|
||||
}
|
||||
|
||||
node autoflow -none
|
||||
kids "autoflow control parameters" {
|
||||
flow::make flow::tmts {result tt set/reg}
|
||||
}
|
||||
|
||||
node calib -none
|
||||
kids calib {
|
||||
node ln_per_min_per_mbar par 0.9
|
||||
node mbar_offset par 0.5
|
||||
}
|
||||
|
||||
node initialize -int out
|
||||
default 0
|
||||
prop visible false
|
||||
prop enum check=1,adjust=2,stop=3
|
||||
prop label "limit switch"
|
||||
prop write nvstep::startinit
|
||||
|
||||
node initstate -text upd
|
||||
prop visible false
|
||||
default ""
|
||||
}
|
||||
}
|
||||
|
||||
proc nvstep::checkset {} {
|
||||
sct update [sct target]
|
||||
set s [hvali [sct parent]]
|
||||
if {[hvali /cc/fa] == 0 || ($s != 1 && $s != 2)} {
|
||||
if {$s != 2} {
|
||||
set s 1
|
||||
}
|
||||
hset [sct parent] $s
|
||||
}
|
||||
}
|
||||
|
||||
proc nvstep::write {} {
|
||||
switch [sct target] {
|
||||
3 {
|
||||
sct rangeshift 0
|
||||
if {[hvali [sct]/nvmot] > [hvali [sct]/nvmot/lowerlimit]} {
|
||||
nvmot [hvali [sct]/nvmot/lowerlimit]
|
||||
updateval [sct]/motstat closing
|
||||
}
|
||||
}
|
||||
4 {
|
||||
nvmot [hvali [sct]/nvmot/upperlimit]
|
||||
updateval [sct]/motstat opening
|
||||
}
|
||||
2 {
|
||||
hupdate [sct]/autoflow/suspended 0
|
||||
}
|
||||
}
|
||||
sct fixed_to_auto 0
|
||||
if {[sct target] == 0 || [sct target] > 2} {
|
||||
logsetup [sct]/set clear
|
||||
logsetup [sct]/autoflow/flowtarget clear
|
||||
}
|
||||
sct update [sct target]
|
||||
return idle
|
||||
}
|
||||
|
||||
proc nvstep::calcstep {from to prop} {
|
||||
# for the decreasing step (to < from), we use a linear function above 20
|
||||
foreach var {from to} {
|
||||
if {[set $var] > 20 && $to < $from} {
|
||||
set $var [expr 1.9 + 0.0025 * [set $var]]
|
||||
} elseif {[set $var] > 1} {
|
||||
set $var [expr 2 - 1.0 / [set $var]]
|
||||
}
|
||||
}
|
||||
set res [expr ($to - $from) * $prop]
|
||||
return $res
|
||||
}
|
||||
|
||||
proc nvstep::poll {} {
|
||||
set now [DoubleTime]
|
||||
set mode [sctval [sct]]
|
||||
if {$mode != 0} {
|
||||
set encpos [hval [sct]/nvmot/encoder]
|
||||
if {$encpos < [hval [sct]/nvmot/lowerlimit] - 15 ||
|
||||
$encpos > [hval [sct]/nvmot/upperlimit] + 15} {
|
||||
hsetprop [sct]/nvmot/encoder adjust_zero 1
|
||||
return idle
|
||||
}
|
||||
}
|
||||
# if {[silent 0 sct initialize] > 0} {
|
||||
# return nvstep::init
|
||||
# }
|
||||
hset [sct]/nvmot/disablelimits 0
|
||||
set umsg "automatic needle valve not activated - set temperature undefined"
|
||||
switch -- $mode {
|
||||
1 - 2 {
|
||||
# pump_is_off is defined in startup/hepump.tcl
|
||||
if {[info command pump_is_off] ne "" && [pump_is_off]} {
|
||||
return idle
|
||||
}
|
||||
if {$mode == 1 || [sctval [sct]/autoflow/suspended]} {
|
||||
set soll [hvali [sct]/set]
|
||||
hupdate [sct]/autoflow/flowtarget $soll
|
||||
} else {
|
||||
if {$now > [silent 0 sct lastauto] + 4.7} {
|
||||
sct lastauto $now
|
||||
set script [hvali [sct]/autoflow/script]
|
||||
set flowmax [hvali [sct]/flowmax]
|
||||
if {$flowmax > 20} {
|
||||
set flowmax 20
|
||||
clientput "WARNING: reduced flowmax to $flowmax ln/min for less stress to the pump"
|
||||
hupdate [sct]/flowmax $flowmax
|
||||
}
|
||||
$script [sct]/autoflow [hvali [sct]/set] $flowmax
|
||||
}
|
||||
set soll [hvali [sct]/autoflow/flowset]
|
||||
if {[hgetpropval [sct]/autoflow/getTset t_set_undefined]} {
|
||||
if {[hvali [sct]/status] ne $umsg} {
|
||||
clientput "ERROR: $umsg"
|
||||
}
|
||||
hupdate [sct]/status $umsg
|
||||
}
|
||||
}
|
||||
set ist [hvali [sct]/flow]
|
||||
set tol [hvali [sct]/ctrl/tol]
|
||||
set a [sct amplitude]
|
||||
set t [sct t_after_delay]
|
||||
if {$t != 0} {
|
||||
set t [expr $now - $t]
|
||||
}
|
||||
set i [hvali [sct]/ctrl/int]
|
||||
# lim is an exponential curve converging to soll.
|
||||
# the range between lim and soll is a window shrinking with time
|
||||
# before t_after_delay, the last 'ist' value is between lim and soll
|
||||
# if the 'ist' value does not change it will reach lim at t_after_delay
|
||||
set lim [expr $soll + $a * exp(-$t/double($i))]
|
||||
# calculate expected limits for no further step needed
|
||||
if {$lim > $soll} {
|
||||
set uplim [expr $lim + $tol]
|
||||
set lolim [expr $soll - $tol]
|
||||
} else {
|
||||
set uplim [expr $soll + $tol]
|
||||
set lolim [expr $lim - $tol]
|
||||
}
|
||||
if {$ist > $uplim || $ist < $lolim} {
|
||||
# we have to do a next step
|
||||
set step [nvstep::calcstep $ist $soll [hvali [sct]/ctrl/prop]]
|
||||
sct t_after_delay [expr $now + [hvali [sct]/ctrl/delay]]
|
||||
sct amplitude [expr $ist - $soll]
|
||||
set v [format %.2f [expr [hvali [sct]/nvmot] + $step]]
|
||||
set u [hvali [sct]/nvmot/upperlimit]
|
||||
set ll [hvali [sct]/nvmot/lowerlimit] ;# ll was 0 before!
|
||||
if {$v > $u} {
|
||||
set v $u
|
||||
updateval [sct]/motstat opened
|
||||
} elseif {$v < $ll} {
|
||||
set v $ll
|
||||
updateval [sct]/motstat closed
|
||||
} elseif {$step > 0} {
|
||||
updateval [sct]/motstat opening
|
||||
} else {
|
||||
updateval [sct]/motstat closing
|
||||
}
|
||||
#clientput "$step $v"
|
||||
nvmot $v
|
||||
} else {
|
||||
# no step needed yet
|
||||
updateval [sct]/motstat idle
|
||||
if {$t > 0} {
|
||||
if {$ist < $uplim - $tol && $ist > $lolim + $tol} {
|
||||
# the ist value is making more progress then expected at worst
|
||||
# so we narrow the window accordingly
|
||||
sct amplitude [expr $ist - $soll]
|
||||
sct t_after_delay $now
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
0 { # fixed
|
||||
set cnt [sct fixed_to_auto]
|
||||
if {[silent 0 hval [sct]/flow] > [hvali [sct]/flowmax] + 10} {
|
||||
incr cnt
|
||||
if {$cnt > 60} {
|
||||
clientput "pressure high - switch to automatic mode"
|
||||
hset [sct] 2
|
||||
}
|
||||
} else {
|
||||
if {$cnt > 0} {
|
||||
incr cnt -1
|
||||
}
|
||||
}
|
||||
sct fixed_to_auto $cnt
|
||||
switch [hvali [sct]/motstat] {
|
||||
opening - closing {
|
||||
if {[hgetpropval [sct]/nvmot status] ne "run"} {
|
||||
updateval [sct]/motstat idle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3 { # close
|
||||
set stat [hvali [sct]/motstat]
|
||||
if {[hgetpropval [sct]/nvmot status] ne "run" && $stat eq "closing"} {
|
||||
updateval [sct]/motstat closed
|
||||
}
|
||||
}
|
||||
4 { # open
|
||||
set stat [hvali [sct]/motstat]
|
||||
if {[hgetpropval [sct]/nvmot status] ne "run" && $stat eq "opening"} {
|
||||
updateval [sct]/motstat opened
|
||||
}
|
||||
}
|
||||
}
|
||||
if {[hvali [sct]/status] eq $umsg && \
|
||||
([sctval [sct]] != 2 || [hgetpropval [sct]/autoflow/getTset t_set_undefined] == 0)} {
|
||||
hsetprop [sct]/autoflow/getTset t_set_undefined 0
|
||||
hupdate [sct]/status ""
|
||||
}
|
||||
return idle
|
||||
}
|
||||
|
||||
proc nvstep::read {{sensirion 0}} {
|
||||
hsetprop /cc/fa nvpath [sct]
|
||||
_cc updatescript /cc/fa nvstep::updatemode
|
||||
hsetprop /cc/f nvpath [sct]
|
||||
if {$sensirion} {
|
||||
hsetprop /nvflow flowsource flowmeter
|
||||
hsetprop /nvflow nvpath [sct]
|
||||
hsetprop /nvflow nvctrl [sct controller]
|
||||
_hemot updatescript /nvflow nvstep::updateflow
|
||||
hsetprop /cc/f flowsource pressref
|
||||
} else {
|
||||
hsetprop /cc/f nvctrl [sct controller]
|
||||
hsetprop /cc/f flowsource flowpress
|
||||
}
|
||||
_cc updatescript /cc/f nvstep::updateflow
|
||||
return unpoll
|
||||
}
|
||||
|
||||
proc nvstep::updateflow {value} {
|
||||
# flowsource:
|
||||
# pressref: just update nv/flowp
|
||||
# flowmeter: update nv/flow
|
||||
# flowpress: flow from pressure
|
||||
|
||||
set source [silent pressure sct flowsource]
|
||||
set filter [lrange "[silent $value sct filter] $value" end-9 10]
|
||||
sct filter $filter
|
||||
# filter out values which are within the 3 highest or 3 lowest values
|
||||
# out of 10 last values (i.e. within 5 seconds)
|
||||
set m 3
|
||||
set filter [lsort -real $filter]
|
||||
if {[llength $filter] < 10} {
|
||||
set flow $value
|
||||
} else {
|
||||
set min [lindex $filter $m]
|
||||
set max [lindex $filter end-$m]
|
||||
set mean [expr double([join $filter +]) / [llength $filter]]
|
||||
set flow [silent 0 sct filtered]
|
||||
if {$max < $flow} {
|
||||
set flow $max
|
||||
} elseif {$min > $flow} {
|
||||
set flow $min
|
||||
} else {
|
||||
set flow [expr $flow * 0.98 + $mean * 0.02]
|
||||
}
|
||||
}
|
||||
sct filtered $flow
|
||||
if {$source eq "flowmeter"} {
|
||||
updateval [sct nvpath]/flow $flow
|
||||
} else {
|
||||
if {$flow < -50} {
|
||||
set flow -62.5
|
||||
} else {
|
||||
set off [hval [sct nvpath]/calib/mbar_offset]
|
||||
set fpm [hval [sct nvpath]/calib/ln_per_min_per_mbar]
|
||||
set flow [expr ($flow - $off) * $fpm]
|
||||
}
|
||||
if {$source eq "pressref"} {
|
||||
hupdate [sct nvpath]/flowp $flow
|
||||
return
|
||||
}
|
||||
updateval_e [sct nvpath]/flow $flow -62.5 no_sensor
|
||||
}
|
||||
[sct nvctrl] queue [sct nvpath] read nvstep::poll
|
||||
}
|
||||
|
||||
proc nvstep::startinit {} {
|
||||
set i [hgetpropval [sct parent] initialize]
|
||||
switch [sct target] {
|
||||
1 {
|
||||
if {$i != 0} {
|
||||
error "checking already"
|
||||
}
|
||||
# hsetprop [sct parent] initialize 10
|
||||
hsetprop [sct parent] initialize 13
|
||||
}
|
||||
2 {
|
||||
if {$i != 0} {
|
||||
error "adjusting already"
|
||||
}
|
||||
hsetprop [sct parent] initialize 20
|
||||
}
|
||||
3 {
|
||||
if {$i >= 10 && $i < 13} {
|
||||
hsetprop [sct parent] initialize 13
|
||||
} elseif {$i >= 20} {
|
||||
hsetprop [sct parent] initialize 28
|
||||
} else {
|
||||
hsetprop [sct parent] initialize 29
|
||||
}
|
||||
}
|
||||
}
|
||||
sct update [sct target]
|
||||
return idle
|
||||
}
|
||||
|
||||
proc nvstep::ierror {msg} {
|
||||
updateerror [sct]/initstate "$msg"
|
||||
clientput "[sct]: $msg"
|
||||
}
|
||||
|
||||
proc nvstep::imsg {msg} {
|
||||
if {$msg ne [hvali [sct]/initstate]} {
|
||||
hupdate [sct]/initstate $msg
|
||||
clientput "[sct]: $msg"
|
||||
catch {hdelprop [sct]/initstate geterror}
|
||||
}
|
||||
}
|
||||
|
||||
proc nvstep::init {} {
|
||||
set now [DoubleTime]
|
||||
if {[hgetpropval [sct]/nvmot status] eq "run"} {
|
||||
return idle
|
||||
}
|
||||
set phase [sct initialize]
|
||||
set pos [hvali [sct]/nvmot/encoder]
|
||||
set goto ""
|
||||
switch $phase {
|
||||
10 { # start check
|
||||
ierror "limit switch no longer supported"
|
||||
}
|
||||
20 { # start adjust
|
||||
ierror "limit switch no longer supported"
|
||||
}
|
||||
}
|
||||
if {$goto ne ""} {
|
||||
sct goto $goto
|
||||
clientput "goto $goto"
|
||||
run [hgetpropval [sct]/nvmot sicsdev] $goto
|
||||
}
|
||||
sct initialize $phase
|
||||
return idle
|
||||
}
|
Reference in New Issue
Block a user