Balancing Robot
Over the past months I've been experimenting with an interially-balancing robot ever since I got one using Infrared sensors to work. The premise of a balancing robot (like the Segway) is that it must be aware of its current position. This data can then be fed into a model and appropriate action can be taken. Think of a broomstick on a hand. If it starts falling, you move your hand in the direction that it is falling. Of course issues arise like how to prevent from overshooting and having the broom wildly oscillate before falling.
First Attempt
Please Download Flash Player
The robot above uses a reflective IR sensor to estimate its angle, but this only works on specific surfaces. Also, the robot does not have any onboard batteries. See improvement below!
Components
-
Physical Chassis made entirely from Lego Bricks. The Lego motors are very nice because they provide very precise speed control at low speeds. The battery is mounted on the top of the robot as to keep a high center of gravity
-
Electronics composed mostly of sampled parts. The microcontroller is an ATmega32. The internal ADC is used to sample the sensors. The uC also generates the PWM and direction signals to control the motor via the L293 double H-bridge chip. A gyroscope (ADXL300) measures angular velocity and a dual-axis accelerometer (AD220) measures the net resultant force (magnitude and direction) acting on the robot, giving a nice indication of where gravity is.
-
Logic is coded in C and compiled with the WinAVR (GNU C). At 200 times a second the robot undergoes a "state-update" where it updates its position and controls the motors accordingly. The code also receives input from the serial port where all of the robots parameters can be changed and from which information about the state of the robot can be gotten.
Control Theory
A balancing robot is a great application to which control theory can be applied because it becomes almost immediately obvious when it is done incorrectly (the robot topples over) A PID (Proportional Integral Derivative) loop was used, taking input as the position estimate of the robot
Sensor Fusion
Sensors, especially inexpensive ones, might not be terribly precise. Besides this, electrical noise tarnishes any perfect sensor because somewhere down the line, an analog value must be measured. For an accurate angle estimate, the balancer requires two sensors.
The accelerometer measures the net acceleration vector (angle and magnitude). If the accelerometer is not moving, then this vector always represents gravity (and from that we know the angle of the sensor with respect to gravity). The accelerometer is mounted on a mobile base, though, which must undergo acceleration, and so the reading rarely reports solely the gravity vector
The gyroscopic sensor (gyro) measures angular velocity. We must know angular position. Solution: numerical integration. The gyroscope values are unbiased (so that 0 represents no angular velocity) and added to an accumulator periodically. The value of this accumulator is proportional to the angular displacement (the proportionality constant is dependant on factors like the sampling frequency and scaling of the gyro). The issue with this method is that due to the integration, any error in the gyro signal is accumulated and grows. Most of these are due to the gyro reporting values indicating a small angular velocity when in fact the angular velocity is zero (drift). This can be partially eliminated, at the cost of precision, by implementing a deadband. Even still, errors do accumulate and the angle estimate progressively worsens.
In summary: the accelerometer returns the correct angle in the long term, but it is adversely affected by short term conditions. The gyro is precise in the short term, but it's long term output is prone to error.
Initially I tried to implement a Kalman filter but that didn't work too well because I was unable to get the filter coefficients tuned well enough. There was a phase lag between the angle estimate and the true angle.
An easier solution exists for most purposes. By lowpassing the accelerometer output, highpassing the gyro output, and combining these two filtered signals, a reasonable angle estimate can be generated. Shane Colton put together a great paper explaining this and other methods of determining the angle.
The pseudo code is basically:
Accel //contains the accelerometer output in [angle units]
Gyro_vel //contains the gyro output in [angle units / time]
angle //contains the angle estimate
angle = .97 * (angle+Gyro_vel) //this line does integration
angle = angle + (.03 * Accel).
.97 and .03 are the complimentary filter coefficients. The small value .03 means that only long-term changes in the acceleration will affect the angle estimate.
Video
Here's a video of the robot as of August 23, 2008
As seen in the video, the desired balance position is set a bit off from the true balance position so that the robot has a constant tendency to drive forward. I use my hands to bump it back into the camera's field of view.
Some physics...
Here are some rudimentary calculations proving that a top-heavy balancer is more stable.