Files
sea/tcl/drivers/cryotelboa.tcl
2023-07-04 11:37:56 +02:00

214 lines
5.4 KiB
Tcl

# version for cryotel at boa (it is to be verified if FOCUS cryotel is different!)
namespace eval cryotelboa {} {
}
proc stdConfig::cryotelboa {} {
# 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 cryotelboa::updatemean
prop readcmd "TC{2}"
prop readfmt "TC ,%f"
kids cryotel {
node cool wr
prop label Cool
prop enum 1
prop read cryotelboa::readcool
prop write cryotelboa::writecool
node control wr
default 1
prop check cryotelboa::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 cryotelboa::updatecontrol
prop writecmd "SET PID=%.2f"
prop readcmd "SET PID{2}"
prop readfmt "SET PID ,%f"
node set wr
prop label Setpoint
prop check cryotelboa::checkset
prop writecmd "SET TTARGET=%.2f"
prop readcmd "SET TTARGET{2}"
prop readfmt "SET TTARGET ,%f"
node setpower wr
prop check cryotelboa::checksetpower
prop writecmd "SET PWOUT=%.2f"
prop readcmd "SET PWOUT{2}"
prop readfmt "SET PWOUT ,%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 {
# on jittery system:
# period was 180, amplitute 3, precision 0.1
node period par 10
prop help "oszillation period / sec"
node amplitude par 0.1
prop help "oszillation amplitude / K (+/-)"
node precision par 0.01
node raw upd
node intdif upd
}
}
}
proc cryotelboa::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]
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]
} elseif {$filtered < [hval [sct]/hold_threshold] + 0.01} {
hset [sct]/setpower [hval [sct]/holdpower]
}
}
}
return idle
}
proc cryotelboa::checkset {} {
if {[hvali [sct parent]/control] == 0} {
sct print "setpoint is effective only in controlled_T mode"
}
}
proc cryotelboa::checksetpower {} {
if {[hvali [sct parent]/control] == 2} {
sct print "setpower is effective only in manual_power mode"
}
if {[sct target] == [hvali [sct]]} {
sct write stdSct::complete
} else {
sct write stdSct::write
}
}
proc cryotelboa::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 cryotelboa::updatecontrol {} {
set value [stdSct::scanresult]
if {$value == 0 && [sctval [sct]] == 1} {
set value 1
}
sct update $value
visibility $value
return idle
}
proc cryotelboa::checkcontrol {} {
visibility [sct target]
if {[sct target] == 1} {
sct write stdSct::completeUpdate
} else {
sct write stdSct::write
}
}
proc cryotelboa::writecool {} {
set flag [expr ! [sct target]]
sct send "SET SSTOP=$flag"
sct update [sct target]
return stdSct::complete
}
proc cryotelboa::readcool {} {
sct send "SET SSTOP{2}"
return cryotelboa::updatecool
}
proc cryotelboa::updatecool {} {
lassign [split [sct result] ,] _ value
sct update [expr $value == 0]
return idle
}