⚖️ PID Balancing Robot
Defy gravity with math. Dynamically balance a two-wheeled ESP32 robot using an MPU6050.
Overview
An inverted pendulum is a classic control theory problem. By reading the precise tilt angle from an IMU and applying a calculated counter-force via the wheels, the robot can remain upright indefinitely.
What you'll learn: I2C IMU reading, complementary/Kalman filters to fuse accelerometer and gyroscope data, and advanced PID loop tuning.
Estimated time: 6-8 hours. Difficulty: ⭐⭐⭐⭐⭐ Expert.
Components Needed
| Component | Specification | Qty | Notes |
|---|---|---|---|
| ESP32 Development Board | Fast processing | 1 | Needed for fast PID loops |
| MPU6050 | 6-DOF IMU | 1 | Accelerometer + Gyro |
| Stepper Motors | NEMA 17 or similar | 2 | For precise, immediate torque |
| A4988 Drivers | Stepper Driver | 2 | |
| Chassis | Custom/3D Printed | 1 | Center of mass should be high |
Step-by-Step Tutorial
1
Mechanical Build
A high center of gravity actually makes balancing EASIER because it falls slower. Mount heavy components (like batteries) near the top.
2
Read the IMU
Raw accelerometer data is noisy; raw gyro data drifts over time. Use a Complementary Filter:
angle = 0.98 * (angle + gyro * dt) + 0.02 * accel.3
Fast PID Loop
The PID loop must run at a strict, fast interval (e.g., 200Hz). Use timer interrupts on the ESP32 to ensure the loop timing is precise.
4
Drive Steppers
Unlike DC motors, steppers need step pulses. The PID output determines the frequency of these step pulses (speed).
Tuning a balancing robot PID: Set Kp until it oscillates quickly. Set Kd to slow down the oscillation. Set Ki to fix long-term drift.
Code / Configuration
balancing_bot.ino
INO
// Balancing Robot IMU Filter (Snippet) - Volt X
#include <Wire.h>
#include <MPU6050.h>
MPU6050 mpu;
float angle, gyroRate;
unsigned long lastTime;
void setup() {
Wire.begin();
mpu.initialize();
lastTime = micros();
}
void loop() {
unsigned long now = micros();
float dt = (now - lastTime) / 1000000.0;
lastTime = now;
int16_t ax, ay, az, gx, gy, gz;
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// Calculate accelerometer angle
float accelAngle = atan2(ay, az) * 180 / PI;
Reviews & Ratings
—0 reviews
Sign in to leave a review
Loading reviews...