IT6800 remote control

In our line of duty (Test Automation) we came about to work with IT6834 (Programmable DC Power Supply). According to it’s Manual http://www.itechate.com/null/IT-DOC/IT6800-UM-EN.pdf , the remote operation commands should have a 26 HEX Bytes code.

After few attempts we got the following:

proc OpenCom {} {
  global fh buff
  set fh [open COM1: RDWR]
  fconfigure $fh -blocking 0 -mode 9600,n,8,1 -translation binary -buffering full -eofchar {} -sysbuffer {4096 4096}
  set buff ""
  fileevent $fh readable GetInst
}

proc GetInst {} {
  global fh buff
  set w [read $fh]
  binary scan $w H* a
  append buff $a
}

proc CloseCom {} {
  global fh
  close $fh
  global fh
}

proc IT6800 {cmd {par ""} } {
  global fh buff
  switch -exact -- $cmd {
    rmt {set cmdH 20}
    out {set cmdH 21}
    vlt {set cmdH 23}
    cur {set cmdH 24}
    get {set cmdH 26}
  }
  switch -exact -- $par {
    on  {set parH 01}
    off {set parH 00}
  } 
  
  if {$cmd=="rmt" || $cmd=="out"} {
    set st [list AA 00 $cmdH $parH 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
  } elseif {$cmd=="vlt"} {
    set mVlt [expr round([expr {1000 * $par}])]
    set mVltH [format %.8X $mVlt]   
    regexp {(\w{2})(\w{2})(\w{2})(\w{2})} $mVltH - b7 b6 b5 b4
    set st [list AA 00 $cmdH $b4 $b5 $b6 $b7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
  } elseif {$cmd=="cur"} {
    set mCur [expr round([expr {1000 * $par}])]
    set mCurH [format %.4X $mCur]   
    regexp {(\w{2})(\w{2})} $mCurH - b5 b4
    set st [list AA 00 $cmdH $b4 $b5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]
  } elseif {$cmd=="get"} {
    set buff ""
    set st [list AA 00 $cmdH 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]    
  }
  ## checkSum calculation  
  set chs [format %.2X [expr {0}]]
  for {set i 0} {$i<[llength $st]} {incr i} {
    set ll [lindex $st $i]
    set chs [format %.2X [expr "0x$chs + 0x$ll"]]
  }
  if {[string length $chs]>2} {
    set chs [string range $chs 1 end]
  }
  lappend st $chs
  
  set st [join $st ""]
  set st1 [binary format H* $st]
  puts -nonewline $fh $st1 ; flush $fh
  set ret 0
  
  if {$cmd=="get"} {
     delay 1
     set adr [string range $buff 2 3]
     set cmd [string range $buff 4 5]
     
     set b4  [string range $buff 6 7]
     set b5  [string range $buff 8 9]
     set prH [set b5][set b4]
     set prD1 [expr {[scan $prH %x]/1000.0}]     
     puts "Present Output Current:$prD1"
     
     set b6  [string range $buff 10 11]
     set b7  [string range $buff 12 13]
     set b8  [string range $buff 14 15]
     set b9  [string range $buff 16 17]
     set prH [set b9][set b8][set b7][set b6]
     set prD2 [expr {[scan $prH %x]/1000.0}]     
     puts "Present Output Voltage:$prD2"
    
     set b11  [string range $buff 20 21]
     set b12  [string range $buff 22 23]
     set prH [set b12][set b11]
     set prD3 [expr {[scan $prH %x]/1000.0}]     
     puts "Current:$prD3"
    
     set b17  [string range $buff 32 33]
     set b18  [string range $buff 34 35]
     set b19  [string range $buff 36 37]
     set b20  [string range $buff 38 39]
     set prH [set b20][set b19][set b18][set b17]
     set prD4 [expr {[scan $prH %x]/1000.0}]     
     puts "Voltage:$prD4"
     set ret [set prD1]_[set prD2]_[set prD3]_[set prD4]
  }
  return $ret
}

proc delay {TimeSec} {
   set x 0
   after [expr $TimeSec * 1000] {set x 1}
   vwait x
}
OpenCom
IT6800 rmt on
IT6800 out on
IT6800 cur 1
IT6800 vlt 48

IT6800 get
CloseCom

Of course, the program is not final but gives a general idea.

Ilya Ginzburg, RAD Data Communications Ltd. <http://www.rad.com >


CJL suggests that the checksum code could be simplified to the following:

set cs 0
foreach byte $st {
        set cs [expr { ($cs + $byte) % 0x100 }]
}
lappend st [format %02x $cs]

The ever useful foreach replaces the for/lindex combo. Staying in the integer realm until the last moment avoids lots of string->int->string->int converstions in the original.