This weekend, my Raspberry Pi Robot tank took its first steps, or trundles, under its own power. The hardware’s been assembled so that it’s completely mobile, a USB battery pack is keeping the controls running and the user interface has been fixed a bit so it’s easier to steer.
The hardware set-up so far is:
- Dagu 5 Rover Chassis
- Dagu’s motor controller PCB
- Dav’s simple 3.3v to 5v glue circuitry
- The Raspberry Pi!
- USB Wireless Ethernet adapter
- Logitech USB Webcam
- Anker 5600mAh Battery
- Some screws and metal spacers that came with the motor controller PCB and a curry takeaway lid
Whereas the software stack running on the Pi and my mobile phone’s web browser is:
- Lighttpd and some trivial FastCGI python to receive commands from the UI and relay them to a unix pipe
- Another simple python script that uses RPi.GPIO to output commands to the Pi’s GPIO pins
- fswebcam to capture frames from the webcam and save them to a file for the web server
What’s changed since last time?
The most significant new addition is the Anker 5600mAh Battery, which is good value for money compared to other brands. It’s essentially a battery with a builtin charging circuit, charge level display and white LED in case you need a torch. With the batteries, bigger is normally better, but I estimated that this one will do the job very well and still cost less than twenty pounds.
The Pi consumes about 700mA or so, depending upon what it’s up to. According to its datasheet, my Linksys USB600 Wifi adapter consumes a maximum of 480mA when transmitting. I haven’t found a figure quoted for the webcam, and I’m too lazy to measure it, so I’ll just assume it’s a worst case of half an amp when it’s capturing an image and that it’s running for about half the time, so call it 250mA. I haven’t yet measured how much power the control circuity uses.
Those numbers added up gives us a total run time of just less than 4 hours of trucking about the place, which is more than enough for this stage of the project.
For a comparision, the motors in the chassis consume a maximum of 2.5A and I’ve used 2700mAh rechargable AAs, so that’s a bit over half an hour of maximum drive on a charge, although it will likely be more than that as my floor shouldn’t need maximum drive power. I haven’t yet added some analogue inputs so the Pi can monitor actual motor power consumption.
Traditional analogue radio controls operating servos operate near enough instantly, whereas my proof of concept, simple to configure CGI python script took between 500 and 1500ms to change a GPIO pin after the input button was pressed. This is fine for putting a tick in the ‘can control it’ box, but half a second lag makes it surprisingly fun to control with any degree of accuracy. So that had to go.
First up against the wall was running the python GPIO driver directly in the CGI script, that extension takes precious time to initialise itself, test it can access /dev/mem, ensure the pins are set for output etc, so I split that out into a seperate control script that ran all the time in a background process and waited for input.
That got us down to about 500ms response time, which is still pants. For those readers who don’t run web servers for a living, ‘CGI’ is a very basic way of connecting a program up to a web server and it’s rare to see it used today. The reason it takes 500ms to run is that CGI starts up a new program for every new web request, which for an interpreted language like python means it then has to initialise any modules the script includes, parse the script and then execute it. The Pi’s ARM core does run at 700Mhz, but it’s still doing work that it doesn’t need to.
The solution is to run an instance of Python all of the time, so it can cache the python language itself as well as my script, so all it has to do is listen for a request, look at the parameters and write a character to a file. For this, I’m using FastCGI, which is itself somewhat old fashioned but it’s quicker to configure in Lighttpd than WSGI:
sudo apt-get install python-flup fastcgi.server = ( ".py" => ( "python-fcgi" => ( "socket" => "/tmp/fastcgi.python.socket", "bin-path" => "/var/www/cgi-bin/fcgiPipe.py", "check-local" => "disable", "max-procs" => 1) ) )
We also have to change our Python code so that it expects to be run using FastCGI. For this, we need the flup library which is included in Raspbian and takes care of everything between the web server and our python. This library also encourages us to write our code in a more structured way as we have a single function as the entry point for all HTTP requests into our project. In my code, cgiPipe and fcgiPipe do pretty much the same thing, so it’s a good illustration of what code is required for FastCGI.
That gets us down to something approaching fast ‘enough’, although I suspect it will need further work once the Pi’s cpu gets busier with the control work I’ve got in mind
The code, as ever, is up on GitHub
As you can see from the photograph, all I’ve really done so far is to add a plastic shelf about 5 cm above the ‘deck’ of the robot chassis, which leaves enough space in the chassis for the batteries, controller PCB and webcam and enough space on the shelf for the Pi and my breadboard with its fragile interface circuits. I say fragile, but it survived flipping onto its top when it tried to drive up a wall without any of the wires coming loose.
I found the plastic lid to be perfect for a shelf, it’s easy enough to drill holes through, it’s almost exactly the same size as the chassis and it’s plenty strong enough to support the entire chassis if it needs to.
I do intend to catch up with writing up the robot’s design in a more logical order: starting with turning LEDs on and off, hooking that up to a web page, turning it up to 5v, sidestepping into USB web cams, before carrying on. I’m really enjoying this robotics game so far, it’s using such a fun variety of skills from electronics, through sysadmin to programming and AI.
My plan is to do a more robust job of connecting the modules together, I’ve got an order arriving this week from Proto-pic of some modular hookup wires and I’ve found somewhere cheap on eBay to buy a small pack of veroboard from. Why on earth is stripboard so very expensive!? Anyway, that will let me do away with the breadboard and connect to more of the pins on the controller PCB, so I can change direction on the motors.
I’d also like to try doing some cheap PWM using a python loop. General purpose multitasking operating systems and interpreted languages are a bad choice for this sort of thing, but I’ll be happy if I can get something like 0, 33%, 66% and 100% duty cycles from the output pins without flatlining the CPU.
There’s also this very interesting forum thread where somebody has written a kernel driver for the Pi that very cunningly uses DMA to drive PWM on the GPIO pins in hardware to a good accuracy level. As I also intend to use i2c and spi in the near future, I’ll have to swap over to using kernel drivers instead of RPi.GPIO and /dev/mem anyway.
Finally, once I’ve got some hookup wires, I intend to connect up a small character LCD I’ve got so that the Pi can talk to me without needing the television. For a start it will be displaying its current command and its IP address, but that’s only the beginning. I’ve found some very cheap SPI LCD modules on eBay that are on order that should be good for graphics, so it can start to map its surroundings.
I’m pretty much going to wait for Quick2Wire’s Analogue input board before I start to connect up sensors to the Pi, although I only need a couple of counter ICs and probably shift registers to start watching the quadrature inputs from the axles.
In no particular order, I want to start with it monitoring the motor current use so it cuts out before stalling. I also want it to cut out if it senses it’s about to crash or its stopped making progress. A couple of forward facing IF range finders are a good place to start there. I also had the idea of pulling apart a cheap USB optical mouse and mounting its LED and sensor on the base, that should also give it an idea of whether the chassis is actually moving or not.