The Balancing Robot

Now avaliable as a kit
A balancing robot kit is now avaliable via Kickstarter: Check out the blog post as well:

Hello everybody
I have for a long time wanted to build a remote controllable balancing robot aka Segway – that’s was actually the main reason why I created the PS3 Bluetooth Library both for Arduino and the FEZ Devices. It has been a long time since the sneak peak and the performance has been improved a lot since then. The original one had a FEZ Rhino as the main processor, but I discovered that it was not fast enough to read the encoders, as it is not running embedded code. Also I was already using more than 10ms per loop, which I used as a fixed time loop, so I decided to step up a notch and go for a much more powerful device: the mbed microcontroller, which is an ARM Cortex-M3 running 96MHz.

It might have been possible with just a normal Arduino (NB: I have now ported the code to Arduino, see update for the code), but I didn’t want the speed of the processor to be an issue, so I decided to go for the mbed. The robot also features an Arduino Duemilanove with a USB Host Shield on top running a sketch based on my PS3 Bluetooth Library. The mbed board actually has USB Host functionality, but I decided not to port the PS3 Bluetooth Library as my original thought were to use an Arduino Due, but as you might know it hasn’t been released yet, despite the Arduino team announced, that it would be released by the end of 2011. But as soon as it is released I think I will port the code to it instead.

Video Demonstration
Here is a short video demonstration of the robot and me explaining some of the concepts of the design and how it works:

The Hardware
Here are some pictures of the robot:

Here is a list of all the hardware I used:

I also used:

The robot itself is made of three pieces of 215x75x7.5mm MDF wood and four threaded rods. The distance between the plates is 7cm at the bottom and 7.5 at the top. In total the robot is 27cm high including the battery.
See the 3D model for more information.

3D Model
I have created a 3D model in Autodesk Inventor with true dimensions, this will hopefully inspire other people for there robot design. All files can be found at github.
The 3D model can also be viewed at the following site:

Check out these rendered images of the robot:

The Code
All the code and 3D model can be found at our github. Here is a list of hyperlinks for all the repositories:

Also check out the wiki.

I have now ported the code to Arduino. The code can be found at github:

I have thought about how I could improve the performance of the robot. First of all I could try to use an accelerometer with a smaller resolution, as the one I got is a ±3g and ±1.5g would be sufficient for my needs. Also my gyro got a resolution of ±300 deg/s and I have seen people use gyro with a resolution as low as ±50 deg/s.

Another aspect would to use belts to minimize backlash, instead of connecting the wheels directly to the motors – a bit like this one.

Also I don’t compensate for the battery level in the code – so it behaves differently depending on the battery level.

Overall I am really happy about the end result – it balances pretty well and the remote control works perfect!

It has been a really good learning experience for me and a really fun project to do, but also very time-consuming – I have spend many nights tweaking the PID values and adjusting tiny bits of the code before I accomplished the end result.

The next step would to build a full size one, but I don’t know if I will do it the near future – but hopefully some day 🙂

That’s all for now. Hope you like my robot. Feel free to post a comment below and I will answer as quickly as possible.

  1. nela
    March 20th, 2015 at 16:04 | #1

    On the website I can read:

    3.2 Faster GPIO performance on shield pins IO0-IO6 and IO9-IO13

    GPIO functionality on these shield pins is provided directly by the Quark X1000. Accessing these pins through the standard Arduino API functions digitalWrite() and digitalRead() allows a sketch to toggle these pins at a frequency of approximately 390 kHz. This performance capability was available on the original Galileo, but only on digital shield pins IO2 and IO3, and only when OUTPUT_FAST pin mode was selected for those pins.
    For even better performance, the following Galileo-specific API functions may also be used:

    fastGpioDigitalRegWriteUnsafe(id, mask)

    So is 390khz with normal digitalWrite fast enough?

  2. March 23rd, 2015 at 23:44 | #2

    You basically increase Kp until it oscillates, then decrease it a little bit. Then increase Ki until it oscillates slowly. Finally increase Kd a little bit to dampen the system. Then increase Kp a little bit. Continue until it can balance.

    It’s hard to say what is “fast enough”. Try to print out your loop time. If it get’s above 10ms, then I would be worried if I were you.

  3. nela
    March 24th, 2015 at 13:16 | #3

    My loop time is about 9ms. I’ll try tune the pid some more. Thank you for your advices. I have one more question. Could you please upload a video of your robot while oscillating? I think it would help me a lot (maybe not even me, but many other people fighting with pid 🙂 ) Thank you

  4. March 24th, 2015 at 16:07 | #4

    No I can’t do that at the moment, as I have actually borrowed my robot out to a friend.

  5. nela
    March 27th, 2015 at 22:32 | #5

    hi, I think I discovered one problem. I set my setpoint to -0.60 where the centre of gravity is. With only P term everything’s ok. Motors don’t move at the setpoint. But when I add K term, my setpoint moves a little in one direction. It’s about at 9 degrees and at that point motors stop moving. The robot behaves like 9 degrees was its setpoint, not -0.60. Do you know what could cause that? I’m confused….

  6. nela
    March 28th, 2015 at 01:16 | #6

    * sorry I meant integral not “K”

  7. nela
    March 30th, 2015 at 21:41 | #7

    Nevermind, I found out why it’s like that.
    What I know there has to be a problem in my complementary filter.
    You said about the accelerometer calibration. I did the very simple one with the gyro, but it doesn’t work with the accel. You can check it on the code I sent you. When I do the same thing with accel like:
    accX = (ax -- avgAccX)/ACCEL_FACTOR;
    accY = (ay -- avgAccY)/ACCEL_FACTOR;
    accZ = (az -- avgAccZ)/ACCEL_FACTOR;
    I get weird results.. Without it, complementary filter seems to be ok. Do you know how can I make the same simple calibration for accel? I know you used the kalman filter, but maybe you know how to program complementary filter?
    ps. the code you showed me with accel calibration.. I guess it’s perfect, but I am not a professional programmer (yet! haha 😀 ) and I don’t really understand what have you done there.
    I look forward to hearing from you. Thank you so much.

  8. March 31st, 2015 at 15:11 | #8

    I recommend you take a look at the calibration routine for the Balanduino: Btw have you connected the encoders or not?
    I don’t have time to adapt it to your code, sorry.

  9. nela
    April 1st, 2015 at 20:21 | #9

    Well, I tried to do calibration for the accelerometer, but with no success. I got NaN from the complemetnary filter or weird values. Without the accelerometer calibration the values were ok, but delayed. I found out that the complementary filter gave me a lag. There was a noticable delay which affected the control. It took few seconds(?) for robot to realize that it’s not in a balanced position and then it was too late. I could do anything, but I couldn’t get rid of that delay. I started to use DMP library and the problem dissapeared. There is no delay, robot reacts immadiately. Did you had that delay with the kalman filter? Maybe kalman is more accurate? Thank you for your time and help.

  10. April 4th, 2015 at 12:19 | #10

    No I did not have that problem with my Kalman filter.

  11. Ahmed Zak
    April 7th, 2015 at 12:12 | #11

    Hi, I wanted to know how many external interrupts are you using? I am using the Uno with Pololu motors (with encoders) and MPU6050. I also plan on using a bluetooth module for remote control later on. This required me to have 3 external interrupts right? But the Uno only has 2.

    Is there anything I can do about this?

  12. April 7th, 2015 at 12:17 | #12

    @Ahmed Zak
    No the original code only uses two, but the Balanduino just uses pin change intterupt, so you might consider using that instead. See: and

  13. Ahmed Zak
    April 7th, 2015 at 12:24 | #13

    @Kristian Lauszus
    Ok i’ll look into this. Thanks for the quick reply. Your code helped me a lot! Save me many hours of despair and also helped me learn many things. Peace.

  14. nela
    April 11th, 2015 at 19:25 | #14

    Hi Lauszus,
    I got it working! 😀 My robot balances now pretty well. Thank your for all your help!

  15. April 14th, 2015 at 15:16 | #15

    You are welcome 🙂 Glad to hear you got it working!

  16. ali
    April 20th, 2015 at 17:19 | #16

    dear lauszus

    i am making a self balancing robot using arduino mega ,mpu6050 and polulu’s 30:1 12v 350 rpm motors with encoder, i am using jeff rowberg library for mpu sensor to get pitch values, the data from mpu comes on interrupt pin which is triggered when fifo buffer has a value , i want to know how can i read encooders using interrupts, because everytime i use ISR for encoders i get false values which i do understand because arduino is already busy on mpu data interrupt ,

    pls help me


  17. Greg
    April 21st, 2015 at 18:28 | #18

    I just had a question about how you implemented the PID loop onto your robot. I have built a robot very similar to yours and I do have it balancing. To do this, I have two PID loops. One varies the angle on which to set the robot to which is determined by how far away from zero the wheels have moved using encoders and the other PID loop gets the robot to that determined angle. Mine is not quite as stable as yours however. Is this similar to how you have set your PID loops up or have you taken a different approach?

  18. April 21st, 2015 at 23:16 | #19

    Yes that is the same approach I have used. Can you share your code somewhere, then I will have a look at your code 🙂

  19. Mansor
    April 23rd, 2015 at 12:35 | #20

    Hi Lauszus,

    Any chance porting the code to Due?

  20. April 24th, 2015 at 21:33 | #21

    No unfortunately that is not something I will be working on in the near future.

  21. arpit
    May 6th, 2015 at 14:13 | #22

    hi lauszus, ur robot balances very well …. great work.
    1.I would like to know can the same robot balance for polulu’s 19:1 12v 500 rpm motor with encoder…??
    2. what was ur pwm value and how to adjust pwm value for 500rpm motor…

  22. May 6th, 2015 at 14:15 | #23

    It possible will, but why not just use the same ones as I used?

    You will have to tune the PID controller, so it works with your motors.

  23. arpit
    May 7th, 2015 at 05:19 | #24

    @Kristian Lauszus
    i will tune the pid controller…because my robot is heavier some what larger in size than urs …. so for my application those motor were suitable…
    by the way thanks for ur suggestion.

  24. May 7th, 2015 at 18:11 | #25

    I would have recommended motors with more torque if it is heaver i.e. a higher gear ratio.

  25. arpit
    May 13th, 2015 at 03:43 | #26

    hi kirstian,
    how did u tune ur PID values so precise ??did u used some software or just by trial and error?

  26. arpit
    May 13th, 2015 at 04:01 | #27

    i would also like to know if the robot balances pretty well using arduino or it balances more precisely using mbed controller and arduino as u have mentioned on ur blog….thanks

  27. Bill Parker
    May 15th, 2015 at 22:47 | #28

    Hi Would it be practical to use this to control a full size self balance ridable 2 wheeled Segway type of transport? Or do you know of anything that might help me I have trouble walking and thinking this may help.

  28. June 7th, 2015 at 15:06 | #29

    I tuned them manually. Start by setting all value to 0, then increase Kp until it starts oscillating, then turned it down a little. Then start increasing Ki until it starts oscillating, but this time the period should be longer. Finally you can increase Kd to dampen the system.

    The performance is the same between the two systems.

    @Bill Parker
    Please see the following blog post:

  29. Rodrigo
    June 17th, 2015 at 22:43 | #30


    I am little puzzled by the way you implemented: (1) the control to reduce the target angle at high velocities and (2) the control to return to the stop position. A more intuitive approach would have been to use standard PID loops for each. For example in the ?non-stop? condition a PID finds the target angle (restAngle) based on the velocity error (difference between the desire velocity and the actual velocity). In the ?stop? condition a PID finds the target angle (restAngle) based on the distance away (encoder counts) from the stop position. Does this make sense? Did you try an approach like this instead? If yes, what was your experience? If not, why not? Any suggestions?

    Thank you,


  30. June 20th, 2015 at 15:21 | #31

    You should check out this branch of the Balanduino repository: where I have experimented with just that, but I never got it to work properly.

  31. Ryuoh
    June 28th, 2015 at 05:23 | #32

    Hi Lauszus
    I’m making balanced robot now but no matter how I tune PID parameter it can’t be balanced
    it swing like this

    I use pololu 50: gear motor with encoder
    robot weight is around 1.5 kg
    can you give me some advice

  32. June 30th, 2015 at 00:57 | #33

    I have replied to your Facebook message 🙂

  33. Siddhant
    July 16th, 2015 at 06:19 | #34

    Hi Kristian,

    Thanks for the great guides you have posted all over the internet and for regularly replying to posts here! There’s a lot to read and I’m hoping I’ll be able to solve most of my troubles during my quest for balance by reading posts from this blog.

    I do have one problem that I cannot seem to solve though. When laying flat on a table, the sensor shows 180 degrees but when I roll it to a vertical position moving it by 90 degrees, the serial monitor does not show a value of 90. It shows 90 degrees at a position that is clearly not 90 degrees. How can I go about fixing this?

    Thank you!


  34. July 16th, 2015 at 07:34 | #35

    You need to calibrate the accelerometer. This can be done by finding the accelerometer values when the robot is horizontal and then subtracting the values from any further measurements. See:

  35. Larry McGovern
    August 23rd, 2015 at 16:47 | #36

    Hi Kristian, your website has a wealth of data, and was a huge source of inspiration for my own balancing robot “Zippy”. Here’s my homage to your project: You may notice one or two design similarities… Thanks for making all this publicly available! I’ll be watching your site.

  36. August 23rd, 2015 at 23:15 | #37

    @Larry McGovern
    Looking good 🙂 How is your experience with those wheels? I might try something similar at some point.

  37. Larry McGovern
    August 24th, 2015 at 01:48 | #38

    @Kristian Sloth Lauszus
    I think the scooter wheels are great, but I can’t say I have any experience with other wheels. They work just as well on hard surfaces and carpet, and have a nice rubbery grip. I used a scooter wheel adapter from Pololu, which directly interfaces with a 6 mm diameter motor shaft. My daughter has wheels that light up on her Razor, which might also be a fun addition to a balancing robot…

  38. August 24th, 2015 at 19:58 | #39

    @Larry McGovern
    I guess you are talking about these ones: I might try them out. They must be relatively new, as I have not seen them in their store earlier.

    Haha yes it might be fun to try someone with flashing lights!

  39. YOBE
    August 29th, 2015 at 03:57 | #40

    Hi Kristian,
    Im also working on my balancing robot but facing problems with interrupt and I2C communication.
    I am using Chipkit, but once I create the high freq interrupts from the encoders, my I2C communication to the IMU is crashing and hangs the uc.
    Have you ever encountered something like this?

  40. mohamed siddik
    September 9th, 2015 at 11:50 | #41

    hi frd;
    i am siddik from india (TN). I am interested to do the self-balance robot. I done mobile controlled robot. I want to do this help me frd . I have Arduino uno, bluetooth transceiver module(hc-05) then two 5v dc motor .

  41. September 11th, 2015 at 08:27 | #42

    No I have not. Maybe it is a problem with your connections? Please try to solder the connections if you haven’t already. Also try to add some capacitors close to the regulators in oder to filter out the noise.

    @mohamed siddik
    Okay sounds good. What do you need help with?

  42. Geoffrey
    February 1st, 2016 at 21:48 | #43

    Hi Kristian,
    I had built my own self-balance robot and your website had been useful, thanks.
    However, I have some difficulties on the last stage: the PID tuning.

    In your method, what do you mean by “it starts oscillating” ? Does it stabilize already or does it only vibrate ?

    Then, can you give me some details about the reaction of the robot along the tuning ?

    Thank you !

  43. February 2nd, 2016 at 00:29 | #44

    It should start to oscillate or vibrate when the gains are too high. Simply increase them until to you reach this point and then decrease them until it stops.

  44. Pat
    February 22nd, 2016 at 21:05 | #45

    Hi Kristian,
    I have just finished my project and thank you for the inspiration.I have just received the mpu6050 in post today and my question is do i need to calibrate the mpu6050 offsets while the unit is off the robot and on a flat level surface or is this taken care of by the software.

    Thank You

  45. Patrick
    March 28th, 2016 at 05:51 | #46

    Great robot! Is this possible without a microcontroller? I have an raspberry pi, L298N stepper drivers, NEMA17 stepper motors, and an MPU6050 for the gyro.

    Before I get too far is the RPI not fast enough to properly calculate IMU dimensions and give the steppers a fine level of control?

  46. March 28th, 2016 at 08:20 | #47

    Hi Patrick.
    It is definitely possible to do with a Raspberry Pi as well, but as you say it would require some cautious Kernel modifications to enable Real time support to get the latency down.

    Please see the following links where the Raspberry Pi is used as a flight controller:

    Regards Thomas

  47. April 14th, 2016 at 23:15 | #48

    In my experience it is usually not needed, but in some rare occasions it is needed, but normally you can just adjust the target angle manually. I simply implemented the calibration algorithm for the Balanduino, so it would be easy for people to do it themselves.

    It is differently possible on a RPi, but as Thomas wrote you will need a real time support. If you are not that experienced with Linux I would recommend sticking with a simpler microcontroller.

  48. Pat
    May 26th, 2016 at 19:31 | #49

    Hi and thanks for your advise Kristian, one last question. My robot is up and running and am very happy with my build it balances very well and moves Forward and Backward great but the Left and and Right steering seems very nervous any suggestions what the problem might be would be very helpful.

  49. Jean
    June 16th, 2016 at 18:52 | #50


    Hey Krisitian,

    I’m having problems with tuning the PID, I’m not really following what do you mean by oscillating, whatever values I’m giving for Kp, the motors react fourth and back, so in every case they are oscillating. Could you please explain more, or maybe record a video while doing it?
    Thank you

Comment pages
1 10 11 12 13 2196
  1. No trackbacks yet.