Go Down

Topic: Balancing robot for dummies (Read 91202 times) previous topic - next topic



Thanks for that. I hadn't quite followed the links for some reason, when I asked.

I'm playing a waiting game on my driver boards before even contemplating a start.

Mind you it allows me to finsih some of the other projects that are started, but not finished.



@ IanJohnston

why don't You try to put the battery (that should be heavy) as close as possible to the ground?
Make the Bot lower as you can...


May 09, 2011, 10:14 pm Last Edit: May 09, 2011, 11:00 pm by IanJohnston Reason: 1
@ prof_jazz
I had read that weight should be at the top......however, worth another try down below I guess.

Made some progress tonight however. I tidied up my power wiring after scoping the signals/supply and noticed that my speed controller is inducing noise onto the 0vdc and thus affecting everything, including the IMU.
I'll probably fit an isolating DC-DC conv this weekend so I can run two independant batteries.....downside is they'll have to come together at the Arduino.......but it should help.

The other thing I did.......and wait till you hear this one.......was overclock the Arduino to 28mHz (from original 16), and it's a vast improvement at first testing.
Actually, it runs at 32mHz also, but crashes every now & then.

I was using Kasbot 1 code mainly up till now and have started to migrate the V2 code over so I can get the encoders hooked up.....however, I'm not that convinced they are best placed in the PID calcs. I'm thinking maybe they could be used elsewhere, or possibly additionally elsewhere covering a new function. Hmmmmm!

My current test code is here:-

To do:-
- Play with 10-bit PWM rather than 8-bit.
- Optimize for 28mHz Arduino.
- Encoders
- DC-DC conv.
- Vref.

So, I'm a lot closer to achieving successful balancing............I think most of my problem all along was noise!



Check out the new maple out http://www.sparkfun.com/products/10664.

12-bit ADC resolution (ADC)
15 PWM pins at 16-bit resolution (PWM)

Should improve the resolution of the angle reading and the motor output a lot..
The balancing robot for dummies guide


May 21, 2011, 01:54 pm Last Edit: May 21, 2011, 02:02 pm by Ro-Bot-X Reason: 1
PWM on pins 9 and 10 (Timer1) is 16 bit, I see no problem from the resolution there, just make sure the code writes an int not a byte. SparkFun also sells a Digital 6DOF IMU unit that has a 3 axis gyro with a built in 16 bit analog converter and a 3 axis accelerometer with a built in 13 bit analog converter and uses a fast I2C interface (400kHz). I got one, but I have no time to work on this until fall.

On the other hand, the Maple brings out more computing power, but I'm not sure the bot really needs it, unless you're trying to do all in one balancing, driving, mapping, obstacle avoiding and other stuff. I would use one Arduino (or compatible) for balancing and another one (or more) for the rest of the stuff. Why? Because these micros don't have multitasking capabilities  and multiple things need to run at the same time, so having multiple micros running different code at the same time solves this problem without programming tricks that might or might not work. The I2C interface is perfect for communications between modules themselves and with the sensors, plus, more modules can read data from the same sensor.


I think that a lot of frustration for those that canno't balance their bot using The Kas/Patrik guide came from the confusion between torque and velocity..

If You use a PID where the Pterm (the one that drives all the balancing) is related to the tilt angle (P=k*error), You'll produce a Torque and not a velocity.

The torque will fight against the tilt and make it zero..

Please read carefully the SnakeLT thread http://arduino.cc/forum/index.php/topic,8871.msg74116.html#msg74116.

He says exactly what I am saying..and his bot is balancing perfectly (like mine... http://www.youtube.com/user/minormelodic#p/a/u/0/BaGc2IHJu40)

My bot started to balance when I started:

*)to use wheel heavier (the motor work produces more torque and less velocity);
*)to make the bot less high (the torque will compensate better the tilt producing);

...stay tuned, I'll post a video with my bot balancing, avoiding obstacles and following ad infrared source..




Jun 03, 2011, 08:01 am Last Edit: Jun 03, 2011, 08:06 am by Eugene Reason: 1
From Russia with love =)

Hello all

Big thx kas and Patrix for they old thread http://arduino.cc/forum/index.php/topic,8871.0.html
My robot don't balancing with active Patrik's GUI =( so slow work

Need help for writing code for movement by serial port without xbee

I use next parts:
Arduino Uno (rev2 with small quarts oscillators)
2A Motor Shield http://www.dfrobot.com/index.php?route=product/product&product_id=69
9V motors 175rpm with bad encoder 75 impuls per revolution (don't uses)
sparkfun modul with analog IDG500 & ADXL335
8.4V 1500mAh battery


Self-balancing robot v2.0

New frame...


And new short video


Hey guys, could you please tell me how to fine tune PID control parameters? I know i should first set them to 0 and then at first i should increase Kp until it oscillates after that increase Kd until there is no overshoot and as last step i should increase Ki. I know the logic but i can't apply it on my balancing robot. Especially determining Kp parameter is kind of hard for me. I don't know why (probably because of the wrong specified kalman filtering weight factor) but it always vibrates around the vertical 0 line.So it always looks like it is oscillating. If you can help me i will be greateful. Thank you...


I find this balancing thing really fascinating!

Excuse me for jumping off the Arduino topic, but I wonder how they got the Murata Boy so stable?


Murata girl is a little bit shaky, but the task on a mono-cycle is way more difficult I guess.


I guess there must be a rotating gyroscope inside to add stability. Any thoughts?


If you look at the "opening" in the chest area, you can clearly see the "gyro" accelerating to counteract the grativtational forces making it tilt.


Please... i try to copy this project.. but i use a IMU Fusion Board - ADXL345 / IMU3000, , I translate the code in this site, for my sensor...
http://www.x-firm.com/?page_id=189 and.. i create this..

Code: [Select]

#define GYRO 0x68         // Direccion del Giroscopo para I2C
#define REG_GYRO_X 0x1D   // Direccion para GYRO_XOUT_H en el IMU-3000
#define ACCEL 0x53        // Direccion del Acelerometro para I2C
#define ADXL345_POWER_CTL 0x2D

byte buffer[12];          // Array para almacenar los valdores del I2C
int IMU[6];               //Valores del IMU 0:GiroX;1:GiroY;2:GiroX;3:AccelX;4:AccelY;5:Accel:6
int zeroIMU[6];           //Resultado de Calibracion IMU, para puesta a 0; 0:GiroX;1:GiroY;2:GiroX;3:AccelX;4:AccelY;5:Accel:6
long tempIMU[6];           //valores temporales de Calibracion del IMU 0:GiroX;1:GiroY;2:GiroX;3:AccelX;4:AccelY;5:Accel:6

int i;

#include <Wire.h>

void configIMU(){
 // Configuramos el Giroscopo
 // Velocidad de Muestreo 1kHz, Filtro de ancho de banda 42Hz, Rango del Girospoco 500 d/s
 writeTo(GYRO, 0x16, 0x0B);      
 //Establecer la direccion del acelerometro
 writeTo(GYRO, 0x18, 0x32);    
 //Setear el acelerometro como esclavo
 writeTo(GYRO, 0x14, ACCEL);    

 // Ajuste el modo de paso a través de Accelerometro para que podamos encenderlo
 writeTo(GYRO, 0x3D, 0x08);    
 // establecer el control de aceleración poder para 'medir'
 writeTo(ACCEL, ADXL345_POWER_CTL, 8);    
 //cancelar el pasar a través del acelerometro, el Giroscopo ahora leerá aceleración para nosotros
 writeTo(GYRO, 0x3D, 0x28);  

// Funcion para escribir un valor en una direccion en un dispositivo especifico
void writeTo(int device, byte address, byte val) {
 Wire.beginTransmission(device);   // Comienza la transmision
 Wire.send(address);               // Envia la direccion
 Wire.send(val);                   // Envia el valor
 Wire.endTransmission();           // Finaliza la transmision

void getIMU(){
 for(int n=0;n<=5;n++){
   IMU[n] = 0;                    //Limpiamos el vector
 // Read the Gyro X, Y and Z and Accel X, Y and Z all through the gyro
 // First set the register start address for X on Gyro  
 Wire.send(REG_GYRO_X); //Register Address GYRO_XOUT_H

 // New read the 12 data bytes
 Wire.requestFrom(GYRO,12); // Read 12 bytes
 i = 0;
   buffer[i] = Wire.receive();

 //Combine bytes into integers
 // Gyro format is MSB first
 IMU[0] = buffer[0] << 8 | buffer[1];
 IMU[1] = buffer[2] << 8 | buffer[3];
 IMU[2] = buffer[4] << 8 | buffer[5];
 // Accel is LSB first. Also because of orientation of chips
 // accel y output is in same orientation as gyro x
 // and accel x is gyro -y
 IMU[3] = buffer[7] << 8 | buffer[6];
 IMU[4] = buffer[9] << 8 | buffer[8];
 IMU[5] = buffer[11] << 8 | buffer[10];

void calibrarIMU(){
 //Numero de Muestras para calibracin
 int muestras = 500;
 //Limpiamos el Vector
 for(int n=0;n<=5;n++){
   zeroIMU[n] = 0;
 for(int n=0;n<=5;n++){
   tempIMU[n] = 0;
 //Sumamos para para el Promedio
 for(int n=0;n<muestras;n++){
   for(int n=0;n<5;n++){
     tempIMU[n] = tempIMU[n] + IMU[n];    
 //Dividimos y obtenemos el promdio
 for(int n=0;n<5;n++){
   zeroIMU[n] = tempIMU[n] / muestras;
 zeroIMU[5] = 0; //Correccion segun datasheet


void setup(){

void leerIMU(){
 //Numero de Muestras para lectura
 int muestras = 10;
 //Limpiamos el Vector
 for(int n=0;n<=5;n++){
   tempIMU[n] = 0;
 //Sumamos para para el Promedio
 for(int n=0;n<muestras;n++){
   for(int n=0;n<=5;n++){
     tempIMU[n] = tempIMU[n] + IMU[n];    
 //Dividimos y obtenemos el promdio y restamos el valor de Calibracion
 for(int n=0;n<=5;n++){
   IMU[n] = (tempIMU[n] / muestras)-zeroIMU[n];    

void printADXL345(){
 Serial.print(IMU[3]);  // echo the number received to screen
 Serial.print(IMU[4]);  // echo the number received to screen
 Serial.println(IMU[5]);  // echo the number received to screen    

void printIMU3000(){
 Serial.print(IMU[0]);  // echo the number received to screen
 Serial.print(IMU[0]);  // echo the number received to screen
 Serial.println(IMU[0]);  // echo the number received to screen    

void loop(){

now i have a simple question... Why  STD_LOOP_TIME  =  9?


Are we abandoning this tread? It's too good to leave alone. Should start shooting for a full size segway based on kasbot code!


now i have a simple question... Why  STD_LOOP_TIME  =  9?

Standard Loop Time was set as nine because that is the time that the original KasBot sketch took to complete a loop. If you do a Serial.print of "lastlooptime" in the "loop timing control" function after doing all your alterations to the code you will get you loop time.

To my understanding you don't want STD_LOOP_TIME to be set above the actual loop time.

Go Up