Author
Topic: Balancing Robot Oscillation (Read 6738 times)

I built a small balancing robot - just two DC motors with wheels and an accelerometer. Axon is the microcontroller.

My code is basically "while tilt forward: move forward, while backward : move backward. It balances for like 2 seconds before oscillating back and forth and eventually falling.Meaning it goes forward a little, then backwards a little, then forward even more, then backward even more, and then forward a lot, then backward a lot, and then falls.

I'm not a control engineer, but I'm pretty sure you need some sort of PID control. What you describe is a common phenomenon: your control system detects an error (tilt), tries to correct it (move forward/backward) but does not take into account the amount of error, and "over compensate" it (this phenomenon has probably a name, I don't know). It eventually amplify this error and falls. A simple, well tuned PID should do the trick. (You might even be able to leave the derivative part out).

I can see how a PID system would greatly help this system, but I'd be cautious on how fast you allow the motors to correct. If you set up the system well your motors will end up running forward and reverse quite rapidly. I would design the controller so that a range of a couple degrees off vertical is read as acceptable. This might prevent blowing the motor driver from changing directions too rapidly.

Yes, I think that PID is the answer. I also agree that you could probably leave the Derivative out.

It seems that simple physics with trig would fix the problem but it doesn't. You need PI or PID.

Balancing a robot without PID is like controlling the speed of your ceiling fan by manually shutting it on and off really fast. By doing this, you over compensate and undercompensate your target speed. You turn off the fan when it's too fast, and you turn it on when it's slower than your target speed. You end up oscillating from your target speed and that would basically also explain why your robot oscillates. If I get it right, it seems that your robot reacts based on tilt only and I would presume that the speed of your motor is directly proportional to the amount of tilt that you get from the accelerometer. If the above is correct, then that means that you're not putting into consideration the speed of your robot as it tilt towards the ground.

From my experience, here's what I found:

1. accelerometer signal is unreliable when in motion (too much noise). You need to filter it out either digitally (code-wise) or analog (using capacitor and resistor).2. the speed of motor to keep the robot perpendicular is direclty proportional to the angular speed of the robot and the tilt of the robot. A gyro would give you angular speed and it is immune to vibration.3. PID would reduce or eliminate your robot's oscillation.

So I suggest:

1. filter out your accelerometer using capacitor and resistor until it becomes immune to some vibrations. About 100 samples per second (100Hz) is decent to balance your robot. I think a real Segway also samples at 100Hz.2. if you're not going to use a gyro, then you need to spend more time polishing your PID and accelerometer signal. The more you filter your accelerometer to reduce noise, the more sophisticated your PID should be.3. as you tweak your PID, also try tweaking the center of gravity.4. turn off your robot when it reached 30 degree angle because it's almost impossible to recover from that angle without running your motors on high.

I'm not an expert in PID but this might help.

When balacing a robot, ideally your target angle is zero or 90 degrees (perpendicular to ground).

Right now you probably only have a "Proportional" control of your motors. When you get a tilt you subtract it from the target point, then you tell your motor to move forward or backward based on that tilt. That part alone is the P in PID. You're driving your motor "Proportional" to the amount of error from the target point.

P = p_Gain x (target_angle - actual_angle)

if you look at your code closely, you'll probably realized that you're multiplying your error by a certainamount before giving the command to your motors. That constant is called your "proportional gain".

if you only use a Proportional control, then you can be sure that your robot will oscillate. =)

to enhance your Proportional controller, you have to introduce the Integral part (the I in PID)...

remember the (target_angle - actual_angle) in the above equation for the proportional controller? That's the "error" part. The "Integral" part takes into consideration ALL your previous errors in the past and adds them all up. For example, if your robot is tilted forward and you commanded your robot to move forward based on its tilt, but after the command your robot is still tilted forward, then the Integral part will put that into consideration and would further increase the speed of your motor to try to decrease the current error.

this is your error = (target_angle - actual_angle)

Integral = i_Gain x (Sum of all error) once again i_Gain is a constant that you use to multiply the sum of error...

now you could add Integral to your Proportional controller...

Output = P + I this is your Proportional Integral controller...

you'll notice that PI controller is much much better than the Proportional controller... it shouldreally improve the balancing of your robot...

you'll notice that the PI controller is less twitchy and it's more accurate...

you could further improve on your PI controller by adding in the Derivative term... the derivativeterm is like the dampener on a spring... the Integral part rushes your value towards the desiredangle, but it has the tendency to overshoot, the Derivative takes this "rushing" aspect into consideration and "dampens" it... you'll notice that the Derivative term slows down your motorwhen it gets close to the target angle... pretty cool huh?! =)

so here's the summary... P term describes the current condition of your robot... the I term describes the past behavior of your robot... and D describes what the future out come will be...if we have all those three covered, then your robot should be able to balance...

D = d_Gain x (( current_error - previous_error)/time) yup! it seems that the derivative term depends on the current error and the previous error.. then multiplied by gain...

if you look at this mathematically, it would look like an equation for a slope... slope basically tells you the rate... i'll leave it up to you to whether or not you need the "time" term in therebecause right now I can't quite remember...

PID = p_Gain x error + integral of error + derivative of error

(please correct me if i got any of the equations wrong) but I think I got them all right...

I'd be cautious on how fast you allow the motors to correct. If you set up the system well your motors will end up running forward and reverse quite rapidly. I would design the controller so that a range of a couple degrees off vertical is read as acceptable. This might prevent blowing the motor driver from changing directions too rapidly.

Yeap. You add whats called a deadband. If you don't have it, your motors will overheat.

As for PID, the hard part is figuring out the gains/constants. I don't really know how to do that without guessing and experiments.

And make sure your accelerometer is at the center of rotation on your robot to reduce the effects of motion on it.

yes it's true... you also have to constrain the speed of your motor so that it doesn'tgo past the maximum speed that you want it to be...

motor_speed = constrain(output,0,255) here's an example where you want your speed to be between 0 and 255. That way, any output that goes negative or past 255 would be constrained.

so worry not... see pic of my balancing robot below... I started robotics from absolutely not knowinganything about programming or electronics in June and by September my robot balanced!

i used Memsic 2125 accelerometer and only used one axis... there was no gyro or anything else... it is extremely hard to balance a robot without a gyro, but just like what i said before, if you have a polished PI (I didn't use PID on the robot below), you could still accomplish this...

the microcontroller is a Basic Stamp II using PBasic... there was 200 lines of codes...just keep on trying and you'll be able to succeed!