namespace eval cryotel {} { } proc stdConfig::cryotel {} { # controler uses std with send terminator "\r" # 5sec comm.interval, receive terminator "\n" # and multi line replies will be separated by "," controller std "\r" 5 "\n" "," # the {2} in addition to the command defines the number of expected return values prop startcmd "SERIAL{2}" # driver for Sunpower stirling cooler CryoTel # serial interface is set to: # Char Size/Stop Bits: 8/1 Input Speed: 4800 # Flow Ctrl: None Output Speed: 4800 # Parity: None Modem Control: None obj cryo rd 0.5 prop label Temperature prop update cryotel::updatemean prop readcmd "TC{2}" prop readfmt "TC ,%f" kids cryotel { node cool wr prop label Cool prop enum 1 prop write cryotel::writecool prop read cryotel::readcool node control wr default 1 prop check cryotel::checkcontrol prop enum auto_power=1,manual_power=0,controlled_T=2 prop help "recommended mode: auto_power, use coolpower or holdpower depending on T" prop update cryotel::updatecontrol prop writecmd "SET PID=%.2f" prop readcmd "SET PID{2}" prop readfmt "SET PID ,%f" node set wr prop label Setpoint prop check cryotel::checkset prop writecmd "SET TTARGET=%.2f" prop readcmd "SET TTARGET{2}" prop readfmt "SET TTARGET ,%f" node setpower wr prop check cryotel::checksetpower prop writecmd "SET PWOUT=%.2f" prop readcmd "SET PWOUT{2}" prop readfmt "SET PWOUT ,%f" node prop wr prop writecmd "SET KP=%.2f" prop readcmd "SET KP{2}" prop readfmt "SET KP ,%f" node integ wr prop writecmd "SET KI=%.2f" prop readcmd "SET KI{2}" prop readfmt "SET KI ,%f" node coolpower par 240 node holdpower par 120 node cool_threshold par 100 prop help "switch to coolpower above this value" node hold_threshold par 95 prop help "switch to holdpower below this value" node power rd prop label Power prop readcmd "P{2}" prop readfmt "P ,%f" node filter -none kids filter { node period par 180 prop help "oszillation period / sec" node amplitude par 3 prop help "oszillation amplitude / K (+/-)" node precision par 0.1 node raw upd node intdif upd } } } proc cryotel::updatemean {} { set value [stdSct::scanresult] set cnt [silent -1 sct cnt] if {$cnt < 0} { sct update $value updateval [sct]/filter/raw $value sct cnt 0 return idle } incr cnt sct sum [expr [silent 0 sct sum] + $value] if {$cnt < 10} { sct cnt $cnt } else { set raw [expr [sct sum] / $cnt] set filtered [hvali [sct]] sct cnt 0 sct sum 0 updateval [sct]/filter/raw $raw # intdif is accumulating the difference raw - filtered # filtered is corrected by +precision or -precision if abs(intdif) is over lim set per [hval [sct]/filter/period] if {$per == 0} { set filtered $raw } else { set lim [expr 0.5 * [hval [sct]/filter/amplitude]] set prec [hval [sct]/filter/precision] # 20 = 4 * pollperiod * cnt set damp [expr exp(-20 * $prec / $lim / $per)] # 10 = cnt * pollperiod * 2 set intdif [expr ([hvali [sct]/filter/intdif] + ($raw - $filtered) * 10 / $per) * $damp] if {$intdif > $lim} { set filtered [expr (round(($filtered + $intdif - $lim)/ $prec + 1)) * $prec] set intdif [expr $lim - $prec * 2] } elseif {$intdif < -$lim} { set filtered [expr (round(($filtered + $intdif + $lim)/ $prec - 1)) * $prec] set intdif [expr -$lim + $prec * 2] } updateval [sct]/filter/intdif $intdif } sct update [format %.5g $filtered] if {[hval [sct]/control] == 1} { if {$filtered > [hval [sct]/cool_threshold] - 0.01} { hset [sct]/setpower [hval [sct]/coolpower] if {[hval [sct]/cool]} { # switch ON (STOP=0) hset [sct]/cool 0 } } elseif {$filtered < [hval [sct]/hold_threshold] + 0.01} { set hp [hval [sct]/holdpower] if {$hp == 0} { if {[hval [sct]/cool] == 0} { # switch OFF (STOP=1) hset [sct]/cool 1 } } else { if {[hval [sct]/cool]} { # switch ON (STOP=0) hset [sct]/cool 0 } hset [sct]/setpower $hp } } } } return idle } proc cryotel::checkset {} { if {[hvali [sct parent]/control] == 0} { sct print "setpoint is effective only in controlled_T mode" } } proc cryotel::checksetpower {} { if {[hvali [sct parent]/control] == 2} { sct print "setpower is effective only in manual_power mode" } if {[sct target] == [hvali [sct]]} { hsetprop [sct] write stdSct::complete } else { hsetprop [sct] write stdSct::write } } proc cryotel::visibility {mode} { set showlist { 0 setpower 1 {coolpower holdpower cool_threshold hold_threshold} 2 set } foreach {m vars} $showlist { if {$m == $mode} { set visible true } else { set visible false } foreach var $vars { hsetprop [sct parent]/$var visible $visible } } } proc cryotel::updatecontrol {} { set value [stdSct::scanresult] if {$value == 0 && [sctval [sct]] == 1} { set value 1 } sct update $value visibility $value return idle } proc cryotel::checkcontrol {} { visibility [sct target] if {[sct target] == 1} { hsetprop [sct] write stdSct::completeUpdate } else { hsetprop [sct] write stdSct::write } } proc cryotel::writecool {} { set flag [expr ! [sct target]] sct send "SET SSTOP=$flag" sct update [sct target] return stdSct::complete } proc cryotel::readcool {} { sct send "SET SSTOP{2}" return cryotel::updatecool } proc cryotel::updatecool {} { lassign [split [sct result] ,] _ value sct update [expr $value == 0] return idle }