This repository contains 3D models, code, notes, etc. on my self-balancing inverted pendulum project. You can watch a video of it by clicking the thumbnail below. The rest of this README explains how it works. A PDF version is also available here.
- Introduction
- Equations of Motion
- Linearisation
- Stability
- Control
- Construction
- Motor Control
- Code
- Conclusion
If you've ever tried to keep something like a broom or a stick upright on your hand you'll know it can be quite tricky! Gravity's constantly pulling it down, so if it's not perfectly vertical it'll start to fall. The same thing happens to the pendulum but it's connected to a cart which is programmed to move left and right in a way that keeps the pendulum upright.
In this document I'll explain how I built it. We'll start by deriving the system's equations of motion, then we'll linearise them so we can make use of some tools from linear control theory. Those tools will help us determine if the system is stable and how to control it. We'll talk about the physical construction of the system and how that integrates with the mathematical model. Finally we'll talk about the code that controls it.
If we want to control this system we need to know how it behaves, so let's derive its equations of motion. First we need to define our coordinate system and variables in a diagram:
We have a cart of mass
With that out of the way, now we can calculate the Lagrangian of the system. The Lagrangian is defined as the difference between the system's kinetic and potential energies
Starting with the cart, its kinetic energy is
Next, the pendulum. Because it's joined to the cart its
Differentiating them with respect to time gives the
Using the Pythagorean theorem we can combine these to find the squared magnitude of its velocity
and we can use this to find its kinetic energy
Unlike the cart, the pendulum's potential energy can change — when it rotates it moves up and down so its gravitational potential energy changes. If we say its potential energy is
where
Combining all of those energies and rearranging gives us our Lagrangian
Now that we have it we can apply the Euler-Lagrange equation to each of the system's two coordinates
and for
Rearranging these two equations and solving for
Now that we have them how do we know they're correct? One way would be to solve them for
The pendulum swings back and forth as we expect, but interestingly it also causes the cart to move. The notebook also generates an animation.
These equations look good, but they're quite complicated so it might be difficult to analyse the stability of the system and determine how to control it. Can we simplify them at all? One approach is to linearise them.
Linearising a function means finding a linear approximation of it at a particular point. For example, if we graph a function
In the case of the pendulum, our goal is to keep the cart in the middle of the track, the pendulum upright, and neither the cart nor the pendulum moving. In other words, we want all four variables
So how do we linearise our equations of motion? First, let's combine them into one vector-valued function
Let's also define the state vector
With this definition we can change our function to accept the state vector
If we include
The general equation to linearise a vector-valued function like this at a particular point
As mentioned before we want to linearise our function at the point where all the elements of
Looking at the elements within
The remaining term is the Jacobian matrix of our function evaluated at the point
I've intentionally skimmed over some details in this section to keep things short. If you'd like to learn more about linearising nonlinear systems and when it's actually valid to do that, these two videos from Steve Brunton are great: Linearizing Nonlinear Differential Equations Near a Fixed Point, and The Hartman-Grobman Theorem, Structural Stability of Linearization, and Stable/Unstable Manifolds.
Now that we have a linearised version of our equations of motion we can apply some tools from linear control theory. One of those tools is stability analysis. This tells us that if any of the eigenvalues of our
I mentioned earlier that the cart moves left and right to keep the pendulum upright. A more formal of saying that is: we can say we apply a force
Again, our goal is for
If we use the coefficients of
Another useful tool from control theory is the concept of controllability. A system is said to be controllable if it's possible to move it into any state you want using only its inputs. In our case, the only input is
If we perform this calculation using our
Now we have a way to control the system, but how do we choose
If we substitute this into our linearised equation of motion we get
This looks very similar to the original equation except
So how do we choose
Here is a Mathematica notebook that calculates the
The cart quickly moves to the left to prevent the pendulum from falling, continues moving until the pendulum is slightly angled to the right, then slowly moves to the right until the cart is in the middle of the track and the pendulum is vertical. The notebook also generates an animation.
That's enough math for now. Let's talk about the physical construction.
At its core are two steel rods that the cart slides along on linear bearings. The cart itself and the two ends are 3D printed in PLA.
On the bottom of the cart are two extensions that the timing belt connects to. The timing belt comes from one side of the cart, over the ilder pulley, all the way over to the timing pulley, and back to the other side of the cart. This means that when the timing pulley rotates, the cart moves.
The timing pulley is on an axle that's connected to an incremental rotary encoder so we can measure the position of the cart. On the other side of the axle is a 3D printed 5:1 gear train that's connected to a DC motor. I had to add the gear train because I bought a 24V motor which ended up being overkill for this project and I needed a way to reduce the RPM. On top of the housing is a limit switch which is primarily used to zero the cart position on startup, but it's also used to kill the motor if the cart gets too close to the end.
The pendulum itself is a long steel rod connected to a shorter steel rod with a
The system is all controlled by an Arduino Uno, the motor is controlled by a motor driver which is connected to a 24V power supply, and everything is connected via a breadboard.
Great! We have our control algorithm and we've built the physical system, but there's still one missing piece. The control algorithm tells us the force
We can model the electrical properties of a DC motor using this simple circuit.
We can model the mechanical properties of a DC motor by treating it as a rotating cylinder. It experiences a torque from the motor
We can solve this equation of motion for
Taking a step back, what does this equation represent? It tells us how the motor's angular velocity changes over time if we apply a constant voltage
This is the general equation for the cart's velocity over time at particular input voltage. In order to use it for our pendulum we need to find the values of the constants
Here is a Mathematica notebook that does just that. First it plots cart's velocity over time for 14 different voltages, some forwards, some backwards. Other than a blip at around
Next it uses Mathematica's FindFit
function to find the best values of
We now have an equation for the cart's velocity over time but it's not very useful. Firstly because it assumes a constant voltage and we're going to be changing the voltage to move the cart back and forth. Secondly, we're trying to find an equation to convert a force into voltage and this equation doesn't involve force at all.
How can we fix this? Newton's second law tells us that
Let's take the derivative of our velocity equation with respect to time
Earlier we found a time-indepdendent equation for the angular velocity of the motor
We don't know the values of these constants
so
Is this equation correct? One way to check is to integrate it numerically and see if the result matches the data we collected. The Mathematica notebook generates the following plot which looks pretty good.
Using Newton's second law we can multiply the cart's mass and acceleration to find the applied force
Here is the code that runs the system. One of its most important jobs is to observe signals from the rotary encoders so we know the motor and pendulum angles. That's achieved with two interrupt handlers. They're called when the signal from a rotary encoder changes, they calculate the angle change, and update the appropriate variable.
The rest of the system is a big state machine. It moves through a series of initialisation states, starts running, and finally gets killed for one reason or another.
On startup we don't know the position of the cart, so in the first state the cart moves to the right until it's pressing the limit switch. At that point we know where the cart is which lets us zero the cart position and motor angle variables.
Next, the cart moves to the middle of the track which is where we want it to be when it starts running.
We also need to zero the pendulum angle. The pendulum might still be swinging from the cart's movement, so we wait until it's still, assume it's pointing down due to gravity, and zero the pendulum angle variable. This does mean that down is considered zero instead of up, but that's fixed in the next state.
The user rotates the pendulum until it's near upright, we offset the pendulum angle variable so up is considered zero, and we start running.
If the cart gets too close to either end of the track or the pendulum angle becomes too great, we assume we're not going to be able to recover, and kill the system. You can also kill it manually by pressing the limit switch.
The last significant part of the code is calculating the cart's velocity and the pendulum's angular velocity. On each iteration of the main loop we record the cart's position, the pendulum's angle, and the time. We store the last
And that's how I built my self-balancing pendulum! The 3D models, code, notes, and everything else are available in this repository. Please let me know if you have any feedback or questions.