Files
sea/tcl/drivers/auto370.tcl
2022-08-18 15:04:28 +02:00

297 lines
7.0 KiB
Tcl

# auto range for lsc 370
namespace eval auto370 {
}
proc stdConfig::auto370 {lsc370 {getcmd 0}} {
variable path
variable name
controller syncedprot 10
pollperiod 1 1
obj auto370 wr
prop enum 1
prop label "auto heater on"
prop read auto370::poll
prop write stdSct::completeUpdate
prop lsc370 /$lsc370/set
prop lastdown 0
prop lastup 0
prop resist 0
prop @rangetarget 0
prop getcmd $getcmd
prop heat 1
kids "$lsc370 autorange settings" {
node mode -int out
prop enum 0,1
prop check auto370::checkmode
prop write stdSct::complete
default 0
node heaterrange -int out
prop check auto370::checkrange
prop write stdSct::complete
prop enum 1,2,3,4,5,6,7,8
prop label heaterrange
node minrange par 3
prop enum 1,2,3,4,5,6,7,8
prop label minrange
node maxrange par 6
prop enum 1,2,3,4,5,6,7,8
prop label maxrange
node switchup par 90
node switchupdelay par 60
prop label "switch up delay"
prop help "min. time to be above the threshold before switching up"
node switchdown par 10
node switchdowndelay par 300
prop label "switch down delay"
prop help "min. time to be below the threshold before switching down"
node heater upd
node autoprop par 0
prop enum 1
prop newline 1
node calcpow upd
node ttable -text par {0.01 0.02 0.064 0.2}
prop width 40
prop label T power table
prop help "T for 1uW, 10uW, 100uW, 1mW ..."
prop newline 1
node prop par 5
prop label "max. prop"
node propmin par 0.2
prop label "min. prop"
}
}
proc auto370::neededPower {tem table} {
set pow 1.0e-7
set last [expr [lindex $table 0] * sqrt(0.1)]
foreach t $table {
if {$tem < $t} {
if {$last == 0} {
return $pow
}
return [expr $pow * pow($tem / $last, 1.0 / log10($t/$last))]
}
set pow [expr $pow * 10]
set last $t
}
return [expr $pow * pow($tem / $last, 2)]
}
proc auto370::poll {} {
catch {hdelprop [sct] geterror}
set now [clock seconds]
set p [sct lsc370]
set resist [sctval $p/resist]
set pow [sctval $p/maxpower]
if {$pow <= 0} {
return idle
}
set htrrng [expr round(log10($pow / $resist) + 10)]
set htr [silent 0 hgetpropval $p/power htr]
updateval [sct]/heater $htr
set minr [sctval [sct]/minrange]
set minp [expr $resist * pow(10, $minr - 10)]
set maxr [sctval [sct]/maxrange]
set maxp [expr $resist * pow(10, $maxr - 10)]
set maxpowerlim [sctval $p/maxpowerlim]
set maxl [expr round(log10($maxpowerlim / $resist) + 10)]
set w1 [expr $resist * 0.01]
set w2 [expr $resist * 0.1]
set w3 $resist
set plist [format {%gnW=1 %guW=2 %guW=3 %guW=4 %gmW=5 %gmW=6 %gmW=7 %gW=8} $w3 $w1 $w2 $w3 $w1 $w2 $w3 $w1]
set plist [lrange $plist 0 [expr $maxl-1]]
set htxt [join [lrange $plist [expr $minr-1] [expr $maxr-1]] ,]
if {$htxt ne [hgetpropval [sct]/heaterrange enum]} {
hsetprop [sct]/minrange enum [join $plist ,]
hsetprop [sct]/maxrange enum [join $plist ,]
hsetprop [sct]/heaterrange enum $htxt
}
set soll [hvali $p/reg]
set psoll [neededPower $soll [hvali [sct]/ttable]]
hupdate [sct]/calcpow $psoll
if {[hvali [sct]/autoprop]} {
set prop [hvali $p/prop]
set f [expr sqrt($psoll / $pow)]
if {$f > 1} {
set f 1
}
set pnew [expr [hvali [sct]/prop] * $f]
set propmin [hvali [sct]/propmin]
if {$pnew < $propmin} {
set pnew $propmin
}
if {$prop != $pnew} {
hset $p/prop $pnew
}
hsetprop $p/prop priv internal
} else {
hsetprop $p/prop priv user
}
set switchup [hvali [sct]/switchup]
if {$switchup > 100} {
set switchup 100
hupdate [sct]/switchup $switchup
} elseif {$switchup < 10} {
set switchup 10
hupdate [sct]/switchup $switchup
}
set switchdown [hvali [sct]/switchdown]
if {$switchdown > $switchup * 0.3} {
set switchdown [expr $switchup * 0.3]
hupdate [sct]/switchdown $switchdown
} elseif {$switchdown < 0.1} {
set switchdown 0.1
hupdate [sct]/switchdown $switchdown
}
set rangetarget [sct @rangetarget]
if {$rangetarget == 0} {
updateval [sct]/heaterrange $htrrng
} else {
sct @rangetarget 0
if {$rangetarget != $htrrng} {
set newpow [expr $pow * pow(10, $rangetarget - $htrrng)]
sctsync {
hset $p/maxpower $newpow
}
return "auto370::complete $pow $newpow [hvali $p/power]"
}
}
if {$htr > $switchup * 0.3 && $htrrng < $maxr} {
sct lastdown $now
if {$htr >= $switchup} {
set newpow [expr $pow * 10]
if {$newpow > $maxp * 1.1} {
set newpow $maxp
}
if {$now > [sct lastup] + [hvali [sct]/switchupdelay]} {
if {[sctval [sct]] == 0} {
return idle
}
sct lastup $now
sctsync {
hset $p/maxpower $newpow
}
return "auto370::complete $pow $newpow [hvali $p/power]"
}
} else {
sct lastup $now
}
set r [expr $now - [sct lastup]]
if {[sctval [sct]] == 0} {
set r 0
}
if {$r < 5} {
hsetprop [sct]/switchupdelay label "switch up delay"
} else {
hsetprop [sct]/switchupdelay label "switch up d.($r)"
}
}
if {$htr < $switchdown / 0.3 && $htrrng > $minr} {
sct lastup $now
if {$htr <= $switchdown} {
set newpow [expr $pow * 0.1]
if {$newpow < $minp * 0.9} {
set newpow $minp
}
if {$htr == 0} {
sct lastdown $now
}
if {$now > [sct lastdown] + [hvali [sct]/switchdowndelay]} {
if {[sctval [sct]] == 0} {
return idle
}
sct lastdown $now
sctsync {
hset $p/maxpower $newpow
}
return "auto370::complete $pow $newpow [hvali $p/power]"
}
} else {
sct lastdown $now
}
set r [expr $now - [sct lastdown]]
if {[sctval [sct]] == 0} {
set r 0
}
if {$r < 5} {
hsetprop [sct]/switchdowndelay label "switch down delay"
} else {
hsetprop [sct]/switchdowndelay label "switch down d.($r)"
}
}
return idle
}
proc auto370::complete {oldpow newpow manpow} {
set p [sct lsc370]
sctsync {
hset $p/manualpower $manpow
}
return "auto370::complete2 $oldpow"
}
proc auto370::complete2 {oldpow} {
set p [sct lsc370]
set pow [sctval $p/maxpower]
sctsync {
hset $p/mode 1
}
# return stdSct::complete
return auto370::finish
}
proc auto370::finish {} {
return idle
}
proc auto370::checkrange {} {
sct @rangetarget [sct target]
sct update [sct target]
}
proc auto370::checkmode {} {
set code [silent {} sct mode[sct target]]
if {$code eq ""} {
error "illegal mode [sct target]"
}
sct update [sct target]
set enum [split [hgetpropval [sct] enum] ,]
clientput "set parameters for [lindex $enum [sct target]]"
eval $code
}
proc auto370::mode {nr mode code} {
set p $::stdConfig::path
hsetprop $p/mode mode$nr $code
set enum [split [hgetpropval $p/mode enum] ,]
if {$nr > 10} {
error "nr $nr too big"
}
while {[llength $enum] <= $nr} {
lappend enum $nr
}
lset enum $nr $mode
hsetprop $p/mode enum [join $enum ,]
}