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. March 5th, 2012 at 03:25 | #1

    Excellent work! I’ve been working in a similar robot since july of 2010, but after a few setbacks I starter working on it again last year. I also decided to use mbed due to the speed. I previously used the PIC18F46K20. you can see some photos of my robot here

  2. Lauszus
    March 5th, 2012 at 10:12 | #2

    So far it looks pretty good. But I think your wheels are a bit to small. Originally I used these wheels from Pololu: They worked okay, but I got much better performance by buying these wheels: The reason why, is because the robot needs torque to stay balanced and not speed and those big wheels help doing that. Of course it depends on your motors, but those wheels worked better for me.
    What motors are you using right now? 🙂

    -- Lauszus

  3. March 5th, 2012 at 18:46 | #3

    @Lauszus Yes, I originally planned to use bigger wheels too, but a few distributors ships to my country, and if they ship stuff, the prices are very high. Now robotshops does not have them in stock, so I’ll have to wait a little more. I’m using these motors: they do not have encoders, but I think I will test how they perform before buying new motors with encoders. =D

  4. Lauszus
    March 5th, 2012 at 21:02 | #4

    It’s the same here in Denmark, that’s why I chose a european distributor. I also had to wait more than two weeks before they were even shipped.
    Okay. I really recommended getting some encoders as they provided the stop functionality and also made the robot stay in one place all the time.

  5. Lucky
    March 8th, 2012 at 05:52 | #5

    I bet balancing needs power. While balancing when not moving around may have its advantages, Why not make a couple of automatic “bike stands” that engage when desired speed is 0?

  6. Lauszus
    March 8th, 2012 at 09:40 | #6

    I see what you meen, but don’t you take all the fun out of it if you just put some wheels on it. Then you could just have made a four wheeled robot to begin with.
    Anyways it can actually run for several hours with a battery fully charged.

  7. Kas
    March 8th, 2012 at 10:26 | #7


    Beautifull implementation, congratulation
    Your bot balances pretty well

    I would like to test the Banebots wheels, please confirm you ordered “2 wheels wide” hubs
    as per
    why not “One wheel wide” hub ??

    Keep up the good job

  8. Lauszus
    March 8th, 2012 at 11:28 | #8

    Thank you.
    Yes that was exactly the hubs i ordered, see the hardware section above for all the information about the hardware that I used.
    The reason why I choose the “2 Wide” version, is pretty simple. Because the wheels are 2 wide (they are in the “series 800”). BaneBots got there own system, so it’s possible to mix up different kinds of wheels -- you could for instance mix up three types of wheels on a 3 wide hub.
    Take a look the this page: at “NOTE”. I also though it was very confusing, regarding to which hubs fitted which wheels, so I actually emailed robotshop asking if they were the right hubs for those wheels.

    I got to ask you. Are you the same Kas that created “Balancing robot for dummies”: You post on the Arduino forum, where the main reason why I choose the motors, brackets and motorcontrollers. I have wanted to thank you, but didn’t know if you’re still active in the balancing robot community 🙂

  9. Cosmin
    March 8th, 2012 at 22:20 | #9

    nice work

    I tried to test the library but I get stuck at:
    Bluetooth Dongle Connected
    CSR Initialized
    HCI Reset complete
    Local Bluetooth Address: 00:09:DD:50:07:7D
    Wait For Incoming Connection Request

    the 4 leds on the DualShock 3 flash constantly but it does not connect
    what could be the problem?


  10. Lauszus
    March 8th, 2012 at 23:06 | #10

    You have to set the bluetooth address into the PS3 Controller first. Try to first to plug in the dongle, then unplug it and then plug in the PS3 Controller. It should then work fine. Or simply just change the following: to your bluetooth address and the you don’t have to plug in the dongle before you plug in the PS3 controller.
    See the wiki for more details:


  11. Kas
    March 9th, 2012 at 08:42 | #11

    Thanks for the clarification, the RobotShop informations are reallly confusing
    I will order those wheels right away

    I now realize that my PID/encoder/motor code is far from perfect
    Did you implement the Arduino version of your code ??
    I would love to test it on my bot

    Kas, the genuine one 🙂

  12. Lauszus
    March 9th, 2012 at 10:28 | #12

    Your welcome -- yes it is very confusing.
    I don’t know if I had the right approach, but it seemed more intuitive to adjust the target angle instead.
    What do you mean by the Arduino version of my code? 🙂 I only used the Arduino for the bluetooth functionality. It’s the mbed that drives the whole thing. But I think you could easily port it to an Arduino, as I only use about 1ms when not receiving any serial data.

    Thank you again for you great guide. It were a big inspiration to me.


  13. Kas
    March 9th, 2012 at 18:09 | #13

    My pleasure

    Well… I mean your mbed code ported to Arduino 😉
    I am especially interested by the void PID(double restAngle, double offset) function
    Would you mind explaining this part of your code ??


  14. Cosmin
    March 9th, 2012 at 22:29 | #14

    finally it works,
    I had 2 problems
    put the mac addres of the dongle in the dualshock3, I used

    the usb shield and the dongle use more power than the arduino supply from the usb
    so needed to connect an external power supply.


  15. March 10th, 2012 at 07:15 | #15

    That is a awesome robot, I have been thinking about getting into walker robotics myself. Any pro/con to wheels that I should take in note?

  16. Lauszus
    March 10th, 2012 at 12:04 | #16

    Okay. Glad you succeeded. I have never had any issues setting the bluetooth address.

  17. Lauszus
    March 10th, 2012 at 12:07 | #17

    @Mads Barnkob
    Thank you.
    I recommend those wheels that I bought, as they are really good quality. Remember that they should be a bit heavy, as it’s torque that keeps it balancing not speed, so don’t go for any tiny wheels. Originally I bought these wheels from Pololu:, but they where not as good as the BaneBots one.

  18. Lauszus
    March 10th, 2012 at 12:26 | #18

    Okay I will give it a try:

    The restAngle is a constant (90 degrees), I only adjusted it before I implemented the encoders, as they keep adjusting the angle, so it remains in the same position.
    The forward and backward commands including the targetOffset, are sent from the Arduino via serial. See this line:
    But if you just set the offset to for instance 5 degrees, it will eventually fall over, so to avoid this, I adjust the offset depending on the wheel velocity. This can also act as an break, as if the wheels are going forward and you set the backward command, the target offset is actually getting bigger than the values being sent.

    The stop function is a bit different. At first there is three zones -- this will slow it down again, when reaching the targetPosition. It adjust the restAngle, so it moves to the right position. At last I have also implemented the wheel velocity. It’s main purpose is to keep it in the same spot. In short the positionError force it to go to a certain position and the wheelVelocity keeps it there.
    At last I limit the restAngle angle, so it doesn’t overreact when the error is great. Think of it as the constrain function for the Arduino.

    The next step is just a normal PID controller. The pTerm looks at the error, if it’s for instance 5 degrees it will multiply it by a constant, to make the error less. The problem is that this will make the robot start to oscillate -- this is what dTerm prevents: it looks at the difference between the last error and the error. So if the last error were 5 degrees, but the new error is 3 degrees, the diference is -2, so it will actually slow the robot down, when it’s reaching the correct angle. At last the iTerm will force it not to be satisfied until the error is zero -- this will also helps the robot from drifting, as if the error is for instance just 0.5 degrees, it would start to drift, if the iTerm values wasn’t there.

    At last I split up the PIDValue, and set and offset to it, if the Arduino sends an turn or rotate command. It will keeps balancing if you just set the exact same offset to the difference motors, as I explained in the video.

    Hope that answered your question fully 🙂 If not just send me another comment.

  19. Kas
    March 11th, 2012 at 08:21 | #19

    Thanks for the clarification, I was not too sure about velocityScaleMove and zone XX

    Now, my roadmap:
    -- Bot reengineering with IMU placed near the wheel axis and new “green” wheels
    -- Look for possible noise with a scope (tantalium capacity across motor leads)
    -- Add a PID per motor

    A PID per motor should correct individual behaviour and allow control based on velocity, not PWM.
    It should also give higher torque at low speed

  20. Lauszus
    March 12th, 2012 at 00:39 | #20

    Nice. Do you got a blog or anything like that, so I can follow your progress? 🙂

  21. zmiguelb
    March 12th, 2012 at 04:42 | #21

    Hi Lauszus,
    You blog is quite amazing, I stumbled upon it because I am building a similar robot to yours and although I have been able to implement everything so far I can’t seem to hit the correct PID values.

    Would it be possible for you to provide me with some insight how you calculated the PID terms.
    I’ve been through a lot of websites and most of them explain PID but not how to get there without a model (expect the Ziegler method).

    Any help would be appreciated 😀

  22. Lauszus
    March 12th, 2012 at 09:15 | #22

    I didn’t calculate the values -- it was more like trial and error. But I followed this guide: see page 42:

    1. Select typical operating setting for desired speed, turn off integral and derivative part, and then increase Kp to max or until oscillation occurs.
    2. If system oscillates, divide Kp by 2.
    3. Increase Kd and observe behaviour when changing desired speed by about 5% and choose a value of Kd that gives a fast damped response.
    4. Slowly increase Ki until oscillation starts. Then divide Ki by 2 or 3.

    I more or less followed that, but I then fine tuned it myself. I recommend using a wireless application, so you can set them wirelessly, as mentioned in the video, as you have to spend a lot of time finding those values.

  23. zmiguelb
    March 12th, 2012 at 13:20 | #23

    Thanks for the fast reply Lauszus.
    I will try that approach as soon as I get home. (Crossing finger hoping it will work 😉 )

  24. Kas
    March 12th, 2012 at 18:54 | #24

    No blog, will keep you informed

  25. Lauszus
    March 12th, 2012 at 18:55 | #25

    Okay, looking forward to see your robot in action 😀

  26. March 19th, 2012 at 19:45 | #26

    Hi Kristian,
    Cool, fun to see that there are more nerds and potential engineers around in Holstebro.
    It’s a really fine robot and some good choices as well.
    Niels Bo

  27. March 20th, 2012 at 21:34 | #27

    Are you still following the Arduino Forum Lauszus?

  28. Lauszus
    March 20th, 2012 at 21:56 | #28

    @Niels Bo
    Thank you Niels, nice to hear that from an engineer 🙂

  29. Lauszus
    March 20th, 2012 at 21:57 | #29

    Yes I’m stil following it, but didn’t have the time to check out the forum until now 🙂
    Your robot looks really nice (,60170.msg732345.html#msg732345), I have one comment though: on the picture it looks like you have put the IMU on second level of the platform -- you should put it just at the axis instead 🙂

  30. March 25th, 2012 at 10:04 | #30


    You’ve done a great job, the robot’s turning is very impressive and when it stops it stands absolutely still. Have you tried climbing down small steps with it? And does it go up a slope? If so, what’s the maximum inclination? What happens when you stop it on a slope?


  31. Lauszus
    March 25th, 2012 at 16:00 | #31

    Thank you, I’m also very pleased with it 🙂
    It can handle steps pretty good and slopes to, but I will not stay at the same position on a slope. You should lower positionScaleC and velocityScaleStop to make it do that, but it will also be more “aggressive” and make it vibrate more when standing still. See this line in the code for more info:
    I don’t know the maximum inclination, I will let you know if I ever measure it.

  32. March 29th, 2012 at 19:48 | #32

    Nice robot! I think you gave me the inspiration to continue with my both also. Now I half to start working on X-bot v3. (

  33. Lauszus
    March 29th, 2012 at 21:26 | #33

    It’s always nice to inspire people, I got inspiration from 🙂

  34. Lucas Ezequiel BLanco
    March 30th, 2012 at 23:48 | #34

    Very good work! THE FOLLOWING I ask, as you have done to adapt the controlardor 5v engine to 3.3 mbed plate. Thank you very much for your respusta and sorry for the translation because I do not speak English and I do it with google translator travez

  35. Lauszus
    March 30th, 2012 at 23:57 | #35

    @Lucas Ezequiel BLanco
    The motors are not running 5V, if that what you asked about, they run at 12V, but the motorcontroller will take care of this.
    I haven’t done anything to convert the logic from the mbed, they work just fine with a logic level of 3.3V.


  36. Patrick
    April 12th, 2012 at 18:13 | #36


    I just bought the exact same motors, wheels and hubs as your robot but I found that the hubs are a bit too large for the motor shaft (lenght wise).

    How did you solve this problem?


  37. Lauszus
    April 12th, 2012 at 19:03 | #37

    I didn’t. I just but mounted them as they were.


  38. Patrick
    April 16th, 2012 at 01:40 | #38

    Thank you,

    I realized that if I tightened them enough they wouldn’t move!

    Thanks again

  39. kas
    April 17th, 2012 at 20:17 | #39

    Hi Lauszus
    I just saw that you ported your code to the Arduino platform
    This is great for the Arduino community
    Did you allready physically test this code on your bot ??
    Do you get the same outstanding beheaviour as with the mbed implementation ??

  40. Lauszus
    April 17th, 2012 at 22:14 | #40

    Yes it’s running just next to me 🙂 The performance is just as good as on the mbed.

    I’m actually really impressed with the performance of the atmega328p -- every loop takes approximately 3ms, just as good as the mbed running 96MHz. But the serial receiving also takes a lot of time on the mbed, but the Arduino still have to run the USB Host communicating with the PS3 Controller.

  41. kas
    April 19th, 2012 at 17:52 | #41


    I looked at your sensor aquisition code and need some clarification:

    >> // (gyroAdc-gyroZero)/Sensitivity (In quids) -- Sensitivity = 0.00333/3.3*1023=1.0323
    why 1023 ? 10 bit is 1024 values (0 to 1023) please correct me if I am wrong

    >>double R = sqrt((accXval*accXval) + (accYval*accYval) + (accZval*accZval));
    Why do you use 3 Acc’s ?
    One Acc axis should be parallel to the wheels axis and remain horizontal, with no gravity modification

    >>double accXval = (double)((double)analogRead(accX) -- zeroValues[1]) / 102.3;
    seems that the 102.3 coeff has no impact on the calculation and can be ommitted

    >>if(inverted) accYval--;
    please elaborate on this one

    // -1g when lying at one of the sides
    Do you perform callbration when the bot is lying ?


  42. kas
    April 19th, 2012 at 19:57 | #42

    An additional one 🙂

    >>define leftA PIND0 // PD0 -- pin 0
    >>define leftB PIND1 // PD1 -- pin 1
    Pin 0 and 1 are used for Arduino serial communication
    Any possible interference with code loading ??

  43. Lauszus
    April 19th, 2012 at 22:12 | #43

    Try to do the math. You want to convert a voltage into quids, so if it is 3.3V that it equal to 1023 -- so the equation looks like this: 3.3V/3.3V*1023=1023

    I calculate the length of the force vector, see You can also just use two or only one axis to calculate the angle, but all three will give you more precision.

    You can also just calculate the angle using sinus:

    accYangle = asin(accYval)*RAD_TO_DEG;

    But yes I see your point, that the x-value are not changing that much, as it’s not affected by any gravitational force. But it will still be affected by the acceleration of the robot.

    Yes I calibrate the robot when it’s laying down, but the “zeroValue” for the y-axis is really not the “zeroValue”, as it’s either +1g or -1g depending at what side is laying down.

    You can easily use pin 0 and 1 -- it works just fine!

Comment pages
1 2 3 13 2196
  1. March 4th, 2012 at 21:03 | #1
  2. March 7th, 2012 at 21:22 | #2
  3. March 7th, 2012 at 21:29 | #3
  4. March 7th, 2012 at 23:33 | #4
  5. March 8th, 2012 at 02:49 | #5
  6. March 8th, 2012 at 05:03 | #6
  7. March 8th, 2012 at 08:31 | #7