Balancing robot for dummies

@ 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:-
http://www.ianjohnston.com/content/images/stories/IanJ/Segway/Code/Segway_K_BotV2_IJ_1/

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!

Ian.

Check out the new maple out Maple - DEV-10664 - SparkFun Electronics.

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..

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.

@IanJohnson
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 Balancing robot for dummies - #172 by system - Exhibition - Arduino Forum.

He says exactly what I am saying..and his bot is balancing perfectly (like mine... minormelodic - YouTube)

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..

bye,

danilo

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...
Prevas Parekring and.. i create this..

#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.beginTransmission(GYRO);
  Wire.send(REG_GYRO_X); //Register Address GYRO_XOUT_H
  Wire.endTransmission();

  // New read the 12 data bytes
  Wire.beginTransmission(GYRO);
  Wire.requestFrom(GYRO,12); // Read 12 bytes
  i = 0;
  while(Wire.available()){
    buffer[i] = Wire.receive();
    i++;
  }
  Wire.endTransmission();

  //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++){
    getIMU();
    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(){
  Serial.begin(9600); 
  Wire.begin();
  configIMU();
  calibrarIMU(); 
}

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++){
    getIMU();
    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(",");
  Serial.print(IMU[4]);  // echo the number received to screen
  Serial.print(",");    
  Serial.println(IMU[5]);  // echo the number received to screen     
}

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

void loop(){
  leerIMU(); 
}

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!

aasanchez:
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.

I'm going to try this code on a ChipKIT Uno32 because of the incredibly fast processing speed in comparison to the Arduino. (80Mhz) I think that should take the loop time down significantly, thus potentially leading to better balance.

One thing I really don't understand is the Kalman filter.

Patrik, or Kas, could one of you offer any insight into being able to further tune balance by changing the Kalman parameters?

Hi guys,

Just want to show you a robot I made. It uses the motors, brackets and motorcontroller as Kas original used:

See my blog post for more details: TKJ Electronics » The Balancing Robot.

Update
I have now ported the code to Arduino.
The code can be found at github: The Arduino version, can now be found at github: GitHub - TKJElectronics/BalancingRobotArduino: This is the Arduino version of the code for my balancing robot/segway

Regards
Kristian Lauszus

Good job, Lauszus!

In wich sector ( industry, army ) it will be able to be use ?

Unbelievable work Lauszus!!

I am also in the middle of getting my robot to balance.. Tried to implement the original coding from KASbot but I haven't yet managed to change the PID values etc.

It's only when you try to do this yourself that you realise how challenging it is! Hopefully I will get my balancing program working soon... RC control is a long way off!

Robot Pic.png

#ericlausanne
I'm not totally sure what you mean? :slight_smile:

#rob4white
Thank you, see my reply at my blog: TKJ Electronics » The Balancing Robot