Build a Self-Balancing Robot That Delivers a Package!
Meet Dash — a two-wheeled robot that balances upright all on its own, just like a mini Segway. Using an MPU6050 sensor and some clever motor control, Dash constantly corrects itself hundreds of times per second while carrying a small package on top.
📦 Say hi to Dash, your self-balancing delivery robot!
What Is a Self-Balancing Robot, Anyway?
Balance on two wheels sounds impossible without falling over — but Dash pulls it off using the same trick real hoverboards and Segways use. An MPU6050 sensor constantly measures how far Dash is tilting, and a control algorithm called PID instantly adjusts the wheel motors to lean back the other way — over and over, hundreds of times per second, keeping Dash (and its package) upright.
What You'll Need
Gather these parts before you start building Dash!
Arduino Uno
Runs the balancing calculations hundreds of times per second.
MPU6050 Gyroscope + Accelerometer
Measures how far the robot is tilting, moment to moment.
DC Gear Motors + Wheels
Drive both wheels to correct the robot's balance.
L298N Motor Driver
Lets the Arduino control both motors' speed and direction.
7.4V Battery Pack
Powers the motors — a taller, top-heavy build balances more easily.
Small Chassis + Package Platform
A narrow, tall frame with a small flat top to carry a package.
Breadboard
For connecting everything without soldering.
Jumper Wires
Male-to-male and male-to-female.
The Circuit Diagram
The MPU6050 and motor driver connect to the Arduino Uno — everything the robot needs to sense and correct its balance.
Step-by-Step Build Instructions
A tall, narrow build balances more easily than a short, wide one. Work with an adult on wiring and testing!
Build a tall, narrow chassis
Construct a frame that stands upright between the two wheels, with the battery and Arduino mounted up high — a higher center of gravity actually makes balancing easier, just like walking with your arms out.
Mount the MPU6050 sensor
Fix the MPU6050 as close to the robot's center as possible, mounted perfectly level — any tilt in how it's mounted will throw off the balance point.
💡 Tip: Use a small level or your phone's level app to check the sensor is mounted flat before testing!Attach the motors and wheels
Mount both DC gear motors symmetrically at the base, one on each side, with matching wheels — any mismatch will make the robot drift.
Add the package platform
Build a small flat shelf near the top of the frame, sized for a lightweight package like a small block or soft toy.
Wire the MPU6050 and motor driver
Connect the MPU6050's SDA/SCL to A4/A5, and wire the L298N motor driver to the Arduino exactly as shown in the circuit diagram.
Upload the code and tune the balance
Upload the code below, hold Dash upright, let go gently, and watch it try to balance. You'll likely need to adjust the PID numbers — more on that in the FAQ!
The Arduino Code
This code talks to the MPU6050 directly over I2C and uses a PID controller to balance. Copy it in, then click Upload.
// ⚖️🤖 Dash the Self-Balancing Delivery Robot — Arduino MPU6050 Robotics Project // Uses a complementary filter + PID control to balance on two wheels #include <Wire.h> const int MPU_ADDR = 0x68; float currentAngle = 0; unsigned long lastTime; // ---- Motor pins ---- const int leftIN1 = 8, leftIN2 = 9, leftENA = 10; const int rightIN3 = 7, rightIN4 = 6, rightENB = 5; // ---- PID constants — you WILL need to tune these for your own robot ---- float Kp = 22.0; float Ki = 140.0; float Kd = 0.8; float setpoint = 0.0; // the "balanced" angle — calibrate this for your build float integral = 0; float previousError = 0; void setup() { Wire.begin(); Wire.beginTransmission(MPU_ADDR); Wire.write(0x6B); // power management register Wire.write(0); // wake the MPU6050 up from sleep Wire.endTransmission(true); pinMode(leftIN1, OUTPUT); pinMode(leftIN2, OUTPUT); pinMode(leftENA, OUTPUT); pinMode(rightIN3, OUTPUT); pinMode(rightIN4, OUTPUT); pinMode(rightENB, OUTPUT); lastTime = millis(); } void loop() { unsigned long now = millis(); float dt = (now - lastTime) / 1000.0; lastTime = now; updateAngle(dt); float error = setpoint - currentAngle; integral += error * dt; float derivative = (dt > 0) ? (error - previousError) / dt : 0; float output = Kp * error + Ki * integral + Kd * derivative; previousError = error; driveMotors(output); } // Reads the MPU6050 and combines accelerometer + gyro readings into one angle void updateAngle(float dt) { Wire.beginTransmission(MPU_ADDR); Wire.write(0x3B); // starting register for accelerometer data Wire.endTransmission(false); Wire.requestFrom(MPU_ADDR, 14, true); int16_t accY = Wire.read() << 8 | Wire.read(); Wire.read(); Wire.read(); // skip accX high/low (not needed for this tilt axis) int16_t accZ = Wire.read() << 8 | Wire.read(); Wire.read(); Wire.read(); // skip temperature int16_t gyroX = Wire.read() << 8 | Wire.read(); float accAngle = atan2(accY, accZ) * 180.0 / PI; float gyroRate = gyroX / 131.0; // Complementary filter: trust the fast-but-drifty gyro short-term, // and slowly correct using the accurate-but-noisy accelerometer currentAngle = 0.98 * (currentAngle + gyroRate * dt) + 0.02 * accAngle; } // Converts the PID output into motor direction and speed void driveMotors(float output) { output = constrain(output, -255, 255); int speed = abs(output); bool forward = output > 0; digitalWrite(leftIN1, forward ? HIGH : LOW); digitalWrite(leftIN2, forward ? LOW : HIGH); digitalWrite(rightIN3, forward ? HIGH : LOW); digitalWrite(rightIN4, forward ? LOW : HIGH); analogWrite(leftENA, speed); analogWrite(rightENB, speed); }
How Does Dash Actually Work?
Here are the big robotics ideas hiding inside this project:
Combining Two Imperfect Sensors
The gyroscope reacts instantly but slowly drifts off over time, while the accelerometer is accurate but jittery. The complementary filter blends them so Dash gets the best of both.
PID: Three Kinds of Correction
Proportional reacts to how far off balance Dash is right now, Integral fixes small lingering leans over time, and Derivative slows things down before Dash overshoots — together they make smooth, stable corrections.
Speed Matters
This whole loop runs continuously, checking and correcting many times per second — balancing only works because the corrections happen faster than Dash can actually fall over.
Tuning Is Part of the Build
No two robots balance the same way — differences in weight, motor strength, and sensor mounting mean the Kp, Ki, and Kd numbers almost always need adjusting by trial and error.
🧑🔬 Safety First!
- Build and tune with an adult — early PID testing often involves a wobbly, falling robot before it's dialed in.
- Test over a soft surface or with your hands nearby to catch Dash during tuning.
- Keep fingers clear of the spinning wheels while powered on.
- Use only small, lightweight packages — an overloaded top platform makes balancing much harder and less safe.
- Double-check all wiring before powering on, especially motor driver connections.
Frequently Asked Questions
How do I tune the PID values if my robot won't balance?
Start with Ki and Kd at 0, and slowly raise Kp until Dash starts to wobble back and forth on its own. Then slowly increase Kd until the wobbling settles down, and finally add a small amount of Ki to fix any steady lean to one side.
Why does the setpoint need calibrating?
No robot is built perfectly symmetrical, so the angle where it's actually balanced might not be exactly 0°. Test different small setpoint values until Dash stays upright without constantly drifting one way.
Can I make Dash drive forward while balancing?
Yes! Add a small offset to the setpoint temporarily — leaning the target angle slightly forward makes Dash "chase" that lean, which moves it forward while still balancing.
What age group is this project good for?
Because it involves real control theory and a good amount of tuning, this is an advanced project best suited for kids around age 12+ working closely with an adult.

Comments
Post a Comment