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

254 lines
6.5 KiB
Tcl

namespace eval bronkgen {} {
}
proc stdConfig::bronkgen {label scale {adr 128} {readonly 0} {ramp 0} {setoffset 0} {ctrlmode 0} {invalidvalue none}} {
# driver for Bronkhorst Flow or Pressure regulator (i.e.P-602CV-21KA-AAD)
# serial interface is set to:
# Char Size/Stop Bits: 8/1 Input Speed: 38400
# Flow Ctrl: None Output Speed: 38400
# Parity: None Modem Control: None
# syntax (chaining not mentioned):
# read command: :06Ad04CopyPrTp
# write command: :LnAd01PrTpData
# where:
# Ln: number of bytes (hex digits pairs) following
# Ad: node address (starting from 3)
# Copy: values just to be copied by the reply (first and third digit < 8)
# recommended practice: Use PrTp for Copy
# Pr: Process number (<80)
# Tp: Type + parameter number. Type: 00 byte, 20 int, 40 long/float, 60 string
# for strings either 00 (for nul terminated) or the max. number of chars
# has to be appended to the type
# Data: length depending on type.
# the interface returns readings on a scale where 32000 is 100%
set adr [format %02x $adr]
controller std "\r\n"
prop read bronkgen::read
prop write bronkgen::write
prop update bronkgen::update
prop startcmd :07${adr}047163716300
prop convert_idn bronkgen::result2string
clientput "BRONK $label $scale $adr"
obj BRONKGEN rd
prop label $label
prop par "1 0 $scale"
prop @adr $adr
if {$invalidvalue ne "none"} {
prop invalidvalue $invalidvalue
}
kids "$label" {
if {$readonly == 0} {
node set wr
prop label setpoint
prop par "1 1 $scale"
prop setoffset $setoffset
if {$ramp != 0} {
prop write bronkgen::write_with_ramp
prop update bronkgen::update_set
node reg upd
node ramptime rd
prop par "1 2 i 0.1"
node ramp par $ramp
node rampstd par $ramp
}
if {$ctrlmode} {
node ctrlmode wr
prop label "control mode"
prop enum manual=4,loop=11
prop par "1 4 b"
node output wr
prop par "114 1 l 0.002"
}
}
node fluid rd -text
prop par "1 17 s"
node par out -text
default "113 6 s"
prop write bronkgen::setpar /x
node x wr -text
prop par "113 6 s"
prop width 32
}
}
proc bronkgen::result2string {} {
set string ""
foreach {h l} [split [string range [sct result] 13 end-2] ""] {
append string [format %c [scan $h$l %2x]]
}
return $string
}
proc bronkgen::update {{as_function 0}} {
lassign [sct par] process par type scale
if {$scale eq ""} {
set scale 1
}
set value 0
switch -- $type {
b {
set res [scan [string range [sct result] 11 12] %2x value]
}
i {
set res [scan [string range [sct result] 11 14] %4x value]
set value [expr $value * $scale]
}
l {
set res [scan [string range [sct result] 11 18] %8x value]
set value [expr $value * $scale]
}
s {
set value ""
foreach {h l} [split [string range [sct result] 13 end-2] ""] {
append value [format %c [scan $h$l %2x]]
}
set res 1
}
default {
set res [scan [string range [sct result] 11 14] %4x value]
set value [format %.4g [expr $value * $type / 32000.]]
}
}
if {$res != 1} {
error "bad result format: '[sct result]'"
} elseif {$as_function} {
return $value
}
if {$value != [silent -0.123e-45 sct invalidvalue]} {
sct update $value
}
return idle
}
proc bronkgen::read {} {
lassign [sct par] process par type
switch -- $type {
b {
set arg [format %2.2X%2.2X $process $par]
set arg $arg$arg
}
s {
set arg [format %2.2X%2.2X $process [expr $par + 0x60]]
set arg $arg${arg}00
}
l {
set arg [format %2.2X%2.2X $process [expr $par + 0x40]]
set arg $arg${arg}00
}
default { # i and scaled
set arg [format %2.2X%2.2X $process [expr $par + 0x20]]
set arg $arg$arg
}
}
set len [format %2.2X [expr 2 + [string length $arg] / 2]]
sct send :$len[sct @adr]04$arg
return update
}
proc bronkgen::write {{logtext ""}} {
# clientput "write [sct] [sct target] $logtext"
lassign [sct par] process par type scale
if {$scale eq ""} {
set scale 1
}
switch -- $type {
b {
set arg [format %2.2X%2.2X%2.2X $process $par [sct target]]
}
s {
set arg [format %2.2X%2.2X $process [expr $par + 0x60]]
set arg $arg00
foreach char [split [sct target] ""] {
lappend arg [format %2.2X [scan $char %c]]
}
lappend "00"
}
i {
set arg [format %2.2X%2.2X%4.4X $process [expr $par + 0x20] [expr round([sct target]/$scale)]]
}
l {
set arg [format %2.2X%2.2X%8.8X $process [expr $par + 0x40] [expr round([sct target]/$scale)]]
}
default {
set val [expr round(([sct target] + [silent 0 sct setoffset]) * 32000. / $type)]
if {$val > 32000} {
if {$val < 32320} {
set val 32000
} else {
error "[sct]: [sct target] must be <= $type"
}
} elseif {$val < 0} {
error "[sct]: [sct target] must be >= 0"
}
set arg [format %2.2X%2.2X%4.4X $process [expr $par + 0x20] $val]
}
}
set len [format %2.2X [expr 2 + [string length $arg] / 2]]
sct send :$len[sct @adr]01$arg
return bronkgen::acknowledge
}
proc bronkgen::acknowledge {} {
if {[string range [sct result] 7 8] ne "00"} {
error "[sct]: bad status '[sct result]'"
}
return read
}
proc bronkgen::write_with_ramp {} {
lassign [sct par] process par scale
set rpath [sct objectPath]/ramp
set ramp [hval $rpath]
set ramptime [format %.1f [expr min(3200.0, max(10., $scale * 60.0 / max($ramp, 0.1)))]]
if {$ramptime != [silent -1 hval ${rpath}time]} {
sct send :06[sct @adr]010122[format %4.4X [expr round(10*$ramptime)]]
hupdate $rpath [hval ${rpath}std]
return "bronkgen::write {with ramp $ramp}"
}
hupdate $rpath [hval ${rpath}std]
return [bronkgen::write]
}
proc bronkgen::setpar {relpath} {
hsetprop [sct objectPath]$relpath par [sct target]
sct update [sct target]
[sct controller] queue [sct objectPath]$relpath read read
return stdSct::complete
}
proc bronkgen::update_set {} {
set req [silent none sct requested]
if {$req ne "none"} {
sct update $req
return idle
}
set value [expr max(0,[bronkgen::update 1] - [sct setoffset])]
if {$value == [silent -9999 sct old]} {
sct update $value
}
sct old $value
updateval [sct parent]/reg $value
return idle
}