Self-balancing robot
A two-wheel robot that falls over unless your code balances it, with its own MPU6050, TB6612 driver and encoders.
It is the body of the "balance car" kits: a tall chassis on one axle, two gear motors with Hall encoders, a motor battery, and a board carrying an MPU6050 and a TB6612FNG. You wire a microcontroller to it. Let go of it and it is an inverted pendulum: gravity tips it further every millisecond unless the wheels drive under it, and the only thing driving the wheels is your sketch. The gallery project Balance bot balances it with a complementary filter and a PID.
Pins
| Pin | What it does |
|---|---|
VCC, GND |
Logic supply for the IMU, the driver's logic and the encoders, 2.7 V to 5.5 V. The motors run from the robot's own battery. |
SCL, SDA |
The built-in MPU6050 at 0x68, with 4.7k pull-ups on the robot's board. |
STBY |
The TB6612's standby: high to run. It has a 200k pull-down, so unwired it is off. |
AIN1, AIN2, PWMA |
The left motor. |
BIN1, BIN2, PWMB |
The right motor. |
LA, LB, RA, RB |
The two quadrature encoders. Optional: leave them unwired if you do not count them. |
Driving it
The motor inputs follow the TB6612FNG truth table, read with their exact timing,
so analogWrite on PWMA is measured as the duty it really is:
| IN1 | IN2 | PWM | Motor |
|---|---|---|---|
| H | L | H | forward |
| L | H | H | backward |
| H | L | L | short brake |
| L | H | L | short brake |
| H | H | any | short brake |
| L | L | any | coast |
On this robot, IN1 high drives that wheel forward on both sides. Leaning forward, drive forward: the wheels run under the body and stand it back up.
Reading the tilt
The MPU6050 is mounted flat on the body with X pointing forward, Y to the left and Z up, so leaning forward is a positive rotation about Y:
float accelAngle = atan2(-ax, az) * 57.3; // degrees, from gravity
float rate = gy / 131.0; // deg/s at the +/-250 range
angle = 0.98 * (angle + rate * dt) + 0.02 * accelAngle;
It is the full MPU6050 model, so it wakes asleep (write 0 to PWR_MGMT_1), and
WHO_AM_I reads 0x68. The accelerometer feels the robot accelerating as well as
gravity, exactly as the real one does, which is why balancing code blends it with
the gyroscope instead of trusting it.
Held, falling, fallen
The robot starts held upright by a hand at tilt degrees, still, for release
milliseconds, then it is let go: that gives the sketch time to start, as you would
hold a real one while it powers up. Past 45 degrees it is falling; at 80 degrees it
lies on the floor and its wheels spin free. The window shows which.
The window's buttons: ↺ stands it up again (held for release more), and ◀ and ▶
push the top of the body back or forward with an impulse of 0.05 N·s, enough to
set it turning at about 70 degrees per second.
The model
A planar wheeled inverted pendulum (the cart-pole with rolling wheels), integrated
with fourth-order Runge-Kutta every 1 ms. x is how far the axle has rolled and
theta the tilt:
a = M + 2m + 2Iw/r^2 + 2J/r^2
b = M l cos(theta) - 2J/r
c = I + M l^2 + 2J
a x'' + b theta'' = tau / r + M l sin(theta) theta'^2
b x'' + c theta'' = M g l sin(theta) - tau
M, l, I are the body's mass, center-of-mass height above the axle and inertia
about its center; r, m, Iw = m r^2 / 2 are each wheel's radius, mass and
inertia; J = rotor x ratio^2 is each motor's rotor inertia seen at the wheel.
tau is the torque both gearboxes put between body and wheels. The motors are
bolted to the body, so the torque that drives the wheels forward pushes the body
back.
Each motor is the linear DC motor law at the gearbox output, plus friction:
tau_i = stall (u - c w / w0) - friction tanh(w / 0.2 rad/s) - damping w
w is the wheel's speed relative to the body, w0 the no-load speed, u the
average drive over the step (+1 forward, -1 backward, times battery / voltage)
and c the fraction of the step the winding was connected (driven or braked): a
connected winding brakes with its back EMF, an open one does not.
The IMU reads the specific force at its mounting height imu, in its own axes:
gravity plus the acceleration of that point, so the accelerometer sees the wheels'
shoves. With noise at 1 it adds Gaussian noise at the datasheet's figures (0.004 g
per accelerometer axis, 0.05 deg/s per gyro axis), from a fixed seed so a run
repeats; gyro_bias adds a constant drift to the Y rate.
Properties
| Property | Default | Meaning |
|---|---|---|
mass |
800 g | Body mass, battery and boards included, wheels not |
com |
70 mm | Center of mass above the axle |
inertia |
17 kg·cm² | Body inertia about its center of mass |
height |
160 mm | Body height; a push lands at the top |
wheel |
68 mm | Wheel diameter |
wheel_mass |
40 g | Each wheel |
voltage |
7.4 V | The motors' rated voltage |
battery |
7.4 V | The motor battery; below voltage the motors are weaker and slower |
rpm |
280 | No-load speed at the wheel, at voltage |
stall |
4.0 kg·cm | Stall torque at the wheel, each motor, at voltage (0.39 N·m) |
rotor |
4 g·cm² | Rotor inertia at the motor shaft |
ratio |
30 | Gearbox ratio |
ppr |
13 | Encoder pulses per motor turn, each channel |
friction |
20 mN·m | Gearbox friction at the wheel, each motor |
damping |
0.5 mN·m·s | Viscous damping at the wheel, each motor, per rad/s |
imu |
120 mm | The MPU6050's height above the axle |
noise |
1 | IMU noise, as a multiple of the datasheet's |
gyro_bias |
0 deg/s | Constant offset on the Y gyro |
tilt |
2° | The tilt it is held at before it is let go |
release |
1000 ms | How long it is held |
The defaults are a small kit robot with JGA25-370 style 1:30 gear motors on a 2S battery. With them it falls from 2 degrees to the floor in about half a second if nothing drives the wheels.
Encoders
Each wheel makes ppr x ratio pulses a turn on each channel, 390 by default, and
four times that many edges. LA leads LB when the left wheel turns forward
relative to the body (the motor measures the wheel against the body, not the
floor). They are driven at the logic supply.
What is not modeled
Turning: the two wheels share one axle, so their torques add and a difference
between them does not yaw the robot. Wheel slip, an uneven floor, gearbox backlash,
motor inductance, the driver's half ohm and current limit, the battery sagging or
running down, and the MPU6050's INT pin, DMP and FIFO.
Readings
The probe is the tilt in degrees, forward positive. The window shows the tilt, the wheel speed in rpm and whether it is held, balancing, falling or fallen.