The Balancing Robot
Now avaliable as a kit
A balancing robot kit is now avaliable via Kickstarter: http://www.kickstarter.com/projects/tkjelectronics/balanduino-balancing-robot-kit. Check out the blog post as well: http://blog.tkjelectronics.dk/2013/03/balanduino-balancing-robot-kit-kickstarter/.
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:
- Motors with build in encoders
- Motor Brackets
- Motor driver
- BaneBots Wheels (These wheels are no longer available from the seller, but you can use these wheels and these hubs instead)
- Hubs
- IMU
- mbed microcontroller
- mbed breakout board
- Arduino Duemilanove for PS3 bluetooth communication
- USB Host Shield
- Bluetooth dongle – it has to support bluetooth version 2.0+EDR
- PS3 Controller
- 12V 3800mAh NiMH Batteries – I got two of them
- Female Tamiya connector
- Two XBee modules for wireless debugging and setting the PID constants wirelessly. Alternativly you could use an inexpensive Bluetooth Serial module
- Two XBee adapter kits
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: http://grabcad.com/library/balancing-robot.
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.
Update
I have now ported the code to Arduino. The code can be found at github: https://github.com/TKJElectronics/BalancingRobotArduino.
Improvements
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.
Conclusion
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.

@WilcovT
Check out the readme: https://github.com/felis/USB_Host_Shield_2.0#how-to-include-the-library it describes how to add the library.
@getSurreal
No mine is more like +/- 0.05 degrees -- I just checked with my Balancing robot that uses a MPU-6050.
@Lauszus
Dear Kristian,
Now i got it, had a typo, after some days with little sleep, looked over a period. But when i compile it says:
In file included from C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/Usb.h:40,
from C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/BTD.h:21,
from C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/SPP.h:21,
from BalancingRobotArduino.ino:16:
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/message.h: In function ‘void ErrorMessage(const char*, ERROR_TYPE)’:
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/message.h:48: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/message.h:50: warning: only initialized variables can be placed into program memory area
In file included from C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/BTD.h:21,
from C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/SPP.h:21,
from BalancingRobotArduino.ino:16:
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/Usb.h: At global scope:
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/Usb.h:168: warning: ‘packed’ attribute ignored
In file included from C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/BTD.h:22,
from C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/SPP.h:21,
from BalancingRobotArduino.ino:16:
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h: In member function ‘void ConfigDescParser::PrintHidDescriptor(const USB_HID_DESCRIPTOR*)’:
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:176: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:177: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:180: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:183: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:186: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:189: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:201: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:204: warning: only initialized variables can be placed into program memory area
C:\Users\Wilco\Documents\Arduino\libraries\USB_Host_Shield_201/confdescparser.h:207: warning: only initialized variables can be placed into program memory area
BalancingRobotArduino.ino: In function ‘void loop()’:
BalancingRobotArduino:115: error: invalid conversion from ‘int’ to ‘char*’
BalancingRobotArduino:115: error: initializing argument 2 of ‘void SPP::doubleToString(double, char*, uint8_t)’
BalancingRobotArduino:115: error: invalid use of void expression
BalancingRobotArduino:117: error: invalid conversion from ‘int’ to ‘char*’
BalancingRobotArduino:117: error: initializing argument 2 of ‘void SPP::doubleToString(double, char*, uint8_t)’
BalancingRobotArduino:117: error: invalid use of void expression
BalancingRobotArduino:119: error: invalid conversion from ‘int’ to ‘char*’
BalancingRobotArduino:119: error: initializing argument 2 of ‘void SPP::doubleToString(double, char*, uint8_t)’
BalancingRobotArduino:119: error: invalid use of void expression
BalancingRobotArduino:121: error: invalid conversion from ‘int’ to ‘char*’
BalancingRobotArduino:121: error: initializing argument 2 of ‘void SPP::doubleToString(double, char*, uint8_t)’
BalancingRobotArduino:121: error: invalid use of void expression
BalancingRobotArduino:128: error: invalid conversion from ‘int’ to ‘char*’
BalancingRobotArduino:128: error: initializing argument 2 of ‘void SPP::doubleToString(double, char*, uint8_t)’
BalancingRobotArduino:128: error: invalid use of void expression
BalancingRobotArduino:130: error: invalid conversion from ‘int’ to ‘char*’
BalancingRobotArduino:130: error: initializing argument 2 of ‘void SPP::doubleToString(double, char*, uint8_t)’
BalancingRobotArduino:130: error: invalid use of void expression
BalancingRobotArduino:132: error: invalid conversion from ‘int’ to ‘char*’
BalancingRobotArduino:132: error: initializing argument 2 of ‘void SPP::doubleToString(double, char*, uint8_t)’
BalancingRobotArduino:132: error: invalid use of void expression
And in an orange banner it says : invalid conversion from int to char and highlighting :
if(SerialBT.connected) {
Usb.Task();
if(sendPIDValues) {
sendPIDValues = false;
strcpy(stringBuf,”P,”);
—> strcat(stringBuf,SerialBT.doubleToString(Kp,2)); //here it begins with an error
strcat(stringBuf,”,”);
strcat(stringBuf,SerialBT.doubleToString(Ki,2));
strcat(stringBuf,”,”);
strcat(stringBuf,SerialBT.doubleToString(Kd,2));
strcat(stringBuf,”,”);
strcat(stringBuf,SerialBT.doubleToString(targetAngle,2));
SerialBT.println(stringBuf);
dataCounter = 1;
} else if(sendData) {
switch(dataCounter) {
case 0:
strcpy(stringBuf,”V,”);
strcat(stringBuf,SerialBT.doubleToString(accYangle,2));
strcat(stringBuf,”,”);
strcat(stringBuf,SerialBT.doubleToString(gyroAngle,2));
strcat(stringBuf,”,”);
strcat(stringBuf,SerialBT.doubleToString(pitch,2));
SerialBT.println(stringBuf);
break;
}
dataCounter++;
if(dataCounter > 4)
dataCounter = 0;
}
}
What to do?
@WilcovT
The doubleToString function has changed since I wrote the code. You can simply download this version of the USB Host Shield library: https://github.com/felis/USB_Host_Shield_2.0/tree/6598bca58aea0eb57457fe28c6faa81a6f247fa2 -- this is the version that will come of if you click at the letters next to the submodule.
If you want you can update the code and send a pull request -- see this line on how to use the function after the update: https://github.com/felis/USB_Host_Shield_2.0/blob/master/SPP.cpp#L924.
Thanks Kristian, that made all the difference!!! Just some memory allocation errors and im good to go!!!!
Thank you for replying so fast, no i wont think about it all night haha.
greetings Wilco
And only trying to get the mpu6050 in the code
@WilcovT
You can just ignore all the warnings that says: “only initialized variables can be placed into program memory area”.
You are welcome
You should check out the MPU-6050 example I wrote: https://github.com/TKJElectronics/Example-Sketch-for-IMU-including-Kalman-filter/blob/master/IMU6DOF/MPU6050/MPU6050.ino. We will also publish the code for our Balancing robot: http://www.kickstarter.com/projects/tkjelectronics/balanduino-balancing-robot-kit in two weeks -- it got several improvements and uses the MPU-6050.
I read about the robot kit, and looks very promising, when it is going to be available, i will order a kit, i am trying to teach my nephew some arduino and want him to have fun, and although i am in the car restoration bussines, it is fun for me too.
I tried the sketch, and it worked, and that i have to implement in the arduino robot sketch, and replace all the analog gyro lines with the example sketch. Sorry for asking so much, but im still learning and in the spare time i have left, im learning code.
greetings Wilco
@WilcovT
It is available -- you simplify order it through Kickstarter
Okay. No problem, you can ask as much as you like!
Hey Kristian, congrats on the kickstarter. I could not get a kickstart set, due to the fact that i dont have a credit card… But in the future i will, and then there will be a set for me. Right now it will be a arduino board and all the other things seperate.
But i have a question, has there be much to be adapted to use a Due, or are those minor changes to the software?
I just got a Due and a sabertooth 2x25 for my birthday and want to port the code to the Due, but was wondering if i need a seperate shield for the bluetooth( due has usbhost) and if the code needs changes)
Greetings Wilco
@Wilco van Toorn
You can’t easily use an Arduino Due, as you can’t use any of the USB Host libraries with it easily, as it’s not an AVR, but an ARM processor.
Okay no problem
But you could try to make a balancing robot to start with and then add remote control of some sort afterwards. It shouldn’t be that hard to port the balancing part of the robot to a Due as most of it’s the same. The major difference is in this file: https://github.com/TKJElectronics/Balanduino/blob/master/Firmware/Balanduino/Motor.ino.
You can’t use the EEPROM functions we use either, as they are for AVR’s only, but just remove them for now.
@Lauszus: hi I am also working on my robot. I liketo ask 2 questions:
1. When you let the robot spin (right forw/left rev), will it stay stable for long time?
2. When you push the robot out of position, it returns. But what part of the sofw prevents it from overshouting when moving back to pos? This part steers it back to position but where is the “braking” part?
if (abs(positionError) > zoneA) // Inside zone A restAngle -= (double)positionError/positionScaleA; else if (abs(positionError) > zoneB) // Inside zone B restAngle -= (double)positionError/positionScaleB; else // Inside zone C restAngle -= (double)positionError/positionScaleC; restAngle -= (double)wheelVelocity/velocityScaleStop;
@YoBe
1. Yes it will stay upright until the batteries runs out!
2. This is the braking part: https://github.com/TKJElectronics/Balanduino/blob/master/Firmware/Balanduino/Balanduino.ino#L227-L229
@Lauszus: thanks for the reply and also GREAT job done on your robot.
At the moment my robot is balancing quite good but during spinning it starts getting out of ballance. My IMU is mounted on the side of the robot. Perhaps this is the problem. I should move it to the center…
I started my balancing robot by inspiration of “n-Bot”. I can only work on it during my spare time so progress is not so fast. But I need to say it takes quite some time to get it up and running.
I use the Madgwick filtering. Perhaps Kahlmann is better, need to evaluate.
I read you have pitch accuracy around 0.05deg (but this is with the latest IMU I think) I still use an 3G accelometer with analog outputs…perhaps need to change to SPI comm.
On my motorcomtroller I need to have minimun 25 on the PWM value to make the motor run. So I always add this offset. You do not need to do this I see. Of course your motor regulater is much better. (I still use LM298…)
At the moment I live in China and it is really fun to buy all these electronic stuff at cheap prices.
My next steps are now improving the spinning, encoder regulation and implementation of a PS2 controller.
Congrats with the Kick starter project!
PS: is this part also not slowing down the robot when steering back to original position?: “restAngle -= (double)wheelVelocity/velocityScaleStop;”.
@YoBe
Okay, yes try that and see if it help. Put it as near to the rotational axis as possible.
Yes it takes much more time than most people think
Also by using a digital IMU you will typically get higher resolution too -- for instance the MPU-6050 we use for the Balanduino (see: http://www.kickstarter.com/projects/tkjelectronics/balanduino-balancing-robot-kit and https://github.com/TKJElectronics/Balanduino) has a resolution of 16bits while the ADC on the ATmega328P used on the Uno only has a resolution of 10bits.
I would love to shop all my parts local so I don’t have to wait for them to arrive and I can get them in my hands before buying them -- but almost everything electronics wise is manufactured in China so it’s not possible here in Denmark
Okay. Let me know your progress and I will be happy to help you out!
Yes this line: https://github.com/TKJElectronics/Balanduino/blob/master/Firmware/Balanduino/PID.ino#L31 will slow down the robot depending on the velocity of the wheels, this helps slow down the robot, so it never goes to fast.
@Lauszus: Thanks for the tip on the IMU. Here in China: 4euro (incl. transport) for this part on a breakboard. Will order it tonight. I Love China for this…
@YoBe
Okay. Actually my teammate Thomas is in China right now. Last time I spoke with him he was going to Shenzhen, so he is properly spending all his money on cheap electronics right now
Hey bud, how are you? You put that money I sent you to good use?
So for the longest time I thought my problem was the gyro (mind you I’ve only spend about 2 hours on this thing since we last talked). Today I decided I would focus on the accelerometer and see if I could find anything. I realized I had the sampling frequency on the accelerometer set to 100Hz even thought I was reading it about about 400Hz. Problem fixed. That was my problem all along.
@Ryan Lush
Hi
Yes I bought a Sanguino, so I could test the ATmega644A we now use for our Balanduino project: http://www.kickstarter.com/projects/tkjelectronics/balanduino-balancing-robot-kit!
Good to hear you solved it! Are you planning to upload a video of it or something like that?
Hi!Lauszus,
i can see the result of angel graphic measured by MPU6050 with Kalman filter in your bot? Because i feel my angle is not good so i want to see your angel graphic to compare them.Thank!
Hey,guy!
Cân you tell me how do you calibrate mpu6050 and how do you get the stable angel from mpu6050.It’s better ì you give me your code.Please reply early ! sorry for my disturbing and thank very much.:)
@kim
Simply upload the firmware: https://github.com/TKJElectronics/Balanduino/tree/master/Firmware/Balanduino to your board.
Then download the Processing app: https://github.com/TKJElectronics/BalanduinoProcessingApp then you will be able to see the data on a graph.
@ROY
Check out the firmware for the Balanduino: https://github.com/TKJElectronics/Balanduino/blob/master/Firmware/Balanduino/Balanduino.ino and these I2C routines we wrote: https://github.com/TKJElectronics/Balanduino/blob/master/Firmware/Balanduino/I2C.ino.
Hi,Lauszus!
I wonder about your power supply for your bot.You use battery as a common source to supply control board and motor or one source for control board and the other for motor ?.thank you?