Monthly Archives: April 2014

Experimenting With Dynamic Stability

Balancing robots are interesting to me because they use such a simple mechanism to achieve a behavior that seems complex and intelligent. They are also a great introduction to applied control systems, and particularly PID controllers. After seeing videos of these robots online I wanted to give it a try for myself, but I also wanted to try something a little different. This got me thinking about (somewhat) practical uses of a balancing robot, and reasons why they might be better at something than a robot with four wheels. The basic idea of my design was something that could act as a mobile table with some resistance to tipping over. This could be useful if I was carrying food or drinks out of the kitchen and needed another hand. The design has been through two iterations and still needs plenty of work, but this video shows a quick look at the current state:

For the robot to meet my goal, it would have to be:

  • Very stable: It can’t be dumping stir-fry all over the floor
    • This means a good control system with properly tuned PID constants
  • Fast enough to keep up with my walking
    • This is a function of motor speed, but also relies on good control
  • Tall enough to be useful
    • The taller the robot is, the more unstable it’s likely to be. My solution is to place a lot of the weight close to the bottom.
  • Sturdy enough to carry plates, etc.
    • Strong materials and design is a requirement. It can’t be vibrating its motors loose.
  • Able to stay in one place. Many balancing robots drift over time.
    • Somehow it needs to find its own center of balance dynamically. This allows plates, etc. to be set on top without causing it to drive off if they’re not perfectly balanced.

For the sake of simplicity and rapid development, the key parts used in this robot are:

Implementing the PID controller is not a difficult task once you understand the idea, but tuning a system that can damage itself if it falls over can be tough. For example, my quick and dirty PID controller is implemented here:

float ComputePID(float input, float kp, float ki, float kd, float setpoint, float &error_sum, float &last_input, float delta) {
 // compute all working error variables
 float error = setpoint - input;
 error_sum += (error * delta);
 float d_input = (input - last_input) / delta; // take the derivative of the input instead of the error to eliminate derivative kick
 last_input = input;

 // compute PID output
 float output = (kp * error) + (ki * error_sum) - (kd * d_input); // derivative term must be negative because its based on input
 return output;

In the case of my balancing robot, the setpoint is the angle the IMU needs to report to be considered “balancing” and the delta is the time between PID calculations. The error_sum (integral) and last_input (derivative) are passed by reference from the calling method so that different systems can use the PID code. Finally, the output is a PWM value that is common to both motors. A differential term can be added to the motors afterward to allow the robot to turn.

This system can be tuned using the Ziegler–Nichols method to obtain kp, ki, and kd if it’s done carefully. First, the ki and kd are set to zero. The kp is increased slowly until the robot starts to oscillate back and forth steadily without falling over. That kp value is called Ku (ultimate gain) and the period of robot oscillation is Pu (ultimate oscillation period). These values are then plugged into the following equations to obtain kp, ki, and kd:

  • Kp = 0.60*Ku
  • Ki = 2*Kp/Pu
  • Kd = Kp*Pu/8

This gives reasonably good results, but usually requires a little tweaking.

Once this was working, I wanted the robot to find its own setpoint, which depends completely on the distribution of weight and can change when something is set on top. This is done by cascading PID controllers, which means adjusting the setpoint of one PID controller (the one that balances the robot) with another PID controller (one that will find the correct angle to balance at). This can be a complete nightmare to tune because telling the Pu apart from normal balancing oscillations is very hard. The trick is to set the PID delta (the time between PID calculations) for this second PID controller, which is finding balance angle, to a much longer time than the one that balances. This makes sure Pu results from large, sweeping oscillations which are much more obvious. I’ve had good luck with a delta that’s 5 to 10 times larger. This second PID controller which finds the balance angle takes the common motor PWM (the output of the balancing PID) as an input, zero as a setpoint (if the robot shouldn’t be moving, but this is really the RPM you’d like the motors to be turning at and it can be adjusted to change the robot’s speed), and the output is the setpoint of the faster, balancing PID controller (the angle that is considered “balanced”).

This is all I have done so far, but I’m working on some more interesting behavior now that I’ve got a system that balances well enough.