During my last round of exams, in an attempt to avoid studying I instead started formulating plans to build a self-balancing robot. And here it is:
The all-knowing, pulsating brain of the robot is an Arduino Duemilanove microcontroller board. This was the first time I've used an Arduino, and I'm pretty impressed at how easy it is. I'm tempted to spend this whole article gushing about the Arduino and how awesome it is. But I won't.
To stay upright, the robot needs to know how much it's leaning. An accelerometer and angular rate sensor (gyroscope) need to be used together to get an accurate angle. The accelerometer gives an acceleration reading for all three axes (X, Y, Z), so simple trigonometry gives the direction of gravity, since gravity is equivalent to upward acceleration. This is highly susceptible to noise because any acceleration will interfere with the detected angle, but if it is averaged out it gives a highly accurate long-term measurement. The gyro gives the angular rate, so if its output is integrated with respect to time, you get the change of angle. This is very accurate in the short term, but integrating the output means that small errors will accumulate to a large error and the measurement will drift. The solution is to low-pass filter the accelerometer output, high-pass filter the gyro output, and add the two together.
The accelerometer and gyro are from Sure Electronics. They're powered from the 5V supply on the Arduino and have analog outputs which are connected directly to the Arduino's analog inputs. I wrote this program to test them. It gets the angle data, processes it, and prints the angle to the serial connection to be viewed on the computer. It can also interface with this graphing program.
The motor/gearbox assembly is a Tamiya Double Gearbox kit, with 36mm Tamiya truck wheels. Originally I planned to have the gearbox positioned vertically. Unfortunately the wheels aren't big enough, and don't touch the ground with the gearbox upright, so now the gearbox is horizontal. The ground clearance isn't great, bit it's enough. The main problem is restricted movement; the robot can only tip over so far until the edge of the gearbox touches the ground. But by the time it tips that far, the motors aren't powerful enough to correct it anyway.
The motors are PWM driven with an L293D driver IC which works as two H-bridges. It's rated for 600mA per channel which seems to be enough; the IC gets warm after a couple of minutes, but never hot. The motors are rated for 3V, but there's a small voltage drop in the L293D, so the voltage seen by the motors isn't quite enough for them to work well with a 3V supply. I ended up powering them with three rechargable AA batteries, with a total voltage of about 3.6V.
A standard PID controller is used by the Arduino to determine the PWM duty cycle to power the motors, with the angle as input and the duty cycle as output.
As it is, the robot's main problem is that it can't distinguish gravity from actual acceleration. When it starts moving to correct its tilt, the acceleration causes the reading for tilt to change and the robot slows down. This problem is reduced by the low-pass filter on the accelerometer but still causes stuttery motion. This could be fixed by putting rotary encoders on the wheels to detect the robot's acceleration, and subtract it from the accelerometer reading. Maybe for version 2.0.
The Arduino source code is here.
Here it is in action: