Self-balancing robot with LEGO SPIKE Prime

Janislav Jankov
4 min readSep 19, 2020

--

So you got your hands on a LEGO SPIKE Prime kit and wonder what to build next? How about a self-balancing robot?

In this tutorial I’ll show you step by step how to build a self-balancing robot using PID controller, no prior knowledge required!

What you’ll need

These are the parts I used. You’ll definitely need the hub, two motors with wheels, and many small black connectors. Everything else you can improvise.

Building the body

Before you start, a few things to consider when building the body:

It’s tempting to have the hub as close to the ground as possible, but the very low center of gravity is not a good thing here. Think of balancing a stick on your palm.

Also you don’t want the hub to be too high either — it will fall many times, trust me!

Here’s how I built it.

Assemble the wheels

Build motor frame

Attach the motors to the hub

Add brackets and bumpers — totally optional

All this falling and shaking (you’ll see!) got me wondering if the battery can become loose, so I decided to secure it with brackets.

I also added “bumpers” to protect the cables when the robot falls by creating space around them. Plus, it looks cooler in my opinion.

Fully assembled 🎉

Here it is, ready to balance.

We can access all of the buttons! But, unfortunately, to charge the battery, you’ll have to remove one of the motors 😬

Note that the motor on the side of the main button is connected to port C and the motor close to the Bluetooth button is connected to port D.

Code

SPIKE supports Python so implementing a PID controller was straightforward except for measuring the time between actions. Because SPIKE actually uses MicroPython, time.time() returns seconds as an integer (see link), which is a bit of a problem as we need to take actions with sub-second granularity. Luckily we can use time.ticks_ms() and time.ticks_diff() which allow for sufficient precision.

Here’s the full code together with tuned parameters KP=10, KI=120, KD=0.1 , which work well on yoga mats 😀 For hard surfaces, the values KP=8, KI=120, KD=0.05 seem to do the trick.

There are few things worth highlighting. I use MotorPair to control the motors together using start_at_power vs start. Also, because the power (and speed) is an integer, setting it requires rounding (line 66), which I suspect is one of the reasons why the motors run a bit choppy. Probably another reason is that the angle is also an integer 🤨 Put these two together and we can’t get smooth reactions.

Running

When you start the program, hold the hub upright. After a couple of seconds of initialization, the hub will show ☑︎ and you’ll have to release it as it will start balancing right away.

The actual balancing loop will run (line 60) until the roll angle exceeds the predefined value of 50 degrees (or goes below -50 degrees). At that point the hub will show the ☒ symbol.

Tuning

I’ve provided the tuned parameters, but part of the fun is to experiment and tune the robot yourself. A word of warning however — PID controllers are a bit of pain to tune.

PID Controller diagram (from https://en.wikipedia.org/wiki/PID_controller)

I experimented with manual tuning and following the Ziegler-Nichols method. And while Ziegler-Nichols worked, it did require some analysis of the results and overall I didn’t find it much easier to implement than the fully manual tuning.

To manually tune, you first start with the proportional response term (KP), keep KI and KD equal to 0, and increase KP until the robot starts to oscillate. For me, the value of KP with very obvious oscillations was around 20.

Then, set the value of KP to half of what you found before (i.e. 10) and start increasing KI while keeping KD set to 0. The goal is to find a value where the robot gets upright pretty fast. You can try 50, 70, 100, 120, etc.

Once the robot keeps balancing and reacts pretty quick but is oscillating a bit you can tune the KD parameter. Start with really low value like 0.05 and increase with increments of 0.05 or 0.1.

That’s it!

Enjoy

Isn’t this mesmerizing?!

Next steps

I find the manual tuning fun in small doses but it can get pretty annoying. I’m looking for how to automate the tuning — there are algorithms developed to do this, so I plan to give it a try. Stay tuned!

--

--