@ 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!
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..
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..
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
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...
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?
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?
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!