Build a Self-Balancing Robot with MPU6050 & PID Control
There's a moment — and you'll know it when it happens — when your little robot stops falling over. When it catches itself, corrects, and just... stands there. Humming quietly. Defying gravity. That moment makes every frustrating hour of wiring and code worthwhile. Building a self-balancing robot isn't just a cool party trick. It's a crash course in control theory, sensor fusion, and real-time embedded systems — the exact skills that power everything from drone stabilization to prosthetic limbs. If you're going to build one project this year, make it this one.
What You'll Need
Gather everything before you start. Hunting for parts mid-build breaks your flow and your focus.
- Microcontroller: Arduino Uno or Nano
- IMU Sensor:
MPU-6050(6-axis gyroscope + accelerometer module) - Motor Driver:
L298Ndual H-bridge module - DC Gear Motors:
6VN20 or TT gear motors × 2 (with wheels) - Power Supply:
7.4V2S LiPo battery or2 × 18650cells in series - Decoupling Capacitors:
100μF 16V electrolytic capacitor × 2 - Ceramic Capacitors:
100nF ceramic capacitor × 4 - Resistors:
10kΩ resistor × 2(I²C pull-ups) - Chassis: Two-wheeled acrylic or 3D-printed frame, narrow and tall
- Wiring: Jumper wires, 22AWG hookup wire
- Misc: Soldering iron, multimeter, breadboard for prototyping, hot glue gun
How It Works
At its heart, this robot is a control system problem. The robot will fall — physics demands it. The job of the electronics is to fall faster than gravity wins. Here's how the pieces talk to each other.
The MPU-6050 sits at the top of the robot and measures two things simultaneously: acceleration (which tells you tilt angle relative to gravity) and angular velocity (which tells you how fast it's tilting). Neither measurement alone is clean enough to act on. Accelerometers are noisy; gyroscopes drift. The solution is a complementary filter — blending both signals to get a smooth, accurate angle estimate. A more advanced implementation uses a Kalman filter, but complementary gets you 90% of the way there with a fraction of the complexity.
That angle gets fed into a PID controller — Proportional, Integral, Derivative. Think of it as three corrective forces working together. P (proportional) pushes the motors harder the more the robot leans. I (integral) corrects for slow drift over time. D (derivative) dampens oscillation by reacting to the rate of change. The PID output becomes the PWM duty cycle sent to the L298N, which drives both motors forward or backward to catch the fall.
The MPU-6050 communicates via I²C on pins A4 (SDA) and A5 (SCL) on the Arduino Uno. The L298N receives PWM signals on its enable pins and direction signals on its input pins. The 100μF caps smooth the motor power rail — motors spike hard on startup, and without decoupling, that noise resets your Arduino mid-balance. Ask me how I know.
Step-By-Step Build
- Mount both gear motors to the bottom of your chassis. Wheels should be centered under the robot's body — balance point matters.
- Secure the Arduino and
L298Nmodule to the middle tier of the chassis using standoffs or hot glue. - Mount the
MPU-6050module as high as possible and as close to vertical center as you can manage — it should be perfectly flat relative to the robot's upright axis. - Solder a
10kΩresistor between theSDAline and3.3V, and another10kΩresistor between theSCLline and3.3V. These are your I²C pull-ups. - Connect
MPU-6050VCC→ Arduino3.3V,GND→GND,SDA→A4,SCL→A5. - Wire the
L298N:IN1→ ArduinoD7,IN2→D8,IN3→D9,IN4→D10. ConnectENA→D5(PWM),ENB→D6(PWM). - Solder one
100μF 16V electrolytic capacitoracross the motor power input terminals on theL298N(positive to12Vrail, negative toGND). Add the second across your battery terminals on the chassis. - Place
100nF ceramic capacitorsdirectly across each motor's terminals to suppress RF noise. - Connect your
7.4VLiPo to theL298Npower input. TheL298N's onboard5Vregulator feeds the Arduino via its5Voutput pin. - Before powering on: Check with a multimeter that you have
3.3Von the MPU-6050 VCC pin and that no wires are bridging ground to your signal lines. - Upload the PID balancing sketch (use the
MPU6050library by Electronic Cats and a standard PID library). Start withKp = 20,Ki = 0,Kd = 0.8.
Testing & Calibration
Power up with the robot held vertical and watch your Serial Monitor. You should see angle readings near 0° when upright and changing values as you tilt it. If you see garbage data, check your I²C connections and confirm the MPU-6050's I²C address is 0x68 (AD0 pin to GND).
Place the robot on the ground and let go — briefly. It will likely lunge forward or backward at first. Tune Kp first: increase it until the robot oscillates fast, then back off by 20%. Then add Kd to dampen the wobble. Only add Ki last, in tiny increments, to correct slow drift. Finding the balance point is iterative — expect 30 minutes of tuning. Mark your best values in comments in the code.
Troubleshooting
- Robot immediately falls without correcting: Motor direction is reversed. Swap the wires on one motor, or flip the sign of your PID output in code.
- Arduino keeps resetting: Motor noise is spiking the power rail. Verify your
100μFcaps are installed correctly — polarity matters on electrolytics. - Angle reads
NaNor stuck at one value: I²C communication failure. Re-check SDA/SCL connections and ensure pull-up resistors are in place. - Robot oscillates wildly and won't settle: Kd is too low or Kp is too high. Reduce Kp by 30% and increase Kd gradually.
- Robot drifts in one direction consistently: Your MPU-6050 is not mounted perfectly flat, or one motor is faster than the other. Calibrate the zero angle offset in code or add a small trim value to one motor's PWM.
Upgrades & Modifications
1. Add Bluetooth control. Drop an HC-05 module on the UART pins and send PID trim commands from your phone. You can steer the robot while it balances — a genuinely impressive demo that teaches you wireless serial communication simultaneously.
2. Implement a Kalman Filter. Replace the complementary filter with a proper Kalman filter for dramatically smoother angle estimation. The math is more involved, but libraries exist. The improvement in stability on rough surfaces is immediately visible — and you'll understand why aerospace engineers love this algorithm.
3. Add encoders for position hold. Wheel encoders let you implement a second outer PID loop that corrects for position drift — the robot stays in one spot instead of slowly walking across the room. This mirrors exactly how real balancing systems like Segways operate, and it elevates your project from demo to engineering artifact.
Watch the full build walkthrough on CircuitMasters YouTube →