Re: RCX using python serial help



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)
.



Relevant Pages

  • Re: insert chars into string
    ... no. Strings are immutable in Python. ... def insert(original, new, pos): ...
    (comp.lang.python)
  • text adventure question
    ... I am working on a text adventure game for python to get back into ... def character_sheet: ... global reputation ... print "Please choose another command. ...
    (comp.lang.python)
  • Re: noob question: "TypeError" wrong number of args
    ... or it's newer syntactic-sugar-version would become somewhat more ... Python source code and outputs the same source code with only one change: ... insert the string 'self" as the first parameter of every "def ... Python code, which is unavoidable for such a syntactic change. ...
    (comp.lang.python)
  • Re: Python 3K or Python 2.9?
    ... function/method argument that might as well be hidden in the compiler ... You could add some syntax to Python such that '.x' was equivalent to ... def factory: ... C.method = foo ...
    (comp.lang.python)
  • [PATCH] tracecmd: Add initial python tracecmd API
    ... Subject: tracecmd: Add initial python tracecmd API ... Add an object oriented python API in a new tracecmd.py module. ... -print "Cycling through the events for each CPU" ... def comm: ...
    (Linux-Kernel)