Self-Balancing Robot with a Pico and a PID Controller
A two-wheeled robot that stays upright by reading an IMU hundreds of times per second — control theory you can see.
Balancing is the classic control-theory challenge. The IMU measures tilt, a complementary filter cleans the signal, and a PID loop drives the wheels under the robot's center of mass.
Mission steps
Build a tall frame
Put the battery high — a higher center of mass is actually easier to balance. Mount the IMU rigidly at the axle line.
Wire it
IMU on I2C to the Pico, motor driver on PWM pins, battery to VM.
Read tilt
Combine accelerometer angle and gyro rate with a complementary filter (98% gyro, 2% accel).
Run the PID loop
Every 5 ms compute error = target angle − current angle and set motor speed from P, I and D terms.
Tune patiently
Start with only P until it oscillates, add D to damp, then a little I to correct drift.
Code
# PID core (MicroPython) — read_angle() returns filtered tilt in degrees
import time
Kp, Ki, Kd = 25.0, 0.4, 0.8
target, integral, prev = 0.0, 0.0, 0.0
DT = 0.005
while True:
angle = read_angle()
err = target - angle
integral = max(-300, min(300, integral + err * DT))
deriv = (err - prev) / DT; prev = err
out = Kp * err + Ki * integral + Kd * deriv
set_motors(max(-1, min(1, out / 100)))
if abs(angle) > 45: set_motors(0) # fell over: stop
time.sleep(DT)Tip: test every script on the bench before installing it in a moving machine.
Questions
Why does it drift across the room?
The balance point is slightly off. Add an outer speed loop that nudges the target angle, or calibrate the IMU's zero.