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