Files
sea/tcl/drivers/dil12.tcl

1509 lines
41 KiB
Tcl

# dil combi (2x LS370 + IGH)
namespace eval dil12 {
}
proc stdConfig::dil12 args {
variable name
variable path
variable node
variable ctrl
scanargs $args var -reg370 /treg -mon370 /tmon -hasturbo 0
variable hostport none
controller syncedprot 30
obj dilcombi -drive wr
prop layoutpos -10
prop @monpath $mon370
prop @regpath $reg370
prop label set
if {[info proc stdConfig::tdrive] eq ""} {
namespace eval :: {
source drivers/trun.tcl
}
}
tdrive $name -log 1
hsetprop $path/set check dil12::check_set
hsetprop $path/set visible false
kids "main dilution control" {
node ramp out
prop help {ramp [K/min]}
prop check dil12::check_ramp
prop write stdSct::completeUpdate
node heaterselect -text out
prop label "heater on "
prop enum sample,mix,mix(temporarely)
default sample
prop check dil12::check_heaterselect
prop write stdSct::completeUpdate
node control -text out
prop label "control sensor "
prop help "click off to reload list"
prop enum "off"
# for seadesc:
prop enum_ off=0,mix=5,sample=6,samplehtr=8
default off
prop check dil12::check_control
prop write stdSct::completeUpdate
# prop regctrl _[string range $reg370 1 end]
$ctrl queue $node read dil12::set_chanlist
node heatermode -text out
prop enum disabled=-1,off=0,on=1
prop check named_enum
prop write dil12::set_heatermode
pollperiod 5 5
node heaterrange -text wr
prop enum off=0,2uW=1,20uW=2,200uW=3,2mW=4,20mW=5
prop check dil12::check_heaterrange
prop write stdSct::complete
prop read dil12::get_heater
node autoheater -int wr
default 1
prop enum 1
prop check stdSct::completeUpdate
prop write stdSct::complete
prop read dil12::autoheater
prop help "automatic heater range"
prop n_overflow 0
kids "auto heater range parameters" {
node wlp0 par 0.06
prop label "base T"
prop help "weak link base temperature (used for auto heater)"
node wlp1 par 0.12
prop label "T for 1uW"
prop help "weak link temperature at 1 uW (used for auto heater)"
node wlp2 par 0.35
prop label "T for 10uW"
prop help "weak link temperature at 10 uW (used for auto heater)"
node wlp3 par 1
prop label "T for 100uW"
prop help "weak link temperature at 100 uW (used for auto heater)"
node wlp4 par 2.8
prop label "T for 1mW"
prop help "weak link temperature at 1 mW (used for auto heater)"
node mxp0 par 0.02
prop label "base T"
prop help "weak link base temperature (used for auto heater)"
node mxp1 par 0.03
prop label "T for 1uW"
prop help "mix.ch. temperature at 1 uW (used for auto heater)"
node mxp2 par 0.07
prop label "T for 10uW"
prop help "mix.ch. temperature at 10 uW (used for auto heater)"
node mxp3 par 0.15
prop label "T for 100uW"
prop help "mix.ch. temperature at 100 uW (used for auto heater)"
node mxp4 par 0.4
prop label "T for 1mW"
prop help "mix.ch. temperature at 1 mW (used for auto heater)"
node switchdown par 5
prop label "switch down"
prop help "percentage for auto heater switch down"
node switchup par 50
prop label "heater threshold"
prop help "when the calculated power is above this percentage, use higher range"
}
node autoprop -int out
default 1
prop check dil12::check_autoprop
prop write stdSct::complete
prop enum 1
prop newline 1
prop help "change prop value depending on actual power"
kids "PI parameters" {
node prop out
default 1
prop help "prop value (maximum prop value when autheater is on)"
prop check dil12::check_prop
prop label "max. prop"
prop write stdSct::completeUpdate
node integ out
default 5
prop help {integral value [sec], deriv is set to 0 on change}
prop check dil12::check_integ
prop write stdSct::completeUpdate
}
node instructions -text upd
default ""
prop label ""
node auto -text wr
if {$hasturbo} {
set t_enum ",pipe_pump=11,pipes_ready=12"
} else {
set t_enum ""
}
prop enum off=0,cool_vti=1$t_enum,ready_for_sorbpump=2,sorb_pump=3,condense=4,circulate=5,remove_only=60,remove_and_warmup=62,remove_and_condense=61,remove_and_sorbpump=63,finished=7
prop enumsplit 3,60,7
default 0
prop read dil12::pollauto
prop write dil12::startauto
prop check dil12::check_auto
prop opentime 0
prop closetime 0
prop g3overg1 0.5
prop time2halve 15
kids "auto parameters" {
node usetrap -text par 0
prop enum trap_A,trap_B
prop check named_enum
if {!$hasturbo} {
node hasturbo -int par $hasturbo
prop enum 1
} else {
node hasturbo -int -internal par $hasturbo
prop enum 1
}
node pipes_pumped -int par 0
prop enum 1
node cool_crit -text par {vti<4 && onek<4 && sorb<4 && still<4}
prop help "criterium for transition to ready_for_sorbpump"
prop width 40
node pumptime1 par 1200
prop help "pump time \[sec] while sorb at 40"
node pumptime2 par 900
prop help "pump time \[sec] while sorb cools down"
node pumptime_remaining upd
prop help "remeaining pump time \[min]"
node condensep par 700
prop label "condense pressure"
node dumptarget par 0
node condenseflow out
default 8
prop check dil12::check_condenseflow
prop write stdSct::complete
prop label "condense n.v. flow"
prop help "VTI flow for condensing and min. flow for cooling"
node circulateflow out
default 4
prop check dil12::check_circulateflow
prop write stdSct::complete
prop label "circulate n.v. flow"
prop help "VTI flow for circulating (may be changed during circulation)"
node onekstate -text out
prop label "one K state"
prop enum normal,fill,optimize
default normal
prop check dil12::check_onek
prop write dil12::startauto
node oneklimit par 2
node minflow par 2
prop help "minimum VTI flow (optimize stops at this value)"
node p1low par 0.1
prop help "p1 value indicating a negligible mixture amount"
node p2low par 0.1
prop help "p2 value indicating a good vacuum"
node warmup_t par 80
prop help "VTI temperature to reach when remove_and_warmup"
node vti_t par 10
prop help "VTI temperature to reach when remove_only"
node xgas -text wr
prop enum pump,add,filled,empty
default empty
prop label "x-gas state"
prop check dil12::check_xgas
prop write stdSct::complete
prop read dil12::read_xgas
node xgas_pulse par 60
prop help {opening time for xgas capillary [sec]}
node removephase -text out
prop enum raw_remove,wait_p1_low,wait_v6_open,wait_a_little,wait_v6_closed,wait_t_warmup
prop label "remove mixture status"
prop check dil12::check_removephase
prop write stdSct::completeUpdate
node ignore_vti_temp -int par 0
prop enum 1
}
}
hset $name/heatermode 0
dolater 0 hset $name/autoprop/integ 5
dolater 0 apply_dilpars
}
proc dil12::check_set {} {
hset [sct @regpath]/set [sct target]
if {[sct target] == 0} {
hset [sct parent]/heaterrange 0
} elseif {[enum_val [sct parent]/heaterrange] == 0} {
hset [sct parent]/heaterrange 1
}
hset [sct parent]/heaterselect [sctval [sct parent]/heaterselect]
hset [sct parent]/control [sctval [sct parent]/control]
}
proc dil12::check_heaterselect {} {
set req [named_enum]
if {$req} {
#mix
hset [sct @regpath]/analog2 0
hset [sct @monpath]/samplehtr/active 1
if {$req ne "1"} {
# mix (temporarely)
sct requested 2
}
foreach hr {0 1 2 3 4} {
hsetprop [sct parent]/autoheater/wlp$hr visible false
hdelprop [sct parent]/autoheater/mxp$hr visible
}
} else {
#sample
hset [sct @regpath]/analog2 100
hset [sct @monpath]/samplehtr/active 0
foreach hr {0 1 2 3 4} {
hsetprop [sct parent]/autoheater/mxp$hr visible false
hdelprop [sct parent]/autoheater/wlp$hr visible
}
}
}
proc dil12::set_chanlist {{value -1}} {
set enum off
foreach kid [hlist [sct @regpath]] {
set chan [silent -1 hgetpropval [sct @regpath]/$kid @channel]
set monactive [silent -1 sctval [sct @monpath]/$kid/active]
if {$chan > 0 && ![silent 0 hgetpropval [sct @regpath]/$kid manualactive]} {
set regactive [sctval [sct @regpath]/$kid/active]
if {[sct enum] eq "off"} {
hsetprop [sct @regpath]/$kid UPDS [sct controller]
[sct controller] updatescript [sct @regpath]/$kid "dil12::updateIfSelected [sct objectPath] [sct]"
}
if {$monactive > 0 || $regactive} {
if {$chan == $value} {
hset [sct @regpath]/set/channel $chan
if {$monactive > 0} {
hset [sct @monpath]/$kid/active 0
}
if {$regactive == 0} {
hset [sct @regpath]/$kid/active 1
}
} elseif {$value > 0} {
if {$monactive == 0} {
hset [sct @monpath]/$kid/active 1
}
if {$regactive > 0} {
hset [sct @regpath]/$kid/active 0
}
}
append enum ",$kid=$chan"
}
}
}
if {$value == 0} {
hset [sct @regpath]/set/mode 0
}
if {[sct enum] eq "off"} {
[sct controller] updatescript [sct @regpath]/set "hsetprop [sct objectPath] target"
[sct controller] updatescript [sct @regpath]/set/ramp "hupdate [sct objectPath]/ramp"
[sct controller] updatescript [sct @regpath]/set/prop "dil12::updateIfOff [sct objectPath]/autoprop/prop [sct objectPath]/autoprop"
[sct controller] updatescript [sct @regpath]/set/integ "hupdate [sct objectPath]/autoprop/integ"
}
sct enum $enum
return idle
}
proc dil12::check_control {} {
set req [named_enum]
dil12::set_chanlist $req
}
proc dil12::updateIfSelected {objpath chanpath value} {
if {[hvali [sct]/active] && [enum_val $chanpath] == [sct @channel]} {
set e [silent 0 sct geterror]
if {$e eq "0"} {
updateval $objpath $value
hsetprop $objpath updatetime [clock seconds]
} else {
updateerror $objpath $e 1
}
}
}
proc dil12::updateIfOff {path flagpath value} {
if {[hvali $flagpath] == 0} {
hupdate $path $value
}
}
proc dil12::check_IGHpower {lp} {
if {abs($lp - [sct target]) > $lp * 0.1} {
error "linear power can not be changed directly, use ts heaterrange instead"
}
sct target $lp
}
proc dil12::set_heatermode {} {
set enumval [lindex [sct requested] 0]
if {$enumval <= 0} {
dil htrrange 0
if {[hvali [sct @regpath]/set/mode] > 0} {
hset [sct @regpath]/set/mode $enumval
}
sct heater_range 0
sct complete dil12::complete_heaterrange
} else {
sctsync {
set old [result dil htrrange]
# this is a fix, which might no longer be needed (special handling of enums)
set r [lindex [split [sctval [sct parent]/heaterrange] ] 0]
# original: set r [sctval [sct parent]/heaterrange]
if {$r < 1} {
set r 1
} elseif {$r > 5} {
set r 5
}
set lp [expr pow(10,$r) * 0.2e-6]
if {[hvali [sct @regpath]/set/mode] < 1} {
hset [sct @regpath]/set/mode 1
hupdate [sct @regpath]/set/linearpower $lp
hupdate [sct @regpath]/set/maxpower $lp
} else {
hsetprop [sct @regpath]/set/linearpower check "dil12::check_IGHpower $lp"
hupdate [sct @regpath]/set/maxpower $lp
hset [sct @regpath]/set/linearpower $lp
}
sct heater_fact [expr pow(10,$r-$old)]
sct heater_range $r
if {$r >= $old} {
sct complete dil12::heaterrange_p
sct complete_p dil12::heaterrange_h
sct complete_h dil12::complete_heaterrange
} else {
sct complete dil12::heaterrange_h
sct complete_h dil12::heaterrange_p
sct complete_p dil12::complete_heaterrange
}
}
}
return complete
}
proc dil12::heaterrange_p {} {
if {[sctval [sct parent]/autoprop]} {
set htr [silent 0 hgetpropval [sct @regpath]/set/linearpower oldhtr]
set prop [expr [sctval [sct parent]/autoprop/prop] * $htr * 0.01 / [sct heater_fact]]
} else {
set prop [hvali [sct @regpath]/set/prop]
}
# set prop and manual_output (manual_output calculated from lsc::wait370heaterchange)
sctsync {
hset [sct @regpath]/set/prop $prop
}
return complete_p
}
proc dil12::heaterrange_h {} {
sctsync {
dil htrrange [sct heater_range]
}
return complete_h
}
proc dil12::complete_heaterrange {} {
sct update [sct target]
hupdate [sct parent]/heaterrange [sct heater_range]
return idle
}
proc dil12::check_heaterrange {} {
set req [named_enum]
if {$req == 0} {
hset [sct parent]/heatermode 0
} else {
hset [sct parent]/heatermode 1
}
}
proc dil12::get_heater {} {
if {[silent "" hgetpropval [sct parent]/heaterrange requested] ne ""} {
return idle
}
set r [result dil htrrange]
if {$r eq ""} {
set r 0
}
if {$r > 0 || [silent 0 sct geterror] ne "0"} {
enum_update $r
}
set m [sctval [sct @regpath]/set/mode]
if {$m > 1} {
set m 1
}
hupdate [sct parent]/heatermode $m
return idle
}
proc dil12::check_autoprop {} {
if {[sct target]} {
hsetprop [sct]/prop label "max. prop"
} else {
hsetprop [sct]/prop label "prop"
}
sct update [sct target]
}
proc dil12::neededPower {T} {
# needed power log10(p/uW) for T
if {[enum_val [sct parent]/heaterselect] == 0} { # weak link
set nam wl
set Tbase [hvali [sct]/${nam}p0]
set Tmix [hvali [sct @regpath]/mix]
set Tsq [expr $T * $T - $Tmix * $Tmix]
} else { # mix. ch.
set nam mx
set Tbase [hvali [sct]/${nam}p0]
set Tsq [expr $T * $T - $Tbase * $Tbase]
}
if {$Tsq < 1e-6} {
set Tsq 1e-6
}
set logp 0
set Tsq0 [expr pow([hvali [sct]/${nam}p1],2) - $Tbase * $Tbase]
if {$Tsq0 < 1e-6} {
set Tsq0 1e-6
}
if {$Tsq < $Tsq0} {
return [expr log10($Tsq) - log10($Tsq0) + $logp]
}
foreach hr {2 3 4} {
set Tsqi [expr pow([hvali [sct]/${nam}p$hr],2) - $Tbase * $Tbase]
if {$Tsqi < 1e-6} {
set Tsqi 1e-6
}
if {$Tsq <= $Tsqi} {
if {$Tsqi <= $Tsq0} {
return $logp
} else {
return [expr (log10($Tsq) - log10($Tsq0)) / (log10($Tsqi) - log10($Tsq0)) + $logp]
}
}
set Tsq0 $Tsqi
incr logp
}
return [expr log10($Tsq) - log10($Tsq0) + $logp]
}
proc dil12::neededHr {htr T} {
return [expr int([neededPower $T] - log10($htr * 0.01) + 1.7)]
}
proc dil12::autoheater {} {
if {[silent 0 sct geterror] ne "0"} {
sct update 1
}
set hr [enum_val [sct parent]/heaterrange]
if {[hvali [sct]] == 0 && $hr == 0 || [enum_val [sct parent]/heatermode] < 1 \
|| [result dil pmix] > 0} {
return idle
}
set htr [hgetpropval [sct @regpath]/set/power htr]
set t [hvali [sct parent]]
set regT [hvali [sct @regpath]/set/reg]
if {[hvali [sct]]} {
# auto heater on
# switch up percentage (90 % used in comments below)
set switchup [hvali [sct]/switchup]
# min. heater range needed for regT with an estimated percentage of less than "switchup"
set minhr [neededHr $switchup $regT]
# switch down percentage (5 % used in comments below)
set switchdown [hvali [sct]/switchdown]
set n_overflow [sct n_overflow]
if {$htr <= $switchdown} {
if {$n_overflow > 0} {
set n_overflow 0
}
incr n_overflow -1
} elseif {$htr >= 100} {
if {$n_overflow < 0} {
set n_overflow 0
}
incr n_overflow
} else {
set n_overflow 0
}
sct n_overflow $n_overflow
set minhr [neededHr 100 $regT]
# clientput "regT $regT hr $hr minhr $minhr neededPower [neededPower $regT]"
if {$hr < 5 && ($minhr > $hr || $n_overflow > 2)} {
if {$minhr > $hr} {
set hr [neededHr $switchup $regT]
if {$hr > 5} {
clientput "increase heaterrange to 5 (needed $hr for T = $regT)"
set hr 5
} else {
clientput "increase heaterrange to $hr (needed for T = $regT)"
}
} else {
incr hr
clientput "increase heaterrange to $hr (heater at 100 %)"
}
hset [sct parent]/heaterrange $hr
return "stdSct::complete"
} elseif {$hr > 1 && $minhr < $hr - 1 && $n_overflow < -2} {
if {$minhr < $hr - 1} {
set hr [neededHr $switchup $regT]
if {$hr < 1} {
clientput "decrease heaterrange to 1 (needed $hr for T = $regT)"
set hr 1
} else {
clientput "decrease heaterrange to $hr (needed for T = $regT)"
}
} else {
incr hr -1
clientput "decrease heaterrange to $hr ($htr < $switchdown %)"
}
hset [sct parent]/heaterrange $hr
return "stdSct::complete"
}
}
if {[hvali [sct parent]/autoprop]} {
set prop [expr $htr * 0.01]
set logpcalc [neededPower $regT]
if {$logpcalc < -1.0} {
set logpcalc -1.0
}
set p [expr 0.5 * pow(10,$logpcalc - 0.3 - $hr)]
if {$p > $prop} {
set prop $p
}
if {$prop < 0.01} {
set prop 0.01
} elseif {$prop > 1.0} {
set prop 1.0
}
set old [hvali [sct @regpath]/set/prop]
set prop [format "%.2g" [expr $prop * [hvali [sct parent]/autoprop/prop]]]
if {abs($prop - $old) > $prop * 0.01} {
hset [sct @regpath]/set/prop $prop
}
}
return idle
}
proc dil12::check_prop {} {
if {[sctval [sct]] == 0} {
hset [sct @regpath]/set/prop [sct target]
}
}
proc dil12::check_ramp {} {
hset [sct @regpath]/set/ramp [sct target]
}
proc dil12::check_integ {} {
hset [sct @regpath]/set/integ [sct target]
hset [sct @regpath]/set/deriv 0
}
proc dil12::pollauto {} {
set msg [silent 0 hgetpropval [sct] geterror]
if {$msg ne "0"} {
# no error messages here / must be on the instructions node
dil12::msg $msg
hdelprop [sct] geterror
}
if {[catch is_dil_cool msg]} {
# clientput "is_dil_cool failed: $msg"
}
return [dil12::autostep [enum_txt [sct]] 0]
}
proc dil12::startcool {} {
nv set [silent 10 hvali [sct]/condenseflow]
nv 2
sorb mode 0
if {[hvali [sct]/hasturbo]} {
if {![hvali [sct]/pipes_pumped]} {
dil12::set_VtiT 10.25
return
}
}
dil12::set_VtiT 1.25
dil12::openvalves v1 v6 v3 v5
}
proc dil12::is_dil_cool {} {
set vti [get_VtiT]
set sorb [silentval 0 [sct @monpath]/sorb]
set onek [silentval 0 [sct @monpath]/onek]
set still [silentval 0 [sct @monpath]/stillt]
set crit [hval [sct]/cool_crit]
set crit [string map "sorb $sorb vti $vti onek $onek still $still" $crit]
set failure [catch {set ret [expr $crit]}]
set_or_clr_msg $failure "ERROR: illegal cool criterium"
if {$failure} {
return 0
}
return $ret
}
proc dil12::check_cool_button {} {
if {[result dil extVersion] eq "0"} {
if {[is_dil_cool] && [sctval [sct]] != 0} { # not off
hset [sct] ready_for_sorbpump
}
} elseif {[result dil roots] > 0} { # "cool VTI" button
if {[is_dil_cool]} {
dil roots 0
}
set t [get_VtiSet]
if {$t != 10.25 && $t != 1.25 || [result nv] != 2} {
clientput "cooling VTI activated"
dil12::startcool
}
}
}
proc dil12::check_trap {force} {
if {[result dil lowerN2] > 90} {
if {$force} {
error "you must fill the trap before condensing"
} else {
dil12::msg "please fill trap!"
}
return 1
}
return 0
}
proc dil12::autostep {phase init} {
if {$phase eq "6"} {
set phase remove_only
}
if {$init} {
set phase init_$phase
}
switch $phase {
init_off {
dil aux 0
dil roots 0
}
off - finished - cool_vti {
if {[result dil p2] > 1} {
hset [sct]/pipes_pumped 0
}
if {[result dil aux] > 0} {
if {[hvali [sct]/hasturbo]} {
# will be set to pumped after the pipe_pump step!
hset [sct]/pipes_pumped 0
hset [sct] pipe_pump
} else {
dil aux 0
hset [sct]/pipes_pumped 1
hset [sct] pipes_ready
}
}
dil12::check_cool_button
}
init_cool_vti {
if {[result dil p2] > 1} {
clientput "[sct]: p2 > 1 -> assume pipes are not pumped"
hset [sct]/pipes_pumped 0
}
dil12::msg ""
if {[enum_txt [sct]] eq "pipes_ready"} {
hset [sct] pipes_ready
}
dil12::startcool
}
init_pipe_pump {
if {[result dil aux] == 0} {
hset [sct] off
dil12::msg "please start the pipe_pump step from the IGH panel"
return idle
}
if {![hvali [sct]/hasturbo]} {
hset [sct] off
dil12::msg "we have no turbo pump"
hset [sct] off
return idle
}
set closed_valves [list v1 v2 v3 v4 v5 v7 v8 v9 v10 v11a v11b v12a v12b v13a v13b v14 v1a v2a v4a v5a]
set open_valves [list]
foreach v $closed_valves {
if {[result dil $v] > 0} {
lappend open_valves $v
}
}
if {[llength $open_valves]} {
dil12::msg "valve(s) $open_valves must be closed before pipe_pump"
hset [sct] off
return idle
}
dil12::openvalves v5a v2a v7 v2 v1 v6 vb_open
dil v4a 1
sct pumptime 0
dil12::msg "pumping, waiting for low pressures P1 and P2"
}
pipe_pump {
if {[result dil aux] == 0} {
dil v7 0
dil v11a 0
dil v11b 0
dil v12a 0
dil v12b 0
dil v4a 0
dil12::openvalves vm_open
hset [sct] off
return idle
}
dil12::check_cool_button
if {[result dil p1] < [hvali [sct]/p1low] && [result dil g1] < 5 &&
[result dil p2] < [hvali [sct]/p2low] && [result dil v6pos] > 50} {
if {[sct pumptime] == 0} {
dil12::openvalves v5a v2a v7 v2 v1 v6 v5 v3 vb_open
dil v4a 1
sct pumptime [expr [DoubleTime] + 105]
dil12::msg "pump for 2 more minutes"
} elseif {[DoubleTime] > [sct pumptime] && [result dil v6pos] > 99} {
# do not check for vb/vm here, as the user already might manipulate the valves
dil12::openvalves v1 v6 v3 v5
dil v4a 0
if {[DoubleTime] > [sct pumptime] + 15} {
hset [sct]/pipes_pumped 1
dil12::set_VtiT 1.25
hset [sct] pipes_ready
dil12::msg "close VB, open VM, open 3 valves on the stick, open dump valves and confirm on the IGH"
} else {
dil12::msg "pump for 15 more seconds"
}
}
# } elseif {[sct pumptime] != 0} {
# dil12::msg "there might be some mixure in TRAP A, please check"
}
}
init_pipes_ready {
if {![hvali [sct]/pipes_pumped]} {
dil12::msg "pipes must be pumped first (see [sct]/pipes_pumped)"
hset [sct] off
}
# do not check for vb/vm here, as the user already might manipulate the valves
dil12::openvalves v1 v6 v3 v5
sct wait4k 1
}
pipes_ready {
if {[enum_txt [sct]/xgas] eq "empty"} {
hset [sct]/xgas add
}
dil12::check_cool_button
if {[hvali [sct]/hasturbo]} {
if {[result dil aux] == 0} {
if {[silent 1 sct wait4k]} {
dil12::msg "wait for dilution unit to be < 4 K"
sct wait4k 0
}
}
} else {
dil aux 0
}
if {[is_dil_cool]} {
if {[result dil aux] == 0} {
hset [sct] sorb_pump
}
}
}
init_ready_for_sorbpump {
dil12::msg "please pump the IVC and switch to 'sorbpump'"
nv set [silent 5 hvali [sct]/circulateflow]
nv 2 ;# auto
}
ready_for_sorbpump {
}
init_sorb_pump {
# Dec 2014: open valve 9 in order not to have overpressure
dil12::clearButtons
dil12::openvalves v1 v6 v3 v5 v9 vm_open
if {[hvali [sct]/hasturbo]} {
hset [sct]/xgas pump
}
nv set [silent 3 hvali [sct]/minflow]
nv 2 ;# auto
run sorb 40
sct sorbstart 0
dil12::msg ""
dil12::set_VtiT 5
}
sorb_pump {
if {[sct sorbstart] == 0} {
if {([hvali [sct @monpath]/onek] > 4) && \
([hvali [sct @monpath]/stillt] > 4) && \
([hvali [sct @regpath]/mix] > 4)} {
sct sorbstart [clock seconds]
}
} elseif {[hvali /sorb/mode]} {
set remt [expr [sct sorbstart] + [hvali [sct]/pumptime1] - [clock seconds]]
if {$remt <= 0} {
run sorb 0
sorb mode 0
sct sorbstart [clock seconds]
} else {
hupdate [sct]/pumptime_remaining [expr int(($remt + [hvali [sct]/pumptime2]) / 60)]
}
} elseif {[hvali /sorb/mode] == 0} {
set remt [expr [sct sorbstart] + [hvali [sct]/pumptime2] - [clock seconds]]
if {$remt < 0} {
hset [sct] condense
hupdate [sct]/pumptime_remaining 0
} else {
hupdate [sct]/pumptime_remaining [expr int($remt / 60)]
}
}
}
init_condense {
dil12::check_trap 0
dil12::clearButtons
if {[enum_val [sct parent]/heaterselect] == 2} {
# switch heating back to sample
hset [sct parent]/heaterselect 0
}
dil12::openvalves v1 v6 v12 v13 vm_open
if {[hvali [sct]/hasturbo]} {
hset [sct]/xgas pump
}
sorb mode 0
dil12::set_VtiT 1.25
hset [sct parent]/set 0
hset [sct parent]/heatermode 0
nv set [silent 10 hvali [sct]/condenseflow]
nv 2 ;# auto
sct condensestart [clock seconds]
dil12::msg ""
}
condense {
dil12::check_trap 0
if {[result dil aux] > 0} {dil aux 0}
if {[result nv] == 4} {
# if valve is open, go to automatic after 10 sec
if {[clock seconds] > [silent 0 sct condensestart] + 10} {
nv 2
}
}
set cp [expr double([hvali [sct]/condensep])]
set dt [expr double([hvali [sct]/dumptarget])]
set g1 [result dil g1]
set g2 [result dil g2]
if {$g2 < $g1} {
# workaround for bad G1 sensor on DIL2
set g1 $g2
}
set g3 [result dil g3]
if {$cp > $g3 + 500} {
set cp [expr $g3 + 500]
}
set g1dif [expr $cp - $g1]
set p1 [result dil p1]
if {[result dil v14] && [sct utime] > [sct opentime] + 9} {
set g3 $p1
if {$g3 < 0.5} {
set g3 0.0
}
}
if {$p1 < 10.0 && [result dil v6pos] > 30 && [sct utime] > [sct opentime] + 30} {
set lim $dt
if {$lim == 0.0} {
set lim 1.0
}
if {$g3 <= $lim} {
hset [sct] circulate
return idle
}
# calculate the amount of gas to remove in units of dump pressure
set amount [expr $g1dif * [sct g3overg1]]
if {$amount > 1.0} {
if {$amount > 50} {
set amount 50
}
if {$g3 < $dt + $amount} {
set amount [expr $g3 - $dt]
if {$dt > 1.0} {
set amount [expr $amount + 1.0]
}
}
set openperiod [expr log(($g3 + 0.1)/($g3 - $amount + 0.1)) * [sct time2halve]]
if {$openperiod > 0.1} {
if {[sct closetime] == 0} {
# last pulse has finished
[sct controller] poll [sct] 0.01 write "dil12::timerauto [expr [DoubleTime] + 5]"
}
set opentime [sct utime]
if {![result dil v14]} {
sct opentime $opentime
}
sct closetime [expr $opentime + $openperiod]
dil v14 1
}
}
}
}
init_circulate {
dil12::clearButtons
dil12::openvalves v1 v6 v12 v13 vm_open
sorb mode 0
hset [sct]/onekstate 0
nv set [silent 5 hvali [sct]/circulateflow]
if {[hval [sct]/ignore_vti_temp]} {
dil12::set_VtiT 0
nv 1 ;# controlled
} else {
dil12::set_VtiT 1.25
nv 2 ;# auto
}
dil12::msg ""
}
circulate {
if {[result dil aux] > 0} {dil aux 0}
switch [hvali [sct]/onekstate] {
0 { # normal
set tlim [expr [hvali [sct]/oneklimit] + 0.2]
if {[silent 0 hvali [sct @monpath]/onek] > $tlim} {
dil12::msg "oneK_T > $tlim -> increased VTI flow for refilling VTI"
hset [sct]/onekstate 1
}
}
1 { # increased flow for filling pumping space
set tlim [hvali [sct]/oneklimit]
if {[silent 0 hvali [sct @monpath]/onek] < $tlim} {
set circulateflow [expr [hvali [sct]/circulateflow] + 0.2]
hupdate [sct]/circulateflow $circulateflow
hset [sct]/onekstate 0
clientput "oneK_T < $tlim -> VTI full enough -> normal flow slighly increased to [hvali [sct]/circulateflow]"
}
}
2 { # optimize
set tlim [expr [hvali [sct]/oneklimit] + 0.2]
if {[silent 0 hvali [sct @monpath]/onek] > $tlim} {
dil12::msg "oneK_T > $tlim -> increased flow for refilling VTI"
hset [sct]/onekstate 1
} elseif {[clock seconds] - [sct optimize] > 1800} {
set circulateflow [expr [hvali [sct]/circulateflow] - 0.1]
set minflow [hvali [sct]/minflow]
if {$circulateflow <= $minflow} {
hupdate [sct]/circulateflow $minflow
hset [sct]/onekstate 1
clientput "end optimizing VTI flow - minimum $minflow reached"
} else {
hupdate [sct]/circulateflow $circulateflow
sct optimize [clock seconds]
clientput "reduced VTI flow to [hvali [sct]/circulateflow]"
nv set $circulateflow
if {[hval [sct]/ignore_vti_temp]} {
nv 1 ;# controlled
} else {
nv 2 ;# auto
}
}
}
}
}
}
init_finished {
# close all valves and zero all powers
dil12::clearButtons
dil12::openvalves
# close v4a
hset [sct]/xgas empty
sorb mode 0
if {[result dil v6pos] == 0} {
dil he3 0
}
nv set [silent 3 hvali [sct]/minflow]
nv 2
if {[enum_val [sct parent]/heaterselect] == 2} {
# switch heating back to sample
hset [sct parent]/heaterselect 0
}
if {[catch {vm 0}]} { # try to close VM
dil12::msg "please close VM"
}
}
default { # treat remove phases
if {[string match init_remove* $phase]} {
dil12::clearButtons
# init remove
dil12::openvalves v1 v6 v3 v5 v9 v12 v11 vm_open
hset [sct parent]/heatermode 0
if {$phase ne "remove_and_condense"} {
# heat sorb only when not condensing afterwards
run sorb 40
} else {
sorb mode 0
}
dil pstill 20
dil pmix 20
# pump trap on second path
if {[result dil v7] == 0} {
dil v8 1
dil v2 1
}
# fix needle valve
nv 0
if {[enum_val [sct parent]/heaterselect] != 1} {
# heating temporarely on mix. chamber
hset [sct parent]/heaterselect 2
} else {
# make sure heating on mix. chamber
hset [sct parent]/heaterselect 1
}
dil12::set_VtiT 5.0
hset [sct]/removephase raw_remove
} elseif {[string match remove* $phase]} {
# remove phases: raw_remove,wait_p1_low,wait_v6_open,wait_a_little,wait_v6_closed,wait_t_warmup
set removephase [enum_txt [sct]/removephase]
set phaseinit [sct removephaseinit]
sct removephaseinit 0
switch $removephase {
raw_remove {
if {[result dil pmix] == 0} {
dil pmix 20
}
if {[result dil p1] < 0.5 && [result dil g3] > 350} {
hset [sct]/removephase wait_p1_low
}
}
wait_p1_low {
if {$phaseinit} {
if {$phase eq "remove_and_condense"} {
hset [sct] condense
} elseif {$phase eq "remove_and_sorbpump"} {
hset [sct] sorb_pump
} elseif {$phase eq "remove_and_warmup"} {
dil12::set_VtiT [silent 80 hval [sct]/warmup_t]
nv set [silent 3 hvali [sct]/minflow]
nv 2
dil12::msg "wait for P1 < [hvali [sct]/p1low]"
} else {
dil12::set_VtiT 10.0
}
return idle
}
if {[result dil p1] <= [hvali [sct]/p1low]} {
hset [sct]/removephase wait_v6_open
}
}
wait_v6_open {
if {$phaseinit} {
# just to be sure that this phase eventually finishes
dil v6 99.9
}
if {[result dil v6pos] > 99 && [result dil p1] <= [hvali [sct]/p1low]} {
if {$phase ne "remove_and_warmup"} {
dil12::msg "you might now safely heat the VTI to 80 K"
}
hset [sct]/removephase wait_a_little
}
}
wait_a_little {
if {$phaseinit} {
nv set [silent 3 hvali [sct]/minflow]
nv 2
dil v6 90
return idle
}
if {[result dil p1] <= [hvali [sct]/p1low] && [result dil v6pos] <= 90
&& [hvali /nv/flow] < [hvali /nv/autoflow/flowtarget] + 1} {
hset [sct]/removephase wait_v6_closed
}
}
wait_v6_closed {
if {$phaseinit} {
dil v6 0
dil pstill 0
dil pmix 0
dil psorb 0
sorb mode 0
nv 2
return idle
}
if {[result dil v6pos] == 0} {
hset [sct]/removephase wait_t_warmup
}
}
wait_t_warmup {
if {$phaseinit} {
dil12::msg "removing mixture finished, you might switch off the gas handling system"
return idle
}
if {$phase eq "remove_and_warmup"} {
if {[dil12::get_VtiT] < [silent 80 hval [sct]/warmup_t]} {
return idle
}
dil12::msg "you might remove the dil insert and switch off the gas handling system"
}
hset [sct] finished
}
}
}
}
}
return idle
}
proc dil12::msg {txt} {
set old [hvali [sct parent]/instructions]
hupdate [sct parent]/instructions $txt
if {$txt eq ""} {
hdelprop [sct parent]/instructions geterror
} else {
if {$old != $txt} {
clientput $txt
}
hsetprop [sct parent]/instructions geterror $txt
}
}
proc dil12::set_or_clr_msg {flag txt} {
if {$flag} {
msg $txt
} else {
set old [hvali [sct parent]/instructions]
if {$old eq $txt} {
hupdate [sct parent]/instructions ""
hdelprop [sct parent]/instructions geterror
}
}
}
proc dil12::check_removephase {} {
named_enum
hsetprop [sct parent] removephaseinit 1
}
proc dil12::check_onek {} {
named_enum req
sct update [sct target]
switch $req {
normal {
nv set [hvali [sct parent]/circulateflow]
}
fill {
nv set [expr [hvali [sct parent]/circulateflow] + 5]
}
optimize {
hsetprop [sct parent] optimize [clock seconds]
nv set [hvali [sct parent]/circulateflow]
}
}
}
proc dil12::set_VtiT {value} {
if {[catch {
tt set/ramp 0
run tt $value
}]} {
tt set $value
}
}
proc dil12::get_VtiT {} {
return [result tt tm]
}
proc dil12::get_VtiSet {} {
return [result tt set]
}
proc dil12::clearButtons {} {
if {[result dil aux] != 0} {
dil aux 0
}
if {[result dil roots] != 0} {
dil roots 0
}
}
proc dil12::openvalves args {
# open valves given in the args, close all others
# start 3he pump, set all powers to 0
# v7 is not set, but used to test if some other valves are allowed to open
# use v11, v12, v13 instead of v11A, v12A, v13B, as the trap choice is
# taken into account
# if vm_open is present, vm must be open, vb closed
# if vb_open is present, vb must be open, vm closed
# if vm_vb_closed is present, both vm and vb must be closed
array set dil {
v1 0
v2 0
v3 0
v4 0
v5 0
v6 0
v8 0
v9 0
v10 0
v11 0
v12 0
v13 0
v14 0
}
if {[hvali [sct]/hasturbo]} {
set dil(v7) 0
set dil(v2a) 0
set dil(v5a) 0
}
set v_pos ""
foreach {var} $args {
if {[info exists dil($var)]} {
set dil($var) 1
} elseif {$var eq "vb_open"} {
set v_pos 0,3
set v_text "VB must be open, VM must be closed"
} elseif {$var eq "vm_open"} {
set v_pos 3,0
set v_text "VM must be open, VB must be closed"
} elseif {$var eq "vm_vb_closed"} {
set v_pos 0,0
set v_text "both VM and VB must be closed"
} else {
error "$var is not a valid argument for dil12::openvalves"
}
}
if {$v_pos ne "" && [sicsdescriptor vb] eq "MotorValve"} {
if {"[result vm],[result vb]" ne $v_pos} {
error $v_text
}
}
if {[enum_val [sct]/usetrap] == 0} {
set trap A
} else {
set trap B
}
if {[result dil v7] && [result dil v2a] == 0} {
# there might be a pump on V7
if {[result dil v11$trap]} {
# used trap is pumping
if {$dil(v12) > 0 || $dil(v13)} {
error "do not open V12$trap or V13$trap when pumping on trap $trap"
}
}
# do not change V11
unset dil(v11)
# keep V8 and V2 closed (do not complain)
set dil(v8) 0
set dil(v2) 0
} else {
# close valves on unused trap
if {$trap eq "A"} {
set dil(v11B) 0
set dil(v12B) 0
set dil(v13B) 0
} else {
set dil(v11A) 0
set dil(v12A) 0
set dil(v13A) 0
}
}
dil he3 1
dil pstill 0
dil pmix 0
dil psorb 0
foreach var [array names dil] {
set val $dil($var)
switch $var {
v11 {
set var v11$trap
}
v12 {
set var v12$trap
if {$var eq "v12A"} {
if {$val} {
set val 99.9
}
}
}
v13 {
set var v13$trap
}
v6 {
if {$val} {
set val 99.9
}
}
}
dil $var $val
}
}
proc dil12::check_auto {} {
if {[result dil status] ne ""} {
clientput "ERROR: in IGH: [result dil status]"
}
named_enum req
dil12::autostep $req 1
sct update [sct target]
}
proc dil12::startauto {} {
sct print ok
return idle
}
proc dil12::timerauto {{reduce_prio 1e20}} {
if {[result dil p1] > 20} {
# close because p1 is high
dil v14 0
sct closetime 0
# allow next opening soon
sct opentime 0
return unpoll
}
set now [DoubleTime]
if {$now >= [sct closetime]} {
dil v14 0
sct closetime 0
return unpoll
}
if {$now > $reduce_prio} {
[sct controller] poll [sct] 0.5 read dil12::timerauto
return unpoll
}
return idle
}
proc dil12::check_xgas {} {
named_enum req
set enum pump,add,empty,filled
switch -- $req {
pump {
dil v4a 1
set enum pump,add,empty
}
add {
if {[enum_txt [sct]] eq "add"} {
sct print "adding x-gas in progress"
return
}
dil v4a 0
dil closedelay [hvali [sct parent]/xgas_pulse]]
dil v1a 1
# [sct controller] poll [sct] 1 start dil12::xgas_off $close_time
sct print "add x-gas (opened v1a for [hvali [sct parent]/xgas_pulse] sec)"
}
empty {
if {[enum_txt [sct]] eq "pump"} {
sct print "closed valve to x-gas pump"
dil v4a 0
} elseif {[enum_txt [sct]] ne "empty"} {
sct print "set xgas to 'empty' (if this is not true set xgas back to 'filled')"
}
}
filled {
if {[enum_txt [sct]] eq "pump"} {
error "ERROR: use '[sct sicscommand] add' to add x-gas"
} elseif {[enum_txt [sct]] ne "empty"} {
sct print "set xgas to 'filled' (if this is not true set xgas back to 'empty')"
}
}
}
sct enum $enum
enum_update $req
}
proc dil12::read_xgas {} {
set old [enum_txt [sct]]
if {[result dil v4a] eq "1"} {
sct enum pump,add,empty
if {$old ne "pump"} {
enum_update pump
}
} else {
sct enum pump,add,empty,filled
if {[result dil v1a] eq "1"} {
enum_update add
} elseif {$old eq "add"} {
enum_update filled
} elseif {$old eq "pump"} {
enum_update empty
}
}
return idle
}
proc dil12::check_condenseflow {} {
switch [sctval [sct parent]] {
1 - 4 {
# cool or condense
nv set [sct target]
}
}
sct update [sct target]
}
proc dil12::check_circulateflow {} {
if {[sctval [sct parent]] == 5} {
# circulate
if {[hvali [sct parent]/onekstate] == 1} {
nv set [expr [sct target] + 5]
} else {
nv set [sct target]
}
}
sct update [sct target]
}