Self-Balancing Robot: The Theory and the Build
Share
A self-balancing robot is an inverted pendulum: a top-heavy body on two wheels that has no stable resting position and will fall over the instant you stop correcting it. It stays upright only because it constantly measures which way it is tilting and drives the wheels underneath the fall, fast enough and often enough — many times a second — to catch itself before the tilt becomes a fall. Take away the sensing loop, or slow it down too much, and the physics wins immediately.
Why is a self-balancing robot an "inverted pendulum" problem?
A ball resting in a bowl is stable — nudge it and it rolls back to the bottom. A pencil balanced on its tip is the opposite: any tiny deviation grows, and gravity pulls it further off balance rather than restoring it. A two-wheeled robot with its mass sitting above the axle is the pencil, not the ball. It has no equilibrium it falls back into on its own. The only way to keep it standing is an active control loop: sense the tilt, decide how hard to react, and move the wheels in the direction of the fall so the base gets back underneath the center of mass before it tips too far. This has to run continuously — pause the loop for even a fraction of a second and the robot topples, because nothing about the mechanics is self-correcting.
What does PID control actually do here?
PID stands for Proportional, Integral, Derivative — three ways of turning a single measured error (how far off vertical the robot currently is) into a motor command.
The proportional term reacts to the size of the current tilt: lean a little, get a small correction; lean a lot, get a strong one. On its own, a proportional-only response tends to overcorrect and oscillate, rocking back and forth instead of settling.
The derivative term looks at how fast the tilt is changing and pushes back against that speed, which damps the oscillation the proportional term introduces — it is what stops the robot from swinging wildly past vertical each time it corrects.
The integral term watches for a small, persistent lean that proportional and derivative alone never fully erase — caused by an off-center battery, an uneven chassis, or a motor that's slightly weaker on one side — and slowly adds correction until that steady-state bias is cancelled out.
All three run every loop cycle, added together, to produce one motor speed/direction command per wheel.
What parts does a self-balancing robot need?
At minimum: a microcontroller, an inertial measurement unit (IMU) to read tilt, a motor driver capable of driving two motors in both directions, two DC gear motors with wheels, a chassis to mount everything, and a battery. The IMU combines an accelerometer (which senses the direction of gravity but is noisy during motion) and a gyroscope (which senses rotation rate accurately over short windows but drifts over time) — the firmware fuses the two into one stable tilt-angle estimate, which is the actual number the PID loop reacts to.
Why is tuning PID gains the hard part?
Getting the parts wired up is the easy half of this build. The default Kp, Ki, and Kd values that any generated sketch starts with are placeholders, not a working configuration — they almost never balance a physical robot on the first try. Every chassis has a different weight distribution, motor response, and wheel grip, so the gains have to be tuned by hand, on the actual hardware, through trial and error: raise the proportional gain until the robot reacts firmly, watch it oscillate, add derivative to calm the oscillation, and only then add a small integral term to kill any residual lean. Get the values wrong in one direction and the robot barely responds and falls slowly; get them wrong in the other direction and it visibly shakes itself apart or overcorrects into a fall. This is the genuinely hard part of a self-balancing build — harder than wiring a sensor or writing the loop — and no parts list, however complete, removes the need for that iteration.
Watch it built live
We gave Compoden's AI build assistant this exact prompt, live, with nothing pre-arranged: "I want to build a two-wheeled self-balancing robot using an MPU6050 and PID control, with an Arduino Uno."
It returned a complete nine-part tray in one pass and explained its reasoning in plain language. On the microcontroller: "The Arduino Uno R3 CH340G ATmega328P Board is the main controller... For this project, the Arduino Uno will read data from the sensor and send commands to the motor driver to keep the robot balanced." On the IMU: "The MPU6050 3-Axis Gyro/Accel Sensor Module is an inertial measurement unit... Before you can get useful information from it, you must calibrate it, which means teaching it what 'level' looks like." On the driver: "The L298N Motor Driver Module is needed because the Arduino cannot directly provide enough power for the motors."
It also flagged real risk, unprompted: "Common issues with this type of build include not calibrating the MPU6050 sensor correctly, which will make the robot unable to balance. Another common problem is not providing enough power to the motors, as the total active parts draw roughly 5054mA, which is a significant amount."
Watch the firmware get generated
We asked the Compoden PWA firmware assistant to write the control loop directly: "I'm building a two-wheeled self-balancing robot with an Arduino Uno, an MPU6050, an L298N motor driver, and two DC motors. Write firmware implementing a PID control loop that reads tilt angle from the MPU6050 and adjusts motor speed to keep the robot balanced."
It generated a real Arduino sketch that includes the Adafruit MPU6050 library, defines the L298N enable/direction pins for both motors, and sets up double-precision Kp, Ki, and Kd variables. The code comment above the gains is explicit about what they are: "PID Constants (Tune these for your robot!) — These are starting values, expect to adjust them significantly." The assistant's own summary repeated the same point: "You will need to carefully tune the Kp, Ki, and Kd values for stable balancing." These are starting points for the iteration described above, not a finished, working configuration — treat them as a first guess to tune from, not a guarantee the robot will balance as generated.
Get everything in this build
Every part below is exactly what the AI assistant put in the tray for this build, at the price it quoted at capture time.
| Part | Role | Qty | Price | Add to cart |
|---|---|---|---|---|
| Arduino Uno R3 CH340G ATmega328P Board | Microcontroller | 1 | Rs.230 | Add to cart |
| MPU6050 3-Axis Gyro/Accel Sensor Module | IMU (tilt sensor) | 1 | Rs.180 | Add to cart |
| L298N Motor Driver Module | Motor driver | 1 | Rs.180 | Add to cart |
| TT Gear Motor (1:48, Dual Shaft) | Drive motors | 2 | Rs.180 each | Add to cart |
| BO Motor Wheel 65mm | Wheels | 2 | Rs.27 each | Add to cart |
| 2WD Robot Chassis Kit | Chassis | 1 | Rs.280 | Add to cart |
| 18650 Battery Shield Module | Power supply | 1 | Rs.280 | Add to cart |
| 400-point solderless breadboard | Prototyping | 1 | Rs.40 | Add to cart |
| Male-to-Male Breadboard Jumper Wires (20 cm, 24 AWG) | Wiring | 1 | Rs.40 | Add to cart |
| Total (9 parts) | Rs.1,644 | Add all 9 to cart | ||
Prices and stock were live at capture time and can change — the AI assistant's tray always reflects current catalog stock and pricing when you build.
Built and Backed by Compoden
Every part in this list ships from Compoden's own catalog, so what the AI assistant recommends is what's actually in stock and buyable, not a generic parts list copied from elsewhere. The same build reopens in the assistant after checkout with this exact tray, its wiring, and its firmware attached, so troubleshooting a balance problem later starts from the real hardware you bought rather than a blank page.
FAQ
Can this robot balance itself with the default PID values from the generated firmware?
Not reliably. The generated Kp, Ki, and Kd values are explicitly marked as starting points that need real-world tuning on your specific chassis, weight distribution, and motors. Expect an iterative tuning process, not an out-of-the-box result.
Why does the build need both an accelerometer and a gyroscope instead of just one?
The accelerometer measures the direction of gravity but is noisy whenever the robot is moving or vibrating. The gyroscope measures rotation rate accurately over short periods but drifts over longer ones. The firmware combines both into a single fused tilt angle so the control loop has a stable number to react to.
What happens if the PID gains are set wrong?
Too little correction and the robot tips over slowly because it isn't reacting hard enough. Too much, especially too much proportional gain without enough derivative damping, and the robot visibly oscillates or shakes itself off balance. Both are normal parts of the tuning process, not signs of a broken build.
Why does the L298N need its own power supply?
The Arduino's own 5V line can't supply enough current to drive two DC motors. The L298N takes logic-level signals from the Arduino and switches a separate, higher-current battery supply to the motors, which is why the assistant calls out connecting a separate supply and sharing a common ground.