IMU Calibrations?

I am currently attempting to calibrate an altIMU-10 v4 sensor that i got off of Polulu to build a self balancing robot, however I am running into some difficulties in calibrating the gyroscope. I do not believe that the sensor is broken. My basic idea of the code is to convert the raw readings from the gyroscope component of the IMU into an angle, however when I use my code to do this I end up with unstable readings. I have an inclinometer and when I move the ramp up the values spike to 1000’s or 10000’s and drops back to what it would be at ground level.

/*
The sensor outputs provided by the library are the raw 16-bit values
obtained by concatenating the 8-bit high and low gyro data registers.
They can be converted to units of dps (degrees per second) using the
conversion factors specified in the datasheet for your particular
device and full scale setting (gain).

Example: An L3GD20H gives a gyro X axis reading of 345 with its
default full scale setting of +/- 245 dps. The So specification
in the L3GD20H datasheet (page 10) states a conversion factor of 8.75
mdps/LSB (least significant bit) at this FS setting, so the raw
reading of 345 corresponds to 345 * 8.75 = 3020 mdps = 3.02 dps.
*/

#include <Wire.h>
#include <L3G.h>

L3G gyro;

//Variables
float Yax = 0;
float angleY = 0;

//Bias Parameters
float bias = 0;
int sampleNum = 500;

void setup() 
{
  Serial.begin(115200);
  Wire.begin();

  if (!gyro.init())
  {
    Serial.println("Failed to autodetect gyro type!");
    while (1);
  }

  gyro.enableDefault();
 
  for(int n=0;n<sampleNum;n++)
  {
    gyro.read();
    bias+=(int)gyro.g.y;
  }
  bias = bias/sampleNum;
  Serial.println();
  Serial.print("Gyro Bias:");
  Serial.print(bias); \
  Serial.println(); 
  delay(300);
}

void loop() {
  double time = millis();
  
  gyro.read();
  Yax = (int)gyro.g.y - bias;
  Yax = Yax*(3.3/1023);
  Yax = Yax/(8.75/1000);
  Serial.println();
  Serial.print("GyroRateY: ");
  Serial.print(Yax);
  Serial.print(" deg/s");
  
  angleY = Yax * (time/1000);
  Serial.println();
  Serial.print("AngleY: ");
  Serial.print(angleY);
  
  delay(100);
}

This code follows the same concept as this link here:

http://www.nuclearprojects.com/ins/arduino_program.shtml


Gyro_Rate = (Gyro_ADC_Value - Zero_Voltage_Value) * (3.3V/1023) / Gyro_Sensitivity
The zero_voltage_value is simply the initial ADC value of the sensor when it’s not moving. You can read and store this value during setup. In the case of the gyro, when it’s not moving, the rate should be zero, so we must zero out the gyro in the equation.

Even though the math is easy, there is nothing better than a worked-out example! In this example, I’ve read an ADC value 411 from the x-axis gyro during a rotation. My zero_voltage_value is 379 from my data above.

GyroRateX = (411-379) * (3.3/1023) / 0.00333 ----> (0.00333 is 3.33mV)
GyroRateX = 32 * 0.0032258 / 0.00333
GyroRateX = 30.999 deg/s
From this, I can see I’m rotating at a rate of about 31 degrees/second. Now how do use this to keep track of my overall angle of rotation? Easy! This can be done by taking regular readings and integrating them over a specified period of time.

Lets say I take readings every 20ms, or 0.020 seconds. My GyroRateX value gives me degrees/second. If I multiply that by 0.02sec, I’ll get the total angle the sensor is rotated during that short period of time. This of course assumes the rate was constant over that time. I can keep track of my overall rotation angle by adding up these small rotations. Example:
GyroAngleX += GyroRateX * 0.02
If you’ve not seen it, the “+=” symbology just says to add the calculated value on the right to GyroAngleX.

Your code doesn't match your description. The code is taking an instantaneous rate and multiplying it by the number of seconds since the Arduino was switched on. That looks worng.

http://stackoverflow.com/questions/7829097/android-accelerometer-accuracy-inertial-navigation