How to Build a Self‑Balancing Robot with Arduino and Free Sensors
Ever watched a Segway glide across a hallway and thought, “I could make one of those at home”? The idea of a robot that stays upright on two wheels feels like magic, but the truth is it’s just a clever mix of math, a few cheap parts, and a lot of patience. In today’s post I’ll walk you through a simple, no‑cost‑sensor version that you can build on a weekend. Grab your Arduino, a couple of old phone accelerometers, and let’s get those wheels wobbling in the right direction.
What You Need – The Bare Minimum
Before we dive into code, let’s list the parts. I like to keep things cheap and reusable, so most of these can be salvaged from old gadgets.
- Arduino Uno (or any compatible board) – the brain of the robot.
- Two DC gear motors with wheels – they provide the motion.
- Motor driver (L298N or similar) – lets the Arduino control motor speed and direction.
- Two MEMS accelerometers (e.g., MPU‑6050) – these are the “free sensors” you can pull from a discarded smartphone or a broken drone.
- Battery pack (7.4 V Li‑Po or 4×AA) – enough juice to run the motors and Arduino.
- Chassis – a simple 3‑D printed frame or even a piece of plywood works fine.
- Jumper wires, screws, and a bit of tape – the usual maker staples.
If you don’t have an accelerometer, you can use the built‑in gyroscope of the MPU‑6050; it gives both acceleration and rotation data in one chip, which keeps the wiring tidy.
Understanding the Balance Problem
At its core, a self‑balancing robot is a classic control‑system problem. The robot is an inverted pendulum: the center of mass sits above the wheel axle. When it tilts forward, the wheels must spin forward to bring the mass back under the axle; when it tilts backward, the wheels spin backward. The sensor tells us the tilt angle, the controller decides how fast the wheels should turn, and the driver makes it happen.
The Role of the Sensors
The accelerometer measures linear acceleration along three axes. When the robot is still, the only acceleration you feel is gravity, so you can infer the tilt angle from the X and Y readings. The gyroscope measures angular velocity, which helps smooth out rapid changes and reduces jitter. By fusing both readings (a technique called a complementary filter) we get a reliable estimate of the robot’s angle.
Wiring It All Together
Here’s a quick sketch of the connections. Keep the wiring short to avoid noise.
-
Motor driver to Arduino
- ENA → PWM pin 9
- IN1 → digital pin 8
- IN2 → digital pin 7
- ENB → PWM pin 10
- IN3 → digital pin 6
- IN4 → digital pin 5
-
MPU‑6050 to Arduino (I2C bus)
- VCC → 5 V
- GND → GND
- SDA → A4
- SCL → A5
-
Power
- Connect the battery’s positive to the motor driver’s VCC and the Arduino’s VIN.
- Ground of the battery, motor driver, and Arduino must be common.
Double‑check the polarity of the motors; swapping them will make the robot spin the wrong way when you try to balance it.
The Code – Step by Step
Below is a minimal sketch that reads the angle, runs a complementary filter, and drives the motors with a simple PID controller. I keep the comments short so you can follow along without getting lost.
#include <Wire.h>
#include <MPU6050.h>
MPU6050 mpu;
// PID constants – you will tweak these later
float Kp = 30.0;
float Ki = 0.8;
float Kd = 0.5;
float setpoint = 0.0; // target angle (upright)
float angle = 0.0;
float error = 0.0;
float previousError = 0.0;
float integral = 0.0;
float derivative = 0.0;
float motorPower = 0.0;
const int ENA = 9, IN1 = 8, IN2 = 7;
const int ENB = 10, IN3 = 6, IN4 = 5;
void setup() {
Serial.begin(115200);
Wire.begin();
mpu.initialize();
if (!mpu.testConnection()) {
Serial.println("MPU6050 connection failed");
while (1);
}
pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
}
void loop() {
// ----- read raw sensor data -----
int16_t ax, ay, az, gx, gy, gz;
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// Convert to g's and deg/s (simple scaling)
float accelAngle = atan2(ax, az) * 180 / PI; // tilt from accelerometer
float gyroRate = gy / 131.0; // deg/s from gyroscope
// ----- complementary filter -----
const float dt = 0.01; // loop time ~10ms
static float filteredAngle = 0.0;
filteredAngle = 0.98 * (filteredAngle + gyroRate * dt) + 0.02 * accelAngle;
angle = filteredAngle;
// ----- PID controller -----
error = setpoint - angle;
integral += error * dt;
derivative = (error - previousError) / dt;
motorPower = Kp * error + Ki * integral + Kd * derivative;
previousError = error;
// ----- drive motors -----
int power = constrain(abs(motorPower), 0, 255);
if (motorPower > 0) { // tilt forward, move forward
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
} else { // tilt backward, move backward
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
analogWrite(ENA, power);
analogWrite(ENB, power);
// optional debug
Serial.print("Angle:");
Serial.print(angle);
Serial.print(" Power:");
Serial.println(motorPower);
delay(10);
}
Tuning the PID
When I first tried this code, the robot wobbled like a newborn deer. The trick is to start with a low Kp (maybe 10) and increase it until the robot reacts quickly but doesn’t overshoot. Then add a small Kd to damp the oscillations, and finally a tiny Ki to correct any steady‑state drift. Every chassis is a little different, so expect a few minutes of trial and error.
Putting It All Together
- Assemble the chassis – mount the motors, driver board, and Arduino securely. Keep the sensor near the robot’s center of mass for accurate readings.
- Upload the sketch – use the Arduino IDE, select the right board and port, and hit upload.
- Power up – turn on the battery. The robot should try to stand up on its own. If it falls, gently push it back and watch the serial monitor for angle values. Adjust the PID constants as needed.
A quick tip from my own workshop: place a small piece of foam under the wheels while you’re tuning. It gives the robot a little “cushion” and prevents it from crashing into the floor every time you overshoot.
Why This Project Matters
Self‑balancing robots are more than a cool demo; they teach you about sensor fusion, real‑time control, and the messy reality of hardware debugging. Those lessons translate directly to drones, exoskeletons, and even smart prosthetics. By building one with free sensors, you also learn to reuse parts responsibly—a value I hold dear at Arduino Innovator.
So, next time you see a robot cruising across a table, remember: the same principles are inside your kitchen drawer, waiting for a curious mind to bring them to life.
#arduino #robotics #diy
#selfbalancing #maker #electronics
- → Integrate AI Vision into a DIY Robot Arm: A Complete Step-by-Step Guide @robofrontier
- → Build a Low‑Cost Autonomous Delivery Robot for Your Home in 7 Simple Steps @robofrontier
- → Build a Voice‑Controlled LED Wall Panel with Node‑RED and Arduino @craftcodeacademy
- → DIY Low‑Cost Universal Joint for Your Robotics Kit @jointmechanics
- → How to Design and Print a Custom Enclosure for Arduino Projects Using Fusion 360 @techcraftworkshop