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 }