510 lines
12 KiB
Tcl
510 lines
12 KiB
Tcl
namespace eval sim921 {
|
|
}
|
|
|
|
# for curve reading
|
|
if {![namespace exists lsc]} {
|
|
source drivers/lsc.tcl
|
|
}
|
|
|
|
proc sim921::sendto {chan cmd} {
|
|
sct send "_\nconn $chan,\"_\n\"\n$cmd"
|
|
}
|
|
|
|
proc stdConfig::sim921 {args} {
|
|
variable node
|
|
|
|
controller std lineseparator=|
|
|
|
|
pollperiod 1 1
|
|
|
|
obj SIM921 -none upd
|
|
kids "AC resistance bridge SIM921" {
|
|
foreach {chan nam} $args {
|
|
node $nam rd
|
|
prop read "sim921::poll $chan"
|
|
prop badcnt 0
|
|
prop rngcnt 0
|
|
prop snschk 0
|
|
prop modcnt 0
|
|
prop lastok 0
|
|
prop last_range_change 0
|
|
prop cnvcnt 0
|
|
|
|
kids "$nam" {
|
|
node r upd
|
|
|
|
node auto -int par 1
|
|
prop enum 1
|
|
|
|
node excitation -int out
|
|
prop write "sim921::wrexci $chan"
|
|
prop width 2
|
|
|
|
node range -int out
|
|
prop write "sim921::wrrange $chan"
|
|
prop width 2
|
|
|
|
node rangemin -int par 3
|
|
prop width 2
|
|
|
|
node rangemax -int par 8
|
|
prop width 2
|
|
|
|
node filter out
|
|
prop write "sim921::wrtcon $chan"
|
|
|
|
node status -text upd
|
|
prop width 32
|
|
|
|
node current upd
|
|
|
|
node voltage upd
|
|
|
|
node mode -int out
|
|
prop label "excit.mode"
|
|
prop enum "passive,current,voltage,power"
|
|
prop write "sim921::wrmode $chan"
|
|
|
|
node rraw upd
|
|
|
|
node sensorcheck -int par 0
|
|
prop enum 1
|
|
prop label "sensor check"
|
|
|
|
node curve out -text
|
|
prop chan $chan
|
|
prop model 0
|
|
prop width 32
|
|
prop check lsc::read_curve
|
|
prop write sim921::set_curve
|
|
|
|
hfactory $node/points plain mugger floatvarar 1
|
|
|
|
node reset out -int
|
|
prop enum push
|
|
prop newline 1
|
|
prop label reset
|
|
prop write "sim921::reset $chan"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
proc sim921::rohm {range} {
|
|
if {$range < 0} {
|
|
set range 0
|
|
} elseif {$range > 9} {
|
|
set range 9
|
|
}
|
|
return [lindex {20mOhm 200mOhm 2Ohm 20Ohm 200Ohm 2kOhm 20kOhm 200kOhm 2MOhm 20Mohm} $range]
|
|
}
|
|
|
|
proc sim921::rexci {exci} {
|
|
if {$exci < -1} {
|
|
set exci -1
|
|
} elseif {$exci > 8} {
|
|
set exci 9
|
|
}
|
|
incr exci
|
|
return [lindex {0 3uV 10uV 30uV 100uV 300uV 1mV 3mV 10mV 30mV} $exci]
|
|
}
|
|
|
|
proc sim921::poll {chan} {
|
|
sendto $chan "tval?;rval?;rang?;exci?;ovcr?;iexc?;vexc?;tcon?;agai?;mode?{10}"
|
|
return sim921::upd
|
|
}
|
|
|
|
proc sim921::setstatus {msg} {
|
|
# if {$msg ne "[hvali [sct]/status]"} {
|
|
# if {$msg eq ""} {
|
|
# clientput ok
|
|
# }
|
|
# clientput $msg
|
|
# }
|
|
hupdate [sct]/status $msg
|
|
}
|
|
|
|
proc sim921::upd {} {
|
|
if {[scan [sct result] "%f|%f|%d|%d|%d|%f|%f|%d|%d|%d" t r rng exci status iex vex tcon agai mode] != 10} {
|
|
error "bad result: [sct result]"
|
|
}
|
|
set now [DoubleTime]
|
|
set rref [expr pow(10, $rng-2)]
|
|
if {$exci % 2 == 1} {
|
|
set exref [expr pow(10, ($exci - 11) / 2)]
|
|
} else {
|
|
set exref [expr 3 * pow(10, ($exci - 12) / 2)]
|
|
}
|
|
set oldrng $rng
|
|
set bad 0
|
|
set msg ""
|
|
updateval [sct]/current $iex
|
|
updateval [sct]/voltage $vex
|
|
updateval [sct]/mode $mode
|
|
if {$agai == 1} {
|
|
hupdate [sct]/status "adjust gain"
|
|
return idle
|
|
}
|
|
if {1 & $status} {
|
|
set msg "overload $status"
|
|
set bad 2
|
|
} elseif {2 & $status} {
|
|
set msg "preamp-overload $status"
|
|
set bad 2
|
|
} elseif {4 & $status} {
|
|
set msg "current-overload $status"
|
|
set bad 2
|
|
} elseif {$mode == 2 && (24 & $status)} {
|
|
# set msg "adjusting excit."
|
|
# set bad 1
|
|
} elseif {$mode == 2 && abs(log10(abs($vex) / $exref)) > 0.08} {
|
|
# 20 % error of excit, not detected by bridge
|
|
# set msg "adjusting excit"
|
|
set bad 1
|
|
} elseif {32 & $status} {
|
|
# this is an R underflow, but we normally have a negative T coefficient
|
|
set msg "T-overflow"
|
|
} elseif {64 & $status} {
|
|
set msg "T-underflow"
|
|
}
|
|
if {$mode == 0} {
|
|
set rraw [expr $exref * 18.2 / $iex - 22 * $rref]
|
|
} else {
|
|
set rraw 0
|
|
}
|
|
updateval [sct]/rraw $rraw
|
|
set badcnt [sct badcnt]
|
|
set rngcnt [sct rngcnt]
|
|
set cnvcnt [sct cnvcnt]
|
|
set rmin [hvali [sct]/rangemin]
|
|
set rmax [hvali [sct]/rangemax]
|
|
set vref [expr $iex * $rref]
|
|
set auto [hvali [sct]/auto]
|
|
set sensorcheck [hvali [sct]/sensorcheck]
|
|
if {$mode == 0 && $bad == 0} {
|
|
set snschk [sct snschk]
|
|
if {$rmax < 8} {
|
|
set rlim [expr 20 * pow(10, $rmax -2)]
|
|
} else {
|
|
set rlim 2.0e7
|
|
}
|
|
if {$rraw > 20 * $rref || $rraw > $rlim} {
|
|
# no sensor ?
|
|
set bad 1
|
|
set msg "no sensor"
|
|
setstatus $msg
|
|
if {$snschk < -3} {
|
|
set rm [expr $rmax - 1]
|
|
if {$rng != $rm && $rraw < $rlim} {
|
|
set rm [expr $rmax - 1]
|
|
hset [sct]/range $rm
|
|
clientput "[sct] max range $rm (passive)"
|
|
sct snschk 3
|
|
} else {
|
|
# error message immediately
|
|
updateerror [sct]/r $msg 1
|
|
updateerror [sct] $msg 1
|
|
}
|
|
return idle
|
|
}
|
|
incr snschk -1
|
|
} elseif {$auto} {
|
|
setstatus "sensor check"
|
|
if {$snschk > 10} {
|
|
set cnt 0
|
|
while {$r > $rref * 5 && $cnt < 3} {
|
|
incr rng
|
|
incr cnt
|
|
set rref [expr 10 * $rref]
|
|
}
|
|
while {$r < $rref * 0.2 && $cnt < 3} {
|
|
incr rng -1
|
|
incr cnt
|
|
set rref [expr 0.1 * $rref]
|
|
}
|
|
if {$rng > $rmax} {
|
|
set rng $rmax
|
|
} elseif {$rng < $rmin} {
|
|
set rng $rmin
|
|
}
|
|
if {$rng != $oldrng} {
|
|
clientput "[sct] new range $rng voltage excit."
|
|
} else {
|
|
clientput "[sct] range $rng voltage excit."
|
|
}
|
|
hset [sct]/range $rng
|
|
hset [sct]/mode 2
|
|
sct snschk 0
|
|
return idle
|
|
} else {
|
|
incr snschk
|
|
}
|
|
}
|
|
sct snschk $snschk
|
|
}
|
|
set cnvlim 4
|
|
if {$bad <= 1} {
|
|
if {$cnvcnt < $cnvlim || ($cnvcnt <= $cnvlim && $bad == 0)} {
|
|
incr cnvcnt
|
|
sct cnvcnt $cnvcnt
|
|
}
|
|
}
|
|
if {$cnvcnt > $cnvlim} {
|
|
updateval [sct]/r $r
|
|
if {[string match T-* $msg]} {
|
|
updateerror [sct] $msg 1
|
|
} else {
|
|
sct update $t
|
|
}
|
|
sct lastok $now
|
|
} elseif {$msg eq ""} {
|
|
set msg "stabilize $cnvcnt"
|
|
}
|
|
setstatus $msg
|
|
if {$now > [sct lastok] + 60} {
|
|
updateerror [sct]/r $msg 1
|
|
updateerror [sct] $msg 1
|
|
}
|
|
if {$mode == 2} {
|
|
if {$sensorcheck} {
|
|
set modcnt [sct modcnt]
|
|
if {$bad > 0} {
|
|
if {$modcnt > 20} {
|
|
sct modcnt 0
|
|
sct rngcnt 0
|
|
clientput "[sct] passive excit."
|
|
hset [sct]/mode 0
|
|
return idle
|
|
}
|
|
incr modcnt
|
|
} elseif {$modcnt > 15} {
|
|
incr modcnt -1
|
|
}
|
|
sct modcnt $modcnt
|
|
}
|
|
if {abs($vex) > $vref * 5} {
|
|
incr rngcnt
|
|
} elseif {abs($vex) < $vref * 0.2} {
|
|
incr rngcnt -1
|
|
}
|
|
}
|
|
if {$bad > 1} {
|
|
set rngcnt 0
|
|
if {$badcnt > 5} {
|
|
set bad 3
|
|
}
|
|
incr badcnt
|
|
} elseif {$badcnt > -5} {
|
|
incr badcnt -1
|
|
}
|
|
#if {[sct] eq "/r/tb" && abs(log10(abs($vex) / $exref)) > 0.04} {
|
|
#clientput "[sct] [expr $vref / $exref] [expr $vex / $exref] bad $badcnt rngcnt $rngcnt $r $status"
|
|
#}
|
|
sct badcnt $badcnt
|
|
if {$auto && $bad == 0 && $mode == 2} {
|
|
if {$rngcnt > 5} {
|
|
if {$rng < $rmax} {
|
|
incr rng
|
|
}
|
|
set rngcnt 0
|
|
} elseif {$rngcnt < -5} {
|
|
if {$rng > $rmin} {
|
|
incr rng -1
|
|
}
|
|
set rngcnt 0
|
|
}
|
|
}
|
|
sct rngcnt $rngcnt
|
|
updateval [sct]/filter [format %.1g [expr 0.32 * pow(10, $tcon * 0.5)]]
|
|
if {$exci != [hvali [sct]/excitation]} {
|
|
hsetprop [sct]/excitation label "excit. ([rexci $exci])"
|
|
updateval [sct]/excitation $exci
|
|
sct rngcnt 0
|
|
sct badcnt 0
|
|
sct cnvcnt 0
|
|
}
|
|
if {$bad == 3 && ($mode == 0 || $sensorcheck == 0 || $now < [sct last_range_change] + 20)} {
|
|
clientput "adjust gain on [sct] (rng=[rohm $oldrng] exci=[rexci $exci])"
|
|
sct badcnt 0
|
|
sct cnvcnt 0
|
|
sct send "agai 1;agai?"
|
|
return stdSct::complete
|
|
}
|
|
if {$rng < $rmin} {
|
|
set rng $rmin
|
|
} elseif {$rng > $rmax} {
|
|
set rng $rmax
|
|
}
|
|
if {$rng != $oldrng} {
|
|
clientput "[sct] new range $rng"
|
|
hset [sct]/range $rng
|
|
} elseif {$rng != [hvali [sct]/range]} {
|
|
clientput "[sct] range changed to $rng"
|
|
hsetprop [sct]/range label "range ([rohm $rng])"
|
|
updateval [sct]/range $rng
|
|
sct rngcnt 0
|
|
sct badcnt 0
|
|
sct modcnt 0
|
|
sct cnvcnt 0
|
|
}
|
|
return idle
|
|
}
|
|
|
|
proc sim921::wrrange {chan} {
|
|
sendto $chan "rang [sct target];rang?"
|
|
sct update [sct target]
|
|
hsetprop [sct parent] rngcnt 0
|
|
hsetprop [sct parent] badcnt 0
|
|
hsetprop [sct parent] modcnt 0
|
|
hsetprop [sct parent] cnvcnt 0
|
|
sct label "range ([rohm [sct target]])"
|
|
return stdSct::complete
|
|
}
|
|
|
|
proc sim921::wrexci {chan} {
|
|
sendto $chan "exci [sct target];exon 1;exci?"
|
|
sct update [sct target]
|
|
hsetprop [sct parent] rngcnt 0
|
|
hsetprop [sct parent] badcnt 0
|
|
hsetprop [sct parent] cnvcnt 0
|
|
sct label "excit. ([rexci [sct target]])"
|
|
return stdSct::complete
|
|
}
|
|
|
|
proc sim921::wrmode {chan} {
|
|
sendto $chan "mode [sct target];mode?"
|
|
sct update [sct target]
|
|
hsetprop [sct parent] last_range_change [DoubleTime]
|
|
return stdSct::complete
|
|
}
|
|
|
|
proc sim921::wrtcon {chan} {
|
|
set filt [sct target]
|
|
if {$filt < 0.1} {
|
|
set filt 0.1
|
|
}
|
|
set tcon [expr round(log10($filt) * 2 + 1)]
|
|
sct update [format %.1g [expr 0.32 * pow(10, $tcon * 0.5)]]
|
|
sendto $chan "tcon $tcon;tcon?"
|
|
return stdSct::complete
|
|
}
|
|
|
|
proc sim921::set_curve {} {
|
|
sendto [sct chan] "cini?1;cini?2;cini?3{3}"
|
|
return sim921::set_curve2
|
|
}
|
|
|
|
proc sim921::set_curve2 {} {
|
|
# download always log log format
|
|
sct logT 1
|
|
sct logR 1
|
|
set z 3
|
|
|
|
set points [hvali [sct]/points]
|
|
set crc [lrange [lsc::crc_code $points] 0 15]
|
|
set nam [string toupper [sct target]]
|
|
set short $nam
|
|
if {[string length $short] > 5} {
|
|
if {[string index $short 0] eq "R"} {
|
|
set short [string range $short 1 end]
|
|
}
|
|
if {[string index $short 0] eq "X"} {
|
|
set short [string range $short 1 end]
|
|
}
|
|
}
|
|
set n [expr [llength $points] / 2]
|
|
set ini "$z,$short/$crc,$n"
|
|
if {[sicsdescriptor sim921] eq "notfound"} {
|
|
makeobject sim921 array
|
|
}
|
|
set id [sct parent]
|
|
if {[sim921 exists ${id}_lastno] == 0} {
|
|
sim921 makeitem ${id}_lastno 0
|
|
sim921 makeitem ${id}_lastno2 0
|
|
}
|
|
set lastno [result sim921 ${id}_lastno]
|
|
set lastno2 [result sim921 ${id}_lastno2]
|
|
set no 1
|
|
set emptyno 0
|
|
set changedno 0
|
|
foreach iniold [split [sct result] |] {
|
|
sct curve$no $iniold
|
|
if {$iniold eq $ini} {
|
|
sct print "[sct parent]: activate curve $nam (already loaded as no $no)"
|
|
sct update [sct target]
|
|
if {$no != $lastno} {
|
|
sim921 ${id}_lastno2 $lastno
|
|
sim921 ${id}_lastno $no
|
|
}
|
|
sendto [sct chan] "curv $no;*OPC?"
|
|
return stdSct::complete
|
|
}
|
|
if {[string match "*,$short/*" $iniold]} {
|
|
set changedno $no
|
|
} elseif {[lindex [split $iniold ","] 2] == 0} {
|
|
set emptyno $no
|
|
}
|
|
incr no
|
|
}
|
|
if {$changedno != 0} {
|
|
set no $changedno
|
|
sct print "[sct parent]: curve $nam has changed - start loading"
|
|
} elseif {$emptyno > 0} {
|
|
set no $emptyno
|
|
sct print "[sct parent]: start loading curve $nam to no $no"
|
|
} else {
|
|
set no $lastno
|
|
incr no
|
|
if {$no > 3} {
|
|
set no 1
|
|
}
|
|
if {$no == $lastno2} {
|
|
incr no
|
|
if {$no > 3} {
|
|
set no 1
|
|
}
|
|
}
|
|
sct print "[sct parent]: start loading curve $nam overwriting no $no"
|
|
}
|
|
if {$no != $lastno} {
|
|
sim921 ${id}_lastno2 $lastno
|
|
sim921 ${id}_lastno $no
|
|
}
|
|
sct no $no
|
|
sendto [sct chan] "cini $no,$z,$short/$crc;*OPC?"
|
|
return "sim921::load_pt 0"
|
|
}
|
|
|
|
proc sim921::load_pt {i} {
|
|
set points [hvali [sct]/points]
|
|
if {$i >= [llength $points]} {
|
|
sct print "[sct parent]: loading finished"
|
|
sct update [sct target]
|
|
sendto [sct chan] "curv [sct no];*OPC?"
|
|
return stdSct::complete
|
|
}
|
|
set r [lindex $points $i]
|
|
if {[sct logR]} {
|
|
set r [expr log10($r)]
|
|
}
|
|
incr i
|
|
set t [lindex $points $i]
|
|
if {[sct logR]} {
|
|
set t [expr log10($t)]
|
|
}
|
|
incr i
|
|
sendto [sct chan] "capt [sct no],[format %.7g $r],[format %.7g $t]\n*OPC?"
|
|
return "sim921::load_pt $i"
|
|
}
|
|
|
|
proc sim921::reset {chan} {
|
|
sendto $chan "*RST;*OPC?"
|
|
return sim921::resetupdate
|
|
}
|
|
|
|
proc sim921::resetupdate {} {
|
|
sct udpate 0
|
|
return idle
|
|
}
|
|
|