bolderflight / invensense-imu

Arduino and CMake library for communicating with the InvenSense MPU-6500, MPU-9250 and MPU-9255 nine-axis IMUs.
MIT License
497 stars 210 forks source link

Calibration not working #78

Closed Ananfruit closed 3 years ago

Ananfruit commented 3 years ago

Hey! I am experiencing difficulty calibrating my sensor. The accelerometer values are biased and gyroscope readings are too low. I have attached a part of my code below. Please reply with an example sketch on how to calibrate the sensor. I'd be really grateful for your help. Thanks in advance

include "MPU9250.h"

// an MPU9250 object with the MPU-9250 sensor on I2C bus 0 with address 0x68 MPU9250 IMU(Wire,0x68); int status; int statusAcc; int statusGyr; int statusMag;

void setup() { // serial to display data Serial.begin(115200); while(!Serial) {}

// start communication with IMU status = IMU.begin(); //calibrating IMU statusAcc= IMU.calibrateAccel(); statusGyr= IMU.calibrateGyro(); statusMag= IMU.calibrateMag();

if (status < 0) { Serial.println("IMU initialization unsuccessful"); Serial.println("Check IMU wiring or try cycling power"); Serial.print("Status: "); Serial.println(status); while(1) {} } // setting the accelerometer full scale range to +/-8G IMU.setAccelRange(MPU9250::ACCEL_RANGE_8G); // setting the gyroscope full scale range to +/-500 deg/s IMU.setGyroRange(MPU9250::GYRO_RANGE_500DPS); // setting DLPF bandwidth to 20 Hz IMU.setDlpfBandwidth(MPU9250::DLPF_BANDWIDTH_20HZ); // setting SRD to 19 for a 50 Hz update rate IMU.setSrd(19); . . . .

GiovanniCmpaner commented 3 years ago

You have to call calibrateAccel() in a loop and move the hardware physically before each call. Think of the hardware as a plain cube with 6 faces, each position would be one face to the touching the ground / table.

Here is an example:

#include <Arduino.h>
#include <Wire.h>
#include <MPU9250.h>

MPU9250 mpu(Wire, 0x68);

void setup()
{
    Serial.begin(115200);
    Serial.println("Doing calibration");

    mpu.begin();

    for(int n = 0; n < 6; n++)
    {
        Serial.print("Move the car into position ");
        Serial.print(n);
        Serial.println();

        delay(7000);

        mpu.calibrateAccel();
    }

    Serial.println("Calibration done");

    Serial.print("bias x = ");
    Serial.print(mpu.getAccelBiasX_mss(), 5);
    Serial.println();

    Serial.print("bias y = ");
    Serial.print(mpu.getAccelBiasY_mss(), 5);
    Serial.println();

    Serial.print("bias z = ");
    Serial.print(mpu.getAccelBiasZ_mss(), 5);
    Serial.println();

    Serial.print("factor x = ");
    Serial.print(mpu.getAccelScaleFactorX(), 5);
    Serial.println();

    Serial.print("factor y = ");
    Serial.print(mpu.getAccelScaleFactorY(), 5);
    Serial.println();

    Serial.print("factor z = ");
    Serial.print(mpu.getAccelScaleFactorZ(), 5);
    Serial.println();
}

void loop()
{

}

Then you use those numbers in the real code:

#include <Arduino.h>
#include <Wire.h>
#include <MPU9250.h>

MPU9250 mpu(Wire, 0x68);

const float accelBias[3] = { 0.11111, 0.22222, 0.33333 }; // Obtained through calibration scketch
const float accelFactor[3] = { 0.11111, 0.22222, 0.33333 }; // Obtained through calibration scketch

void setup()
{
    Serial.begin(115200);
    Serial.println("Doing calibrated reading");

    mpu.begin();

    mpu.setAccelCalX(accelBias[0], accelFactor[0]);
    mpu.setAccelCalY(accelBias[1], accelFactor[1]);
    mpu.setAccelCalZ(accelBias[2], accelFactor[2]);
}

void loop()
{
    mpu.readSensor();

    Serial.print("accel x = ");
    Serial.print(mpu.getAccelX_mss(), 5);
    Serial.println();

    Serial.print("accel y = ");
    Serial.print(mpu.getAccelY_mss(), 5);
    Serial.println();

    Serial.print("accel z = ");
    Serial.print(mpu.getAccelZ_mss(), 5);
    Serial.println();

    Serial.println();
    delay(100);
}
paulrossmanith commented 3 years ago

Hey Ananfruit,

I do have a similar issue. I have no issues running the gyro/mag calibration. The accelerometer however will not calibrate correctly.

#include "MPU9250.h"

MPU9250 IMU(Wire, 0x68);

void setup() {
  // serial to display data
  Serial.begin(115200);
  while (!Serial) {}

  // start communication with IMU
  IMU.begin();
  if (IMU.begin() < 0) {
    Serial.println("IMU initialization unsuccessful");
    Serial.println("Check IMU wiring or try cycling power");
    Serial.print("Status: ");
    Serial.println(IMU.begin());
    while (1) {}
  }

  Serial.println("Calibrating Gyro... Please hold still");
  IMU.calibrateGyro();
  Serial.println("Gyro Calibration Complete!");
  Serial.print("Gyro Bias X (rad/s): \t"); Serial.println(IMU.getGyroBiasX_rads());
  Serial.print("Gyro Bias Y (rad/s): \t"); Serial.println(IMU.getGyroBiasY_rads());
  Serial.print("Gyro Bias Z (rad/s): \t"); Serial.println(IMU.getGyroBiasZ_rads());
  Serial.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
  delay(4000);

  Serial.println("Calibrating Accelerometer... Please rotate slowly");
  for (int n = 0; n < 6; n++)
  {
    Serial.print("Move the IMU into position ");
    Serial.print(n);
    Serial.println();
    delay(5000);
    IMU.calibrateAccel();
  }
  Serial.println("Accelerometer Calibration Complete!");
  Serial.print("Accelerometer Bias X (m*s^(-2)): \t"); Serial.println(IMU.getAccelBiasX_mss());
  Serial.print("Accelerometer Bias Y (m*s^(-2)): \t"); Serial.println(IMU.getAccelBiasY_mss());
  Serial.print("Accelerometer Bias Z (m*s^(-2)): \t"); Serial.println(IMU.getAccelBiasZ_mss());
  Serial.print("Accelerometer Scale X : \t"); Serial.println(IMU.getAccelScaleFactorX());
  Serial.print("Accelerometer Scale Y : \t"); Serial.println(IMU.getAccelScaleFactorY());
  Serial.print("Accelerometer Scale Z : \t"); Serial.println(IMU.getAccelScaleFactorZ());
  Serial.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
  delay(4000);

  Serial.println("Calibrating Magnetometer... Please move in 8-Shape slowly");
  IMU.calibrateMag();
  Serial.println("Magnetometer Calibration Complete!");
  Serial.print("Magnetometer Bias X (uT): \t"); Serial.println(IMU.getMagBiasX_uT());
  Serial.print("Magnetometer Bias Y (uT): \t"); Serial.println(IMU.getMagBiasY_uT());
  Serial.print("Magnetometer Bias Z (uT): \t"); Serial.println(IMU.getMagBiasZ_uT());
  Serial.print("Magnetometer Scale X : \t"); Serial.println(IMU.getMagScaleFactorX());
  Serial.print("Magnetometer Scale Y : \t"); Serial.println(IMU.getMagScaleFactorY());
  Serial.print("Magnetometer Scale Z : \t"); Serial.println(IMU.getMagScaleFactorZ());
  Serial.println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
  while (true);
}

void loop() {
  // put your main code here, to run repeatedly:
}

Now I will get the following output for the acceleromter:

Calibrating Accelerometer... Please rotate slowly
Move the IMU into position 0
Move the IMU into position 1
Move the IMU into position 2
Move the IMU into position 3
Move the IMU into position 4
Move the IMU into position 5
Accelerometer Calibration Complete!
Accelerometer Bias X (m*s^(-2)):    0.00
Accelerometer Bias Y (m*s^(-2)):    0.00
Accelerometer Bias Z (m*s^(-2)):    0.00
Accelerometer Scale X :     1.00
Accelerometer Scale Y :     1.00
Accelerometer Scale Z :     1.00

I do not believe the accelerometer is calibrated perfectly. 😄 Futhermore, when reading the accelerometer ( in m*s^-2), I get the followingm which obiously shows the calibration did not work at all.

                                 X                   Y                     Z     
11:34:01.459 -> -1.087023   -23.866619  9.783207
11:34:01.505 -> -1.019982   -23.971970  9.768841
11:34:01.599 -> -1.005616   -23.876196  9.893346
11:34:01.647 -> -1.019982   -23.952814  9.730532
11:34:01.695 -> -0.967307   -23.914505  9.783207
11:34:01.741 -> -1.029559   -23.904928  9.711377
11:34:01.789 -> -1.029559   -23.876196  9.706589
11:34:01.837 -> -0.972095   -23.871407  9.778418
11:34:01.884 -> -1.072657   -23.885773  9.792784
11:34:01.932 -> -1.087023   -23.847464  9.821516

Am I using the calibrateAccel() function incorrectly? If so, could you please point me towards the right direction?

Thanks guys! 🥂

flybrianfly commented 3 years ago

Calibration functions are no longer included as part of this library.