Monday 4 February 2013

Controlling Lego Mindstorms with Linux

In another 200 years I might have built the terminator

Last Christmas, I was the very lucky recipient of the incredibly awesome Lego Mindstorms kit. Here's a picture of all that awesome:


Yes indeed - computer controlled Lego. If I'd got this 20 years ago I wouldn't have seen daylight until I had to leave home.

Now the way this works is that there is a microprocessor controller brick that can have up to 3 motors and 4 sensors connected to it. In theory you build your robot (or whatever) using the included Lego (and any other bits you have lying around), design your program for it using the LabView based language included, download it to the control brick and away you go.

Now this is all well and good and gives you quite a bit of control. Here's a case in point:


However, though I appreciate the benefits of Labview, I'm more of a C++ kind of guy. I also have a long term plan of using another of my presents this year, a Raspberry Pi, as the main controller and maybe throw in an Arduino as well for a bit more flexibility.

This will therefore necessitate an API interface to the controller. A quick bit of googlage pointed me at a promising looking Python based version: NXT-python. This not only allowed all the file access and compilation options I could want, but also (and this was the important bit) had a direct, real time control option. What was even better was that in my Mint install had in the software manager (search for 'nxt'). A couple of clicks later and it was ready to try out. Awesome.

Or not. The version in the repo is a bit behind the main release (V.2.2.1-2 instead of V2.2.2) and contains a rather critical Ultrasonic sensor bug. However, I was still able to plug the brick in via USB (after building the basic tracked vehicle in the instructions), turn it on, and use the following code to get it move rather drunkenly around:

 
import nxt.locator
from nxt.motor import *

def spin_around(b):
    m_left = Motor(b, PORT_B)
    m_left.turn(400, 360)
    m_right = Motor(b, PORT_C)
    m_right.turn(-400, 360)

b = nxt.locator.find_one_brick()
spin_around(b)


Obviously, this requires you to plug motors into ports B and C :)

This code was shamelessly nicked from the examples that came with the nxt-python install and can (probably) be found here:

/usr/share/doc/python-nxt/examples/


These contain code for using the speaker and reading the sensors, the latter of which required a bit of hacking to fix for the ultrasonic one. If you run it as is, you get the error:

    sensor = Ultrasonic( BRICK, inPort)
  File "nxt-my\nxt\sensor\generic.py", line 95, in __init__
    super(Ultrasonic, self).__init__(brick, port, check_compatible)
  File "nxt-my\nxt\sensor\digital.py", line 73, in __init__
    sensor = self.get_sensor_info()
  File "nxt-my\nxt\sensor\digital.py", line 156, in get_sensor_info
    version = self.read_value('version')[0].split('\0')[0]
  File "nxt-my\nxt\sensor\digital.py", line 143, in read_value
    raise I2CError, "read_value timeout"

As this it's basically saying, there is a timeout issue when reading the ultrasonic sensor. Again, google came to my rescue and pointed me Here. After doing the correction suggested (i.e. increasing the loop count up to 30 on line 84), all was right with the world.

So I now have a computer controlled robot (sort of) that can be told what to do through python. This is certainly a start but if I'm going to control it with the kind of code I have in mind, I'm going to need something a bit more heavy duty. Next job: running python from C++.

No comments:

Post a Comment