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