179 lines
4.0 KiB
Tcl
179 lines
4.0 KiB
Tcl
# software pi loop
|
|
namespace eval loop {
|
|
}
|
|
|
|
if {![namespace exists trun]} {
|
|
source drivers/trun.tcl
|
|
}
|
|
|
|
proc stdConfig::loop args {
|
|
variable name
|
|
variable path
|
|
variable node
|
|
|
|
scanargs $args var -invar -outvar -outmin 0 -outmax 1 -prop 1 -int 1 -maxdelta 60 -precision 0.001 -mindelta 0
|
|
|
|
variable hostport none
|
|
controller syncedprot
|
|
|
|
obj loop -drive out
|
|
prop lastinput 0
|
|
kids "$name control parameters" {
|
|
node mode -int out
|
|
default 0
|
|
prop enum off,on,manual
|
|
prop check loop::checkmode
|
|
prop write stdSct::completeUpdate
|
|
|
|
node output out
|
|
default $outmin
|
|
prop check loop::checkoutput
|
|
prop write stdSct::completeUpdate
|
|
|
|
node invar -text out
|
|
default 0
|
|
prop check loop::setinvar
|
|
prop write stdSct::completeUpdate
|
|
prop visible false
|
|
|
|
node outvar -text par $outvar
|
|
prop visible false
|
|
|
|
node pollinput rd
|
|
prop read stdSct::complete
|
|
|
|
node prop par $prop
|
|
prop help "the bigger, the less sensible"
|
|
|
|
node int par $int
|
|
node outmin par $outmin
|
|
node outmax par $outmax
|
|
|
|
node precision par $precision
|
|
prop label "output precision"
|
|
|
|
node maxdelta par $maxdelta
|
|
|
|
node mindelta par $mindelta
|
|
}
|
|
stdConfig::tdrive "$name control parameters" self loop::settarget
|
|
# hset $path/setcmd loop::settarget
|
|
hset $path/invar $invar
|
|
}
|
|
|
|
proc loop::checkmode {} {
|
|
if {[sct target] == 0} {
|
|
set output [hvali [sct parent]/outmin]
|
|
hset [sct parent]/output $output
|
|
}
|
|
}
|
|
|
|
proc loop::updateinput {value} {
|
|
set prop [hvali [sct]/prop]
|
|
set int [hvali [sct]/int]
|
|
set outmin [hvali [sct]/outmin]
|
|
set outmax [hvali [sct]/outmax]
|
|
set span [expr double($outmax - $outmin)]
|
|
set maxdelta [hvali [sct]/maxdelta]
|
|
set mindelta [hvali [sct]/mindelta]
|
|
set precision [hvali [sct]/precision]
|
|
set input $value
|
|
|
|
set effoutput [eval "result [hvali [sct]/outvar]"]
|
|
if {[hvali [sct]/mode] == 2} {
|
|
return idle
|
|
}
|
|
if {[hvali [sct]/mode] == 0} {
|
|
# to be put into write script of ../mode
|
|
if {$effoutput > $outmin} {
|
|
eval "[hvali [sct]/outvar] $outmin"
|
|
}
|
|
return idle
|
|
}
|
|
set output [hvali [sct]/output]
|
|
if {abs($effoutput - $output) > $precision} {
|
|
clientput "$output -> $effoutput"
|
|
set output $effoutput
|
|
}
|
|
set now [clock seconds]
|
|
if {[sct lastinput] == 0} {
|
|
set deltat 1
|
|
} else {
|
|
set deltat [expr $now - [sct lastinput]]
|
|
if {$deltat < $mindelta} {
|
|
return idle
|
|
}
|
|
if {$deltat > $maxdelta} {
|
|
set deltat $maxdelta
|
|
}
|
|
}
|
|
sct lastinput $now
|
|
set lastdif [silent 0 sct lastdif]
|
|
|
|
set dif [expr double([hvali [sct]/set] - $input)]
|
|
set output [expr $output + $span/$prop \
|
|
* (($dif - $lastdif) * $deltat + $dif / $int)]
|
|
sct lastdif $dif
|
|
|
|
if {$outmax > $outmin} {
|
|
if {$output > $outmax} {
|
|
set output $outmax
|
|
} elseif {$output < $outmin} {
|
|
set output $outmin
|
|
}
|
|
} else {
|
|
if {$output < $outmax} {
|
|
set output $outmax
|
|
} elseif {$output > $outmin} {
|
|
set output $outmin
|
|
}
|
|
}
|
|
hset [sct]/output $output
|
|
return idle
|
|
}
|
|
|
|
# updatescript on the remote input node
|
|
proc loop::updateinput1 {value} {
|
|
set loopobj [sct loopobj]
|
|
if {[silent 0 sct geterror] eq "0"} {
|
|
updateval $loopobj $value
|
|
}
|
|
return
|
|
}
|
|
|
|
proc loop::setinvar {} {
|
|
if {[silent none hgetprop [sct target] sicscommand] eq "none"} {
|
|
set t [sct parent]/pollinput
|
|
sct target [sct parent]/pollinput
|
|
# clientput "Tp $t"
|
|
} else {
|
|
set t [sct target]
|
|
# clientput "Tt $t"
|
|
}
|
|
[sct controllerName] updatescript [sct parent] loop::updateinput
|
|
[sct controllerName] updatescript $t loop::updateinput1
|
|
hsetprop $t loopobj [sct parent]
|
|
hsetprop $t read loop::pollinput
|
|
return
|
|
}
|
|
|
|
proc loop::pollinput {} {
|
|
catch {sct update [result [hval [sct parent]/invar]]}
|
|
return idle
|
|
}
|
|
|
|
proc loop::settarget {target} {
|
|
updateval [sct]/mode 1
|
|
sct print "[sct]/set = $target"
|
|
return idle
|
|
}
|
|
|
|
proc loop::updtarget {} {
|
|
sct print "[sct]/set = [sct target]"
|
|
return idle
|
|
}
|
|
|
|
proc loop::checkoutput {} {
|
|
eval "[hvali [sct parent]/outvar] [sct target]"
|
|
}
|