Mini Self-Balancing Robot - RasPi + Arduino

A two-wheeled, stepper-driven mini self-balancing robot using a Raspberry Pi Zero W and an Arduino-compatible Exen Mini microcontroller.

Similar projects worth following
The two-wheeled, self-balancing robot — a classic rite of passage for an aspiring roboticist!

At university, my entire mechatronics cohort were thrown into groups, each given an identical set of components, and told to build a balancing robot with them. In the end, perhaps two groups out of thirty were able to get their robot balancing. Unfortunately, I wasn't one of them!

We spent many hours in the laboratory, tuning the control system, adjusting circuits, rewriting code, to no avail. Worst of all, we couldn't seem to work out which part of the system was letting us down. After the class, I couldn't leave it at that. I needed the experience of seeing that cute little wheely-boy stand up, all on his own, for the first time. So I set out on my own quest to conquer the self-balancing robot challenge!

Watch it in action:

Choosing the features

I like to start a design by making some high-level decisions about what features it will have. There’s no need to be too specific at this point, we’re just setting our overall goals for the robot.

  1. Form. If we’re sticking with the classic self-balancing robot challenge, we’ll need two motorised wheels, one on each side of a frame — easy. We’ll make its body taller than it is wide, so it doesn’t naturally balance. Now that would just be cheating!
  2. Style. Let’s make this a small, cute balancing robot, roughly the size of a human hand. What would make it even cuter? A little LED emoji face, of course! And while we’re at it, we’ll give it a speaker so it can chirp at us.
  3. Function. If we’re going to take the time to make our own robot, we might as well give it a few extra functions on top of the basics. Let’s give it a camera and a microphone, so we can play around with autonomy later. And, just to be different, we’ll give it a pair of servo-powered forks, so it can pick up itty bitty things and carry them while balancing. What could go possibly wrong?

Once you’ve chosen your features, it wouldn’t hurt to do a couple of sketches to visualise what you’re creating. It’s easier to work towards the end goal when you can actually see what you’re aiming for. Plus it helps you think about part positioning

Finding the right components

With the concept in mind, we can now start speccing and picking our components. The basic bits we’ll need are a microcontroller (for low-level control of the balancing), a single-board computer (for the camera, microphone, speakers and high-level control), a battery, an inertial measurement unit (to measure the robot’s angle) and, of course, motors. There will also be a few standard components we’ll need like voltage regulators, motor drivers, etc, but we’ll get to that later.

As we go through each piece and identify the specific component we want, we should always remember to keep track of the communication protocols and power requirements we need. For example, if we pick an inertial measurement unit (IMU) that communicates with I²C and requires a 3.3V power supply, we need to ensure our microcontroller has I²C capabilities, and that our system provides access to a 3.3V power supply.

Getting specific and narrowing it down

To start with, we’ll decide on a battery to power our little friend. This will likely be the biggest and heaviest component, making it a good starting point for identifying requirements for the rest of the system. Looking for a battery with a good power density (low mass, high capacity), I came across a 2-cell LiPo from HobbyKing which will do the job nicely. It’s the right size, and will give us a constraint for the robot’s minimum width.

I decided to use stepper motors to drive the wheels, allowing precise control of the wheel speed without needing encoder feedback from a DC motor, or an additional control loop to maintain speed. We’ll use two little 12V geared stepper motors, two stepper driver boards and two step-up voltage converters to raise the battery’s 7.4 volts up to 12V.

The Pi Cam seems like a natural choice of camera, and we’ll pick up a little speaker, amplifier and an I²S MEMS microphone. For the face, we’ll use an 8×8 DotStar Matrix, and to power the forks, an SG90 servo. Lastly, we’ll go with an MPU6050 6-axis inertial measurement unit to track our robot’s orientation.

For the sake of keeping everything small (and cute), we’ll go with the Nerdonic Exen Mini for our microcontroller — a coin-sized, Arduino compatible board with a ‎Cortex M0+ CPU. It will talk to the motor drivers, the IMU and our single-board computer, for which we’ll use a Raspberry Pi Zero W. With such a big community around the Raspberry Pi, we’ll have a solid base to work from. Plus it’s a very compact computer that we can connect to wirelessly with WiFi and Bluetooth. We’ll also need a 5V voltage regulator to give us a consistent...

Read more »

MPEG-4 Video - 22.72 MB - 04/19/2021 at 10:27


  • 1 × LiPo Battery 2-cell, 950mAh
  • 1 × Exen Mini Arduino-compatible, Cortex M0+, I²C, UART
  • 1 × Pi Zero W WiFi, Bluetooth
  • 1 × 5V Regulator 1.5A, 2-16V input
  • 2 × Stepper Motor 12V, 0.18° per pulse, 0.6

View all 14 components

  • Designing an Even Smaller Balance-Bot

    Ben Steer05/03/2021 at 13:45 0 comments

    After reflecting on the first version of our mini self-balancing robot, I was wondering how I could improve the design and perhaps make it even smaller… We’re going to do an exercise in system design - which I love almost as much as creating robots - and come up with a plan for a balance-bot version 2!

    Heads up - this lil’ post contains some sponsored content from PCBWay.

    Changes in the New Design

    We’re going hard on reducing the mass of this bot; as a result, some of our components are going to change considerably. Let’s talk through the new design:

    • Chassis: We’re going to ditch most of the 3D printed parts that made up the body of the previous robot, and we’ll try to mount components directly to the PCB as much as possible. There may still be some 3D printed parts around the wheel assemblies, and the wheels themselves.
    • Minimal Features: I was overly ambitious with the previous robot, trying to add a camera, face, microphone and forklift (what a silly boy). We’re going barebones on this one and focusing on balancing, driving and turning nicely.
    • Surface-Mount PCB: Instead of the previous board, where we attached pre-made modules to our PCB using through-hole legs and headers, we’re going to have SMD mount as much as possible. The microcontroller(s) may still be mounted as modules, depending on how much work we want to put into the PCB design. Either way, this will reduce mass and let us make the board even tinier!
    • Raspberry Pi Swap-out: Instead of having a RasPi Zero, which is relatively big, we’ll go for a Wi-Fi capable microcontroller (MCU) that’s a bit more compact, like an Arduino Nano 33 IoT (which also includes a 6-axis IMU on board if we wanted to swing that way).
    • Steppers to DC Motors: Instead of our micro metal geared stepper motors (which weren’t quite beefy enough for the job), we’ll go with some brushed 6V DC motors with gearboxes and encoders, like these. This will require adding some motor controller elements to the PCB, instead of stepper driver modules. However, if we go with 6V, we won’t need 12V boost converters any more - we can draw power directly from the battery, or run them through some (relatively) high current voltage regulators.
    • LiPo to LiFePO4: Working with LiPo batteries makes me anxious lol - this time we’ll use a 2-cell LiFePO4 battery, which is less energy dense, but safer to work with.
    • Battery Indicator: It would be super handy to add a little array of LEDs to the board to indicate the remaining battery life. Last time, I had to wire and stick a little alarm board to the side of the bot, which was pretty annoying to do every time I swapped the battery out.

    The other elements of the balance bot will be similar to the original, including a dedicated MCU for balance control, 3D printed wheels, an IMU, and voltage regulators for the MCUs. Next, let’s figure out what this thing will look like.

    Physical Layout

    I’ve added a few sketches here for how I envisage the new robot being configured. Here you can see the general layout - the PCB is really the core structural element holding the robot together. Instead of having a plastic chassis with the battery mounted in an enclosure, we’ll have the battery mounted vertically on the back of the PCB with a very light frame to hold it in place. This means we can make the robot narrower, bringing the wheels closer together and reducing the overall dimensions of the robot. The motor and encoder assemblies will be mounted directly to the board with some 3D printed clamps/mounts and some pre-planned holes in the PCB.

    From the side view, you can see that the center of mass of the robot will be offset from center of the motor/wheel axes. We want the robot to be as statically stable as possible, which in our case, means it can nearly balance on its own if there is no outside influence. To help with this, the new design will allow the distance between the battery mount and the PCB to be customised, perhaps using some adjustable screws...

    Read more »

  • Project Afterthoughts

    Ben Steer04/20/2021 at 02:16 0 comments

    I thought I'd make a few comments about what I would do differently if I did the project a second time.

    • I would either use stronger stepper motors next time, or DC motors that are stronger than these. They were powerful enough to keep it balanced, but not enough to reliably drive around and steer. I do like the precision of the steppers and not needing encoders though.
    • Mount the wheels more rigidly, rather than relying on the precision of 3D printed holes. Or at least get a better 3D printer XD
    • As mentioned in the first post, I would triple check the PCB design for places where pullup / pulldown resistors are needed (I hate janking things onto PCBs after the fact).
    • Spend some time setting up a method of flashing code to the Exen Mini remotely. That would save a looooot of prototyping time in the long run.

  • Mini Self-Balancing Robot – Code & Run

    Ben Steer04/19/2021 at 10:32 0 comments

    In order to balance our little guy, we’re going to read in data from our inertial measurement unit (IMU), create a PID controller to catch the robot from falling, and write an accurate stepper motor controller from scratch. We’ll also read in commands from serial input, in order to tweak and configure our controller on the fly.

    I won’t give code snippets for every section of the program I’ve written, as that will make this post quite messy and detract from providing a concise overview. Instead, you can find my full program on my Github in the balance_bot repository, and refer to any code I mention here but don’t explicitly show. Keep in mind that some of the examples I give are simplified for clear explanation, so be sure to check out my Github if you want to implement something similar. Let’s get cracking!

    Measuring angles with an MPU6050

    The key piece of information we need to get our robot to balance, is the current pitch angle of the robot, which we’ll read from our MPU6050 IMU. To do this, I adapted some code from Jeff Rowberg’s MPU6050 library (as many do) for Arduino, specifically the MPU6050_DMP6 example. DMP stands for Digital Motion Processor, which is basically some circuitry in the chip which pre-processes the sensor values for us, meaning less work for us in the code.

    We take three main things from this example code. Firstly, some global variables which the program needs, namely the MPU6050 object, some flags, buffers, and vectors to store the sensor readings. You’ll find these defined in my code here. Secondly, we need to begin communication with the IMU and initialise the DMP unit, the code for which you’ll find in my setupMPU6050() function.

    Thirdly and finally, my loopIMU() function waits for an IMU reading to be available, and then calculates the robot’s pitch angle, storing it in a global variable called “pitch“. These measurements take less than 10ms to be available, meaning I’m able to call this function during each main loop and maintain it at a consistent 100Hz. This consistency is important for reliable control, which we’ll need, unless we want to see this guy on his face.

    One last thing. To make the angle reading as reliable as possible, you should run the IMU_Zero example in the MPU6050 library, following its instructions, in order to calibrate your specific chip. The output from this example program is a number of offset values, which you need to add to the setup code in setupMPU6050(), in the following section:

    // Accelerometer and gyrometer offsets.
    mpu.setXAccelOffset(-2947); mpu.setYAccelOffset(-5297);

     The values currently there are specific to my chip, and likely will cause inaccuracies with your own, so be sure to calibrate! Now, let’s do something with this angle.

    PID control

    If we want our little guy to stay upright, we’ll have to command his wheels to turn in such a way that he maintains an angle of about 90 degrees. A common control method used to address this is a PID controller, which we’ll use here. I won’t go into much detail about it, but essentially it uses the error between the desired angle (the setpoint) and measured angle (the observation), the accumulation of that error over time, and the rate of change of that error, in order to send commands to the wheels (the control signal).

    This might sound like a mouthful, but a basic implementation doesn’t require much code at all. I implemented it with a handful of global variables and a function, but I’d recommend using a struct (similar to a class in C++), or creating/using a library to keep things cleaner. It can be valuable to write it yourself, or at least see how someone else’s library works, in order to learn how it works, and perhaps to make sure it doesn’t have too much overhead for low-latency applications like this.

    The following snippet shows the core parts of my PID controller:...

    Read more »

View all 3 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates