initial commit
This commit is contained in:
380
tcl/drivers/ccu4ext.tcl
Normal file
380
tcl/drivers/ccu4ext.tcl
Normal file
@ -0,0 +1,380 @@
|
||||
|
||||
namespace eval ccu4ext {
|
||||
}
|
||||
|
||||
# automatic fill with level reading from external source
|
||||
proc stdConfig::ccu4ext {type {readlevel 0}} {
|
||||
|
||||
variable node
|
||||
variable ctrl
|
||||
|
||||
controller syncedprot
|
||||
|
||||
obj fillccu wr -int
|
||||
default -1
|
||||
prop write ccu4ext::writeExt $type
|
||||
prop read ccu4ext::fillExt $type
|
||||
|
||||
prop enum watching=0,filling=1,inactive=2
|
||||
prop label "filling state"
|
||||
|
||||
if {$type eq "n2"} {
|
||||
set text LN2
|
||||
} else {
|
||||
set text LHe
|
||||
}
|
||||
kids "$text fill settings" {
|
||||
|
||||
node state upd -text
|
||||
|
||||
node readlevel -text par $readlevel
|
||||
prop visible false
|
||||
node lowlevel par 10
|
||||
node highlevel par 100
|
||||
|
||||
node smooth upd
|
||||
prop fmt %.7g
|
||||
default -1
|
||||
|
||||
node minfillminutes par 3.0
|
||||
node maxfillminutes par 30.0
|
||||
node minholdhours par 12.0
|
||||
node maxholdhours par 120.0
|
||||
node tolerance par 20.0
|
||||
node badreadingminutes par 30.0
|
||||
node tubecoolingminutes par 3.0
|
||||
if {$type eq "he"} {
|
||||
node vessellimit par 10.0
|
||||
node vext upd
|
||||
}
|
||||
}
|
||||
set node /sics/$ctrl
|
||||
return "$text fill with CCU4 and external level meter"
|
||||
}
|
||||
|
||||
proc ccu4ext::changestate {type state} {
|
||||
switch $type {
|
||||
n2 {
|
||||
set cmd nc
|
||||
set auto na
|
||||
}
|
||||
he {
|
||||
set cmd hcd
|
||||
set auto ha
|
||||
}
|
||||
default {
|
||||
error "illegal level meter type: $type"
|
||||
}
|
||||
}
|
||||
switch $state {
|
||||
stop {
|
||||
cc $cmd 0
|
||||
cc $auto 1
|
||||
}
|
||||
fill {
|
||||
cc $cmd 1
|
||||
cc $auto 1
|
||||
}
|
||||
off {
|
||||
cc $cmd 2
|
||||
cc $auto 0
|
||||
}
|
||||
watch {
|
||||
cc $cmd 3
|
||||
cc $auto 1
|
||||
}
|
||||
}
|
||||
sct change_time [DoubleTime]
|
||||
}
|
||||
|
||||
proc ccu4ext::calcsmooth {level minspeed maxspeed} {
|
||||
if {![string is double $level]} {
|
||||
return 999.9
|
||||
}
|
||||
set now [clock seconds]
|
||||
set lasttime [silent 0 sct lasttime]
|
||||
if {$lasttime == 0} {
|
||||
set lasttime $now
|
||||
}
|
||||
set delta [expr $now - $lasttime]
|
||||
sct lasttime $now
|
||||
set smooth [hvali [sct]/smooth]
|
||||
if {$smooth < 0} {
|
||||
set smooth $level
|
||||
}
|
||||
set gs [expr $smooth + $delta * $maxspeed]
|
||||
if {$level > $gs} {
|
||||
set smooth $gs
|
||||
} else {
|
||||
set gs [expr $smooth + $delta * $minspeed]
|
||||
if {$level < $gs} {
|
||||
set smooth $gs
|
||||
} else {
|
||||
set smooth $level
|
||||
}
|
||||
}
|
||||
set badtime [silent 0 sct badtime]
|
||||
if {abs($smooth - $level) > [hvali [sct]/tolerance]} {
|
||||
if {$badtime < [hvali [sct]/badreadingminutes] * 60 * 2} {
|
||||
sct badtime [expr $badtime + $delta]
|
||||
}
|
||||
} else {
|
||||
if {$badtime > $delta} {
|
||||
sct badtime [expr $badtime - $delta]
|
||||
} else {
|
||||
sct badtime 0
|
||||
}
|
||||
}
|
||||
hupdate [sct]/smooth $smooth
|
||||
return $smooth
|
||||
}
|
||||
|
||||
proc ccu4ext::setmode {type state} {
|
||||
if {[sctval [sct]] != $state} {
|
||||
sct target $state
|
||||
writeExt $type 0
|
||||
}
|
||||
}
|
||||
|
||||
proc ccu4ext::fillExt {type} {
|
||||
if {$type eq "n2"} {
|
||||
set valve [sctval /cc/nv]
|
||||
set auto [sctval /cc/na]
|
||||
} else {
|
||||
set valve [sctval /cc/hv]
|
||||
set auto [sctval /cc/ha]
|
||||
}
|
||||
set enumtxt "watching,fill,inactive"
|
||||
set errtxt ""
|
||||
set sm [expr [DoubleTime] > [silent 0 sct change_time] + 10]
|
||||
switch -- $valve {
|
||||
0 {
|
||||
set txt "fill valve off"
|
||||
if {$sm} {
|
||||
if {$auto} {
|
||||
setmode $type 0
|
||||
} else {
|
||||
setmode $type 2
|
||||
}
|
||||
}
|
||||
}
|
||||
1 {
|
||||
set txt "filling"
|
||||
if {$sm} {setmode $type 1}
|
||||
}
|
||||
2 {
|
||||
set txt "no fill valve"
|
||||
if {$sm} {setmode $type 2}
|
||||
set enumtxt "$txt=2"
|
||||
}
|
||||
3 {
|
||||
set errtxt timeout
|
||||
}
|
||||
4 {
|
||||
set errtxt timeout1
|
||||
}
|
||||
default {
|
||||
set errtxt "unknown error"
|
||||
}
|
||||
}
|
||||
sct enum ${enumtxt}
|
||||
if {$errtxt eq ""} {
|
||||
updateval [sct]/state $txt
|
||||
hupdate [sct]/status ""
|
||||
} else {
|
||||
hupdate [sct]/status $errtxt
|
||||
updateval [sct]/state $errtxt
|
||||
}
|
||||
|
||||
set level [silent invalid result [hvali [sct]/readlevel]]
|
||||
if {! [string is double $level]} {
|
||||
hsetprop [sct]/readlevel geterror "illegal $type level reading"
|
||||
return idle
|
||||
}
|
||||
set state [sctval [sct]]
|
||||
set now [clock seconds]
|
||||
set lowlevel [hvali [sct]/lowlevel]
|
||||
if {$lowlevel < 0.0} {
|
||||
hupdate [sct]/lowlevel 0.0
|
||||
}
|
||||
if {$lowlevel > 90.0} {
|
||||
hupdate [sct]/lowlevel 90.0
|
||||
}
|
||||
set highlevel [hvali [sct]/highlevel]
|
||||
if {$highlevel > 100.0} {
|
||||
hupdate [sct]/highlevel 100.0
|
||||
}
|
||||
if {$highlevel < $lowlevel + 10.0} {
|
||||
hupdate [sct]/highlevel [expr $lowlevel + 10.0]
|
||||
}
|
||||
switch -- $state {
|
||||
-1 { # initializing
|
||||
hupdate [sct]/status "automatic $type filling off"
|
||||
hset [sct] 0
|
||||
sct lasttime 0
|
||||
changestate $type watch
|
||||
return idle
|
||||
}
|
||||
0 { # watching
|
||||
set minspeed [expr - 100.0 / [hvali [sct]/minholdhours] / 3600.]
|
||||
set maxspeed [expr - 100.0 / [hvali [sct]/maxholdhours] / 3600.]
|
||||
set s [calcsmooth $level $minspeed $maxspeed]
|
||||
if {$s < $lowlevel} {
|
||||
if {[sct badtime] > [hvali [sct]/badreadingminutes] * 60} {
|
||||
hupdate [sct]/status "automatic $type filling off - continuos bad reading"
|
||||
hset [sct] 2
|
||||
changestate $type off
|
||||
return idle
|
||||
}
|
||||
# start fill
|
||||
hset [sct] 1
|
||||
clientput "$type level low - start fill"
|
||||
} else {
|
||||
changestate $type stop
|
||||
}
|
||||
return idle
|
||||
}
|
||||
1 {
|
||||
set vcmd [silent 0 sct vessel_cmd]
|
||||
# check that vessel command works
|
||||
if {$vcmd ne "0" && [catch {[result $vcmd]}]} {
|
||||
clientput "WARNING: He vessel reading is configured, but not connected"
|
||||
sct vessel_cmd 0
|
||||
set vmd 0
|
||||
}
|
||||
set now [clock seconds]
|
||||
set s [hvali [sct]/smooth]
|
||||
sct minlevel [silent 999 sct minlevel]
|
||||
if {$s < [sct minlevel]} {
|
||||
sct minlevel $s
|
||||
}
|
||||
set vessel 999
|
||||
set maxspeed [expr 100.0 / [hvali [sct]/minfillminutes] / 60.]
|
||||
if {[sct tubecooling] && $now < [sct startfill] + [hvali [sct]/tubecoolingminutes] * 60 && $s < [sct minlevel] + 5} {
|
||||
# allow fill tube to get cold
|
||||
set minspeed [expr - 100.0 / [hvali [sct]/maxfillminutes] / 60.]
|
||||
} else {
|
||||
if {[sct tubecooling]} {
|
||||
sct tubecooling 0
|
||||
if {$vcmd ne "0"} {
|
||||
sct vstart_level [expr [result $vcmd]]
|
||||
# start time - 2 minutes
|
||||
sct vstart_time [expr $now - 120]
|
||||
sct vlast_time $now
|
||||
hupdate [sct]/vext [sct vstart_level]
|
||||
}
|
||||
}
|
||||
set minspeed [expr + 100.0 / [hvali [sct]/maxfillminutes] / 60.]
|
||||
if {$vcmd ne "0"} {
|
||||
set dt [expr $now - [sct vlast_time]]
|
||||
if {$dt > 0} {
|
||||
set slope [expr ([hvali [sct]/vext] - [sct vstart_level])/([sct vlast_time] - [sct vstart_time])]
|
||||
} else {
|
||||
set slope 0
|
||||
}
|
||||
set vessel [result $vcmd]
|
||||
set vext [expr [hvali [sct]/vext] + $slope * $dt]
|
||||
if {$vext < $vessel} {
|
||||
if {$vext < $vessel - 2.0} {
|
||||
set errcnt [silent 0 sct errcnt]
|
||||
incr errcnt
|
||||
if {$errcnt > 3} {
|
||||
hupdate [sct]/status "not enough progress on $type vessel - automatic ${type} filling off ($vext < $vessel - 2)"
|
||||
hset [sct] 2
|
||||
changestate $type off
|
||||
return idle
|
||||
}
|
||||
sct errcnt $errcnt
|
||||
} else {
|
||||
set vessel $vext
|
||||
}
|
||||
}
|
||||
hupdate [sct]/vext $vessel
|
||||
sct vlast_time $now
|
||||
}
|
||||
}
|
||||
if {$vessel < [silent 0 hvali [sct]/vessellimit]} {
|
||||
hupdate [sct]/status "$type vessel empty - automatic ${type} filling off"
|
||||
hset [sct] 2
|
||||
changestate $type off
|
||||
return idle
|
||||
}
|
||||
if {[calcsmooth $level $minspeed $maxspeed] <= $highlevel} {
|
||||
# continue filling
|
||||
changestate $type fill
|
||||
return idle
|
||||
}
|
||||
clientput "$type level high - stop fill"
|
||||
hset [sct] 0
|
||||
changestate $type watch
|
||||
return idle
|
||||
}
|
||||
2 {
|
||||
set minspeed [expr - 100.0 / [hvali [sct]/minholdhours] / 3600.]
|
||||
set maxspeed [expr + 100.0 / [hvali [sct]/minfillminutes] / 60.]
|
||||
calcsmooth $level $minspeed $maxspeed
|
||||
}
|
||||
}
|
||||
return idle
|
||||
}
|
||||
|
||||
proc ccu4ext::writeExt {type {activate 1}} {
|
||||
sct update [sct target]
|
||||
hupdate [sct]/smooth [silent 0 result [hvali [sct]/readlevel]]
|
||||
switch -- [sct target] {
|
||||
# watching
|
||||
0 {
|
||||
catch {logsetup [sct]/vext clear}
|
||||
hupdate [sct]/status ""
|
||||
eval [silent "expr 0" sct slow_cmd]
|
||||
if {$activate} {
|
||||
changestate $type watch
|
||||
}
|
||||
return idle
|
||||
}
|
||||
# inactive
|
||||
2 {
|
||||
catch {logsetup [sct]/vext clear}
|
||||
eval [silent "expr 0" sct slow_cmd]
|
||||
if {[hvali [sct]/status] eq ""} {
|
||||
hupdate [sct]/status "automatic ${type} filling off"
|
||||
}
|
||||
clientput "ERROR: [hvali [sct]/status]"
|
||||
if {$activate} {
|
||||
changestate $type off
|
||||
}
|
||||
return idle
|
||||
}
|
||||
# fill
|
||||
1 {
|
||||
hupdate [sct]/status ""
|
||||
set vcmd [silent 0 sct vessel_cmd]
|
||||
if {$vcmd ne "0"} {
|
||||
set vlev [silent 60 result $vcmd]
|
||||
if {$vlev == 60} {
|
||||
clientput "WARNING: vessel level meter not connected - proceed without it"
|
||||
sct vessel_cmd 0
|
||||
} elseif {$vlev < [hvali [sct]/vessellimit] + 3.0} {
|
||||
hupdate [sct]/status "vessel not full enough - automatic ${type} filling off"
|
||||
clientput [hvali [sct]/status]
|
||||
sct update 2
|
||||
if {$activate} {
|
||||
changestate $type off
|
||||
}
|
||||
return idle
|
||||
}
|
||||
}
|
||||
sct minlevel 100
|
||||
sct errcnt 0
|
||||
sct startfill [clock seconds]
|
||||
sct tubecooling 1
|
||||
# eval [split [silent "expr 0" sct fast_cmd]]
|
||||
eval [silent "expr 0" sct fast_cmd]
|
||||
if {$activate} {
|
||||
changestate $type fill
|
||||
}
|
||||
return idle
|
||||
}
|
||||
}
|
||||
return idle
|
||||
}
|
Reference in New Issue
Block a user