RCX using python serial help

MRAB python at mrabarnett.plus.com
Tue Dec 7 15:42:11 EST 2010


On 06/12/2010 15:37, Astan Chee wrote:
> Hi,
> I've got a lego mindstorm RCX 1.0 (but firmware is 2.0) that uses one of
> those old serial IR towers to control the microcontroller. I've had a
> look around at python's serial documentation as well as the RCX's
> documentation and I'm trying to write something to control the RCX
> directly using python. Several examples from of doing this in python
> include using lnp (i think) and that doesn't quite run well in windows.
> I've had a look at the C++ code and some protocol documentation here:
> http://www.generation5.org/content/2001/rob08.asp and converted it to
> python. I've attached it at the end of the email. So now I've figured
> out how to check for the battery level and it seems to work (I've tested
> it on my RCX) but I'm confused with the other documentation (e.g.
> http://graphics.stanford.edu/~kekoa/rcx/ ) about how to do this in
> python or what this all means. I was wondering if anyone can help me
> complete these? or maybe help me do it step-by-step?
> Thanks for any help.
> Below is the python code I've been working on:
> import time
> import serial
> import struct
> import binascii
> def tcbin(x, y=8):
> """
>      This function returns the padded, two's complement representation
> of x, in y-bits.
>      It is conventional for y to be 8, 16, 32 or 64, though y can have
> any non-zero positive value.
> """
>      if x >= 0:
>          binstr = bin(x)
>          # pad with leading zeros
>          while len(binstr) < y + 2:
>              binstr = "0b0" + binstr[2:]
>          return binstr
>      return bin((2**y) + x) # x is negative
> def bitcompliment(hex_code):
>      return hex(int(tcbin(~(ord(hex_code))),2))
>
> def processOutput(raw_data,output):
>      outputStatus = True
>      pos = 0
>      for i in range(3):
>          if raw_data[i] != output[i]:
>              outputStatus = False
>          pos+=1
>      if outputStatus:
>          print "output OK"
>      else:
>          print "problem with output"
>      outputCompliment = True
>      while outputCompliment:
>          if hex(ord(output[pos])) == bitcompliment(output[pos+1]):
>              print "output compliment OK"
>          else:
>              print "problem with output compliment"
>          pos+=2
>          if hex(ord(output[pos])) == '0x55' and hex(ord(output[pos+1]))
> == '0xff' and hex(ord(output[pos+2])) == '0x0':
>              pos+=3
>              outputCompliment = False
>      if hex(ord(output[pos])) == '0xcf' or hex(ord(output[pos])) == '0xc7':
>          #battery checker
>          pos+=2
>          if hex(ord(output[pos])) == bitcompliment(output[pos+1]) and
> hex(ord(output[pos+2])) == bitcompliment(output[pos+3]):
>              s = ((ord(output[pos+2]) * 256) + ord(output[pos])) / 1000.0
>              print "Battery is at " + str(s) + " Volts"
>      else:
>          for i in range(len(output[pos:]),len(output),2):
>              print hex(ord(output[i]))
>              if i+1 < len(output):
>                  if hex(ord(output[i])) == bitcompliment(output[i+1]):
>                      print "message OK. contents: " + hex(ord(output[i]))
>
> # configure the serial connections (the parameters differs on the device
> you are connecting to)
> ser = serial.Serial(
>   port='COM1',
>   baudrate=2400,
>   parity=serial.PARITY_ODD,
>   stopbits=serial.STOPBITS_ONE,
>   bytesize=serial.EIGHTBITS
> )
> raw_data = '\x55\xff\x00\x38\xc7\x38\xc7'
> result = ser.write(raw_data)
> out = ''
> time.sleep(1) #pause for a second
> while ser.inWaiting() > 0:
>      out+=ser.read(1)
> processOutput(raw_data,out)
>
Here's my version of your code:

import time
import serial
import struct
import binascii

# not needed!
def tcbin(x, y=8):
     """
     This function returns the padded, two's complement representation 
of x, in y-bits.
     It is conventional for y to be 8, 16, 32 or 64, though y can have 
any non-zero positive value.
     """
     return "0b" + bin((2 ** y) + x)[-y : ]

def byte_complement(hex_code):
     return (~ord(hex_code)) & 0xff

def process_output(raw_data, output):
     output_status = raw_data[ : 3] == output[ : 3]
     if output_status:
         print "output OK"
     else:
         print "problem with output"
     pos = 3
     output_complement = True
     while output_complement:
         if ord(output[pos]) == byte_complement(output[pos + 1]):
             print "output complement OK"
         else:
             print "problem with output complement"
         pos += 2
         if ord(output[pos]) == 0x55 and ord(output[pos + 1]) == 0xff 
and ord(output[pos + 2]) == 0x00:
             pos += 3
             output_complement = False
     if ord(output[pos]) == 0xcf or ord(output[pos]) == 0xc7:
         # battery checker
         pos += 2
         if ord(output[pos]) == byte_complement(output[pos + 1]) and 
ord(output[pos + 2]) == byte_complement(output[pos + 3]):
             s = ((ord(output[pos + 2]) * 256) + ord(output[pos])) / 1000.0
             print "Battery is at %s Volts" % s
     else:
         for i in range(len(output[pos : ]), len(output), 2):
             print hex(ord(output[i]))
             if i + 1 < len(output):
                 if ord(output[i]) == byte_complement(output[i + 1]):
                     print "message OK. contents: %s" % hex(ord(output[i]))

# configure the serial connections (the parameters differs on the device 
you are connecting to)
ser = serial.Serial(
  port='COM1',
  baudrate=2400,
  parity=serial.PARITY_ODD,
  stopbits=serial.STOPBITS_ONE,
  bytesize=serial.EIGHTBITS
)
raw_data = '\x55\xff\x00\x38\xc7\x38\xc7'
result = ser.write(raw_data)
out = ''
time.sleep(1) # pause for a second
while ser.inWaiting() > 0:
     out += ser.read(1)
process_output(raw_data, out)



More information about the Python-list mailing list