A few months back, I posted about my prototype "Raspberry Rover" - and then I had to stop work on it for a while, because things were busy at work, and my part-time work on iFringe and FringeGuru were reaching their busiest time of the year with the Edinburgh Fringe Festival coming up.
Recently I was able to pick it back up again, and fix a few of the snags that I'd come up against. It's now in a state where I feel able to share some of the lessons learnt. It's far from perfect, but it is functional with some clear ways forwards.
This posting will deal with the hardware design, and I'll talk about software and further plans for the future later.
The hardware consists of these main systems:
The robot chassis.
The Raspberry Pi, brains of the operation
The hardware interfacing between Pi and motors etc.
The power supply
The chassis
Cable ties and modelling balloons - the construction tools of kings.
As mentioned in the earlier post, I picked up a cheap '3-in-1' toy robot kit from the internet. I've found that kits like this are a very cost-effective way to get a well put together system, taking care of the hard part of the mechanical engineering. This particular kit is pretty good - it's very modular, with a choice of 3 main configurations (fork lift, tank and grabber), and has 3 geared motors with easy to use connectors (0.1" 2-way female headers, one per motor, directly wired to the motor contacts). The main drawback is that there's nowhere very obvious to mount further hardware. In the end, I used a combination of reusable cable ties and modelling balloons, balancing all the extra components on the top of the robot chassis. "Wait," you say. "Modelling balloons?" Yes. They're like tie-your-own, giant rubber bands, and are surprisingly useful for attaching things together temporarily.
The Raspberry Pi
The Pi makes for an excellent robot brain. It's cheap, fairly low power consumption, small, and has good connectivity and processing power for an embedded device. I found it very straightforward to add a cheap webcam (for vision) and tiny wifi adapter (Edimax EW-7811UN, which makes it easy to log into the robot while it's on the move).
The GPIO header makes it easy to communicate directly with other hardware, exposing SPI, I2C, and various GPIO pins. These days, the default Raspbian kernel and Linux distro make it easy to interface directly with the GPIO hardware, which is great.
Hardware Interface
Plenty of space for a dual H-bridge motor controller. Placing a smoothing capacitor here on the board lines up nicely with blank space on the Raspberry Pi PCB, giving the board a bit more support and stability - otherwise it's supported entirely by the 26-way GPIO header.
Initially, I used a single "Slice of Pi" prototyping board from Ciseco. This breaks out all the GPIO pins into well-labelled, Arduino-style female headers, has enough room for one, maybe 2 16-pin through-hole ICs in its prototyping area, and also offers optional interfacing to XBee-style radio modules. Before I got the wifi working, I was using an XBee to give me a remote serial console to the Pi, but wifi turned out to be much less prone to packet loss.
The prototyping area gave enough room to connect an SN754410 dual H-bridge motor controller. This was perfect for controlling the robot's motors, as it can be driven directly from the Pi's GPIO signals, and switches an optionally separate power supply to the motors. Sending one pin high drives the motor forwards, and another pin will drive it backwards. I connected very simply with one GPIO pin to each of the 4 direction control pins (2 for each motor), and the motor connectors directly to the motor output pins on the IC.
Once I'd got things working with the basic 2 motors for movement, I decided to stack a second Slice of Pi on top of the first, so that I could add another H-Bridge driver (to control the auxiliary motor - for grabber, or forklift - connected exactly the same as the first), and also to add a couple of small microcontrollers, interfaced to the Pi over I2C.
Using stackable headers to make a stackable Slice of Pi board. This needs some care to make sure that components on the two boards don't physically clash with each other, but it works very well.
I chose to use ATTiny85s, because I have a number of them lying around, they can be programmed via the Arduino tools, they're dirt cheap, they fit a surprisingly large amount of function into their titchy 8-pin package, and they can be run from a wide range of voltages (so I was able to connect them directly to the Pi's 3.3V rail, and not worry about level conversion).
One of the ATTinies is currently designated as input (3 channels, 2 of them analogue-capable), and one as output (3 channels, currently driving LEDs directly).
LEDs mounted directly in a female header. These are controlled by an ATTiny85.
There are a few advantages to using Tinies for IO:
By connecting them over I2C, you can control a very large number (around 99) from a single pair of GPIO pins on the Pi
They form a cheap interface between the Pi (pretty cheap, but for a long time very hard to replace) and the random electrical signals that you're playing around with while prototyping
They can run their own programs, so can be fairly autonomous of the main programming on the Pi.
They have analogue inputs (the Pi has none), and PWM outputs (the Pi has just one).
They need no additional components
A nicer choice yet would be to wire up an ATMega328 (the core of the Arduino), but that takes a lot more space on the prototyping board, and requires a handful of supporting components. The Tinies were more than sufficient for my needs.
Where possible, everything was wired up with removable connectors - usually, taking a cue from the motor connectors, I used pin headers on the circuit board, with push connectors to connect to external components and power.
Power supply
This turned out to be the trickiest part to get right, although the initial design was very straightforward. In my post about powering a pi from batteries, I looked at a few ways to give the robot his own power supply. Eventually I settled on a battery box approach:
It gives a broad, flat platform to mount the other components on top of
It's easy to recharge without having to remove the batteries
It gives a steady 5V supply, with a large capacity.
Custom USB power connector. Only 2 of the 3 pins are connected (5V and 0V). This connector fits nicely into the power header on the Slice of Pi board.
The battery box has a standard USB socket to provide the output power. Although I could have used a standard Pi USB power lead, this would have been sub-optimal, because of the limitations of the power fuses on the Pi's micro-USB input. Instead, I chose to make my own custom lead to supply the 5V directly into the female power header on the Slice of Pi board. This bypasses the fuses, and allows the full current capacity of the power supply to be used.
As well as the standard 5V power output, I also hacked in a connection directly to the input voltage from the batteries to the power converter inside the box. This meant that I could directly read the current battery voltage using an analogue input on one of the ATTinies - giving me a charge level indication. As well as being quite cool to be able to get a battery level reading on the Pi, it also makes it possible to be able to automatically shut down the Pi if the battery level gets too low, avoiding damage to the batteries.
In the end, due to problems with the motor power (see later), I also ended up mounting an additional standard battery pack, dedicated to supplying power to the motor.
Problems, and their solutions
Here are a few of the snags I hit along the way, and the solutions I adopted.
Initially, I used the Pi's 5V rail as the power supply for the motors, but it became quickly obvious that when the motors drew too much power, the Pi's supply couldn't cope, and it reset. I tried several tricks to try to sort this out:
Connect a large (3,000 μF) capacitor across the power supply rails. In theory this helps cope with transient surges, and it did help with some scenarios, especially in conjunction with other tricks, but was never completely satisfactory. Observing things with an oscilloscope, the power was still dipping well below the necessary 5V on a regular basis.
Connect the motor supply pin directly to the battery voltage. In theory, this would have separated the motor supply from the computer supply, and if the voltage regulation on the voltage converter between the battery and the computer was good enough, then there might have been no interference between the two supplies. As it happens, the regulation wasn't good enough.
The final solution was to simply use a separate battery pack for the motor. It's less neat, but does have one advantage - it makes it easy to select the voltage that will be used to drive the motors. When running at 5V or so, the motors run quite fast, and can make it hard for the vision system to keep up with the changing view. Using a 3V supply makes things a lot slower, and therefore easier for the robot to cope - at least until I optimise the vision system a little better.
The Slice of Pi provides a great little platform for building prototyping boards, but it doesn't have a lot of space. They've recently improved that with the Humble Pi, which is a lot bigger - I'd probably use one of those now in preference. But it seemed to me that it should be easy to stack Slices, and indeed it is. Instead of using the 1x10 female headers that come with the board, I used some stackable headers designed for Arduino, that have long pins at the bottom. Soldering those in, it's easy to pass the pins from one header into the sockets on the header of the board below, and almost all of the relevant signals are passed through on those headers. The ones that are missing are the power pins, and TX/RX on the XBee interface - but those are all easily taken care of using the same technique.
The battery input voltage ranges from about 3V up to about 4.5V. Unfortunately the ATTinies trying to measure that voltage are running at 3.3V, so this can overload their analogue input. Not only that, but providing a voltage on an ATTiny input pin when the rest of the power is off can lead to current leak into the rest of the circuit - in the case of this robot, that meant that the power light on the Pi came on, which wasn't good and presumably would have drained the battery. I solved both of these problems by building a simple voltage divider out of a pair of 1 MΩ resistors, which were large enough to avoid appreciable battery drain, and halved the input voltage to give a more manageable range to measure.
In action
Here's a small video of the improved Rover in action.