First Robot -- Successfully Failed
What I Was Building
A self-balancing two-wheeled robot โ the kind that looks like it should fall over but doesn't. This was my first attempt at one, and I went in with a clear philosophy: just get it working. It doesn't need to be perfect. All I need is to learn and know how I'd improve another iteration.
There are four motor types I want to get hands-on with โ brushed DC, servo, stepper, and brushless DC โ in roughly that order. Each one teaches you something the next one builds on. Brushed DC was the natural starting point for this build.
The Parts I Chose (and Why)
Motors: Pololu 25D brushed DC motors with encoders. I'd used brushed DC before on a Lego chassis car, so the fundamentals were familiar. I went with Pololu specifically because they publish full specs and the motors have a built-in gearbox โ worth a small premium over the Amazon alternatives where half the listings have no usable specs. I wasn't sure if the encoders would be useful, so I splurged on those too
IMU: A budget MPU-6050. Cheap accelerometer + gyroscope combo. The catch: neither sensor is clean on its own โ you have to fuse the two signals together to get something stable. More on that in a minute.
Everything else: ESP32 as the brain, 3 ร 18650 cells for 12v power, a 3D printed chassis I designed myself in Fusion. This was my first complete, fully-designed 3D printed project โ from blank CAD file to working robot.
PID Tuning
Getting the robot to balance meant tuning a PID controller โ the algorithm that decides how hard to correct based on how far off-balance the robot is. The setpoint is simple: 0ยฐ, perfectly upright. The controller reads the current angle from the IMU 20 times per second and drives the motors to close that gap. Tune it too aggressively and the robot oscillates wildly; too conservatively and it topples. The three PID values interact with each other, so finding the right combination takes a lot of trial and error to tune well
The problem: every time I wanted to try new values, I had to edit the firmware, compile it, and flash it to the ESP32 over USB. Each iteration took about a minute. I was doing this dozens of times a day โ and eventually I snapped the USB port clean off an ESP32 from plugging and unplugging it so many times.
That was the push I needed to do it properly. The ESP32 has built-in WiFi, so on boot it now connects to a small Flask server running on my laptop. The server has a simple web interface where I can set PID values and save them. The robot fetches the latest values at startup โ no USB, no recompile, no reflash. Iteration time went from ~60 seconds down to about 10. That kind of feedback loop makes a huge difference when you're tuning by feel.
It Actually Worked
The robot balanced. I was pretty happy about that.
The problem was the way it balanced โ a constant rapid clicking back and forth, like it was vibrating in place rather than standing still. Not smooth. Not what I had imagined.
The culprit: deadband in the brushed DC motors. There's a small zone around zero speed where the motor doesn't respond โ it takes a small burst of power before anything moves. For a car driving in one direction that's fine. For a balancing robot that needs to make dozens of tiny corrections per second, it's a nightmare. The robot was overcompensating, then overcompensating the other way, over and over.
Making things worse: all that motor vibration was feeding noise directly into the IMU, making the balance signal even sloppier. The sensor fusion between the accelerometer and gyroscope helped โ that was one of the more interesting problems to solve โ but it could only do so much.
Knowing When to Stop
I could have kept digging โ tried different brushed DC motors, tuned the deadband compensation (ok, I tried that a lot). But eventually I threw in the towel.
But I'd already learned what I came to learn:
- How to tune a PID controller
- How to run an IMU in a high-speed feedback loop
- How to do sensor fusion between an accelerometer and gyroscope
- How to design and print a functional chassis from scratch
- That brushed DC motors have real limitations for this kind of task
The motors were the bottleneck. I knew brushless motors were on my list anyway โ more interesting, more capable โ so I called it and moved on.
What's Next
Robot arms. Specifically a 4DOF arm โ a completely different kind of challenge.