Files
sea/tcl/drivers/heliox.tcl

321 lines
8.5 KiB
Tcl

namespace eval heliox {
}
source drivers/trun.tcl
proc stdConfig::heliox {} {
variable name
controller syncedprot
obj Heliox -drive out
prop layoutpos -10
prop check heliox::check_set
prop write stdSct::complete
# prop label set
tdrive $name -log 1
kids heliox {
node mode -int wr
prop enum undefined=0,hiT=1,midT=2,lowT=3,condense=4
prop read heliox::read
prop check heliox::check_mode
prop write heliox::complete
node lasts_until -text upd
prop visible False
default 0
node pot_state -text upd
node target_hours par 48
prop help "how many hours the pot should last (< 75)"
node holdflow out
default 1.5
prop check heliox::check_holdflow
prop help "flow for holding pressure"
prop write stdSct::complete
node condenseflow out
default 3
prop check heliox::check_condenseflow
prop help "flow for condensing"
prop write stdSct::complete
}
catch {
hsetprop /tt getsample hvali /th/pot
} msg
clientput $msg
}
proc heliox::check_set {} {
# save for later
sct goto [sct target]
if {[sct target] < 1.6} {
set condense_text ""
if {[hvali [sct]/lasts_until] > [DoubleTime]} {
if {[hvali [sct]/mode] < 3} {
hupdate [sct]/mode 3
}
} elseif {[hvali [sct]/mode] == 4} {
set condense_text "running"
} else {
hupdate [sct]/mode 4
set condense_text "started"
}
# sct goto [sct target]
if {$condense_text ne ""} {
sct print "going to [sct target] K might take a while - condense process is $condense_text"
}
} else {
if {[sct target] > 25} {
hupdate [sct]/mode 1
} elseif {[sct target] < 22} {
hupdate [sct]/mode 2
} elseif {[hval [sct]/mode] < 1 || [hval [sct]/mode] > 2} {
hupdate [sct]/mode 1
}
}
set mainsensor /th/pot
switch [sctval [sct]/mode] {
1 {
nv set [hvali [sct]/holdflow]
th setsorb/channel C
th setsorb 20
th mainloop set
tt dblctrl 1
run tt [sct target]
}
2 {
nv set [hvali [sct]/holdflow]
th setsorb/channel C
th setsorb 20
th mainloop set
tt dblctrl 0
tt set 1.25
th set [sct target]
}
3 {
nv set [hvali [sct]/holdflow]
th setsorb/channel B
th mainloop setsorb
th set 0
if {[sct target] != [hvali [sct]]} {
th setsorb [sct target]
}
set mainsensor /th/low
tt dblctrl 0
tt set 1.25
set state "low-T mode"
}
4 {
th setsorb/channel C
th setsorb 40
th set 0
th mainloop setsorb
tt dblctrl 0
tt set 1.25
catch {hdelprop /ts/mode soft_deadline}
}
default {
error "bad mode"
}
}
setmainsensor $mainsensor
sct update [sct target]
hsetprop /ts target [silent 0 sct goto]
hsetprop /th target [silent 0 sct goto]
}
proc heliox::setmainsensor {mainsensor} {
if {$mainsensor eq "/th/low"} {
set old /th/pot
} else {
set old /th/low
}
catch {[sct controller] killupdatescript $old "updateval [sct objectPath]"}
[sct controller] updatescript $mainsensor "updateval [sct objectPath]"
hsetprop [sct objectPath] mainsensor $mainsensor
}
proc heliox::check_mode {} {
set mainsensor /th/pot
switch [sct target] {
0 {
}
1 {
nv set [hvali [sct parent]/holdflow]
if {[sct target] != [hvali [sct]]} {
th set [hvali /th/target]
}
th setsorb/channel C
th setsorb 20
th mainloop set
set state "hi-T mode"
}
2 {
nv set [hvali [sct parent]/holdflow]
if {[sct target] != [hvali [sct]]} {
th set [hvali /th/target]
}
th setsorb/channel C
th setsorb 20
th mainloop set
set state "mid-T mode"
}
3 {
nv set [hvali [sct parent]/holdflow]
if {[hvali [sct parent]/lasts_until] > [DoubleTime]} {
th set 0
th setsorb/channel B
th mainloop setsorb
if {[sct target] != [hvali [sct]]} {
th setsorb [expr min(1.8, [hvali /th/target])]
}
tt set 1.25
tt dblctrl 0
} else {
clientput "the 3He pot is probably empty"
error "condense needed before lowT mode"
}
set mainsensor /th/low
set state "low-T mode"
}
4 {
th set 0
th setsorb/channel C
th mainloop set
th setsorb 40
tt set 1.25
tt dblctrl 0
set state "-> condense"
hsetprop /th target 0.25
hsetprop /ts target 0.25
catch {hdelprop /ts/mode soft_deadline}
}
}
setmainsensor $mainsensor
clientput "the 3He pot [hvali [sct parent]/pot_state]"
sct update [sct target]
}
proc heliox::check_condenseflow {} {
if {[sctval [sct parent]/mode] == 4} {
nv set [sct target]
}
sct update [sct target]
}
proc heliox::check_holdflow {} {
if {[sctval [sct parent]/mode] != 4} {
nv set [sct target]
}
sct update [sct target]
}
proc heliox::complete {} {
sct print [lindex {undefined "hi-T mode" "mid-T mode" "low-T mode" "-> condense"} [sct target]]
return idle
}
proc heliox::read {} {
set now [DoubleTime]
set lasts_until [hvali [sct parent]/lasts_until]
# calculate additional losses
set lasttime [silent 0 sct lasttime]
if {$lasttime == 0} {
set delay 5
} else {
set delay [expr min(30, $now - $lasttime)]
}
set ts [result th pot]
set tsorb [result th sorb]
sct lasttime $now
set mode [hvali [sct]]
if {(($mode == 3 && $ts > 2) || ($ts > 3)) && $tsorb < 10} {
if {$lasts_until} {
clientput "3He pot went empty"
}
set lasts_until 0
} else { # check losses through heating
# factor 30000 is a rough guess (measured 25000 for regulation th pot at 1 K)
set loss [expr $delay * ([silent 0 result th set/power] + [silent 0 result tt set/power]) * 30000]
set lasts_until [expr $lasts_until - $loss]
if {$loss > 0 && $lasts_until < $now} {
if {$lasts_until > 0} {
clientput "guess 3He pot went empty"
}
set lasts_until 0
}
}
if {$mode == 4} {
if {$ts > 3} {
# above 3 K: set deadline
nv set [hvali [sct parent]/condenseflow]
set lasts_until 0
sct condense_deadline [expr $now + 3600]
} elseif {[result th sorb] > 39} {
nv set [hvali [sct parent]/condenseflow]
# 3He vapor pressure: 200 mbar at 2 K, power law
set p [expr 200 * ($ts / 2.0) ** 3.5]
# dump pressure at condensation start
set p_max 410
# the amount of 3He corresponding to 1 mbar in the dump lasts that many hours
set hours_per_mbar 0.3
# the condensation does not stop immediately -> add 8 hours
set hours [expr max(0, $hours_per_mbar * ($p_max - $p)) + 8]
set target_hours [hvali [sct parent]/target_hours]
set lasts_until [expr int($now + $hours * 3600)]
calc_pot $lasts_until
sct condense_deadline [silent [expr $now + 3600] sct condense_deadline]
if {$hours > 8} {
set dl [expr $now + ($target_hours - $hours) * 30]
set sdl [silent $dl sct soft_deadline]
if {$dl <= $sdl} {
sct soft_deadline $dl
} elseif {$now > $sdl + 300} {
clientput "stop condensing - target_hours is probably too high - expect only [expr round($hours)] h hold time"
set target_hours $hours
}
} elseif {$now > [sct condense_deadline]} {
clientput "condense timeout - hold time is probably very low"
set target_hours $hours
}
if {$hours >= $target_hours} {
th setsorb 0
th setsorb/channel B
th mainloop setsorb
th setsorb [silent 0.25 hgetpropval [sct parent] goto]
# switch to lowT and trigger check_mode
hset [sct] 3
nv set [hvali [sct parent]/holdflow]
clientput "the 3He pot [hvali [sct parent]/pot_state]"
}
}
}
calc_pot $lasts_until
sct update [hvali [sct]]
return idle
}
proc heliox::calc_pot {lasts_until} {
set now [clock seconds]
set lasts_until [expr int($lasts_until)]
hupdate [sct parent]/lasts_until $lasts_until
if {$lasts_until == 0} {
hupdate [sct parent]/pot_state "is empty"
} elseif {$lasts_until > 0} {
set dynow [clock format $now -format "%j"]
set dayofyear [clock format $lasts_until -format "%j"]
if {$dayofyear == $dynow} {
set day today
} elseif {$dayofyear == $dynow + 1} {
set day tomorrow
} else {
set day [clock format $lasts_until -format %Y-%m-%d]
}
hupdate [sct parent]/pot_state "lasts until $day [clock format $lasts_until -format %H:%M]"
}
}