Motivation

Several years ago I build an inverted pendulum on a cart, I spent about a year trying to balance the rod with stepper motors with no success, however, I saw a lot of balancing robots build with stepper motors, so I decided to give it a try once again.

Choice of components

The idea was to use cheap and popular components so that in the future I can turn this project into a DIY kit with instructions for a broad audience.
This is what I ended up with:


Mathematical model and simulation

Assuming we are using stepper motors, we can control torque directly. I wrote a post on Kaggle with equations and simulations of the robot. For stabilizing the robot I used 2 PID control loops:
- inner PD-loop for holding upright position
- outer PI-loop for bringing velocity to zero
I assume there is a need for the third loop to control the position (comments of experienced users are welcome :) )

Frequencies
This is the most frustrating part when it comes to the implementation, if you choose frequencies wrong tuning PID coefficients will not help. What frequencies am I talking about?

Assume we want to allow maximum wheel velocity 5 rotation per second, having D = 72mm wheels from roller skate means linear speed is about 5 * 72/1000 * PI ~ 1.13 m/s which is more than enough. Using 1/8th micro-stepping mode we need 5 * 1600 = 8000 pulses per second, in fact, we need at least twice that for triggering step pin from LOW to HIGH and back, so we need to run stepper control routine at least at 16kHz.

Pulse frequency also gives us "velocity resolution", e.i. the higher the frequency the closer velocities if we change a number of pulses per second which is what we need to produce a smooth force, otherwise the robot will experience a kick when the velocity changes which not what our controller is trying to predict.

In my current implementation, I ended up with 40kHz. Also, this routine should be timely precise, so we should use timer interrupts here.

In order to balance the robot the motor needs to produce a force, so it should accelerate between measurements, ideally, the velocity should change after each step of the stepper motor, meaning that step delay should be recalculated after each step. But it requires floating-point operations in the timer ISR which is too heavy. So I just put in the main loop and run as fast as possible.

The frequency at which we obtain the new position of the robot, should be 10-100Hz, consider that i2c communication and filtering take unavoidable constant time, so we can't waste CPU time at the expense of the velocity update.

Intuitively the velocity update cycle should be faster than the measurement so that the force produced has the time to act on the robot after the measurement.


Working video


To be continued...

This is still an ongoing project, next steps would be the following:

If you are interested, feel free to join at any stage :)