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]" } }