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