How to calibrate sparkfun mpu9250

Hi,

I have a sparkfun mpu9250 imu and I want to properly calibrate the magnetometer, accelerometer and the gyroscope. I found this very useful thread ([SOLVED] ISSUE: MPU9250 Sensor: Can't get correct data from Magnetometer) along with this blog (Tutorial: How to calibrate a compass (and accelerometer) with Arduino | Underwater Arduino Data Loggers) that explain how to do just that except they do it for a different sensor that had the gain settings in the datasheet.

GN2 GN1 GN0 Sensor input field range [Gauss] Gain X, Y, and Z [LSB/Gauss] Gain Z[LSB/Gauss] Output range
0 0 1 ±1.3 1100 980
0 1 0 ±1.9 855 760
0 1 1 ±2.5 670 600 0xF800-0x07FF
1 0 0 ±4.0 450 400 (-2048 to +2047)
1 0 1 ±4.7 400 355
1 1 0 ±5.6 330 295
1 1 1 ±8.1 230 205

However, I can't seem to find those settings in the sparkfun datasheet.

Here's the part in the blog in question that i'm referring to

I ran a sketch to collect raw data while i rotated the imu but the values are too high and according to the blog, they need to be scaled down to be fed to the magneto program. My question is where can I find those gain factors for the sparkfun mpu9250?

The Sparkfun sensor page discusses a manual procedure for calibration of the magnetometer.
https://learn.sparkfun.com/tutorials/mpu-9250-hookup-guide/all

Please note that this unit is depreciated and a newer model is recommended.

I saw that but then I read that the Sparkfun and Kris Winer MPU-9250 code both have major errors and should not be used which is why i turned to that blog post and I am using the code from this post but in the blog they were using another sensor.

The calibration procedure must still be performed "somehow" regardless of the library used (library should implement some procedure.)

Well in this case, the files suggested to first run the mpu_9250_cal sketch to get the gyro offset and collect raw value samples while rotating the sensor. After that it said I have to input those values to magneto so it calculates and gives me corrections. It outputs combined scale factors, misalignments and compensation for soft iron. My issue is i don't know if I need to do the axis specific gain correction and if so I can't seem to find the gain scale to use from the datasheet.

For magneto, the "norm H" value is arbitrary, as none of the AHRS programs care about the absolute value of the magnetic field strength. They use only the direction of the magnetic field vector, and for input to the Mahony or Madgwick filters, the vector should be normalized (if it is not normalized elsewhere).

For Magneto, choose a value for the norm so that the diagonal correction matrix elements end up being about 1. The average magnitude of the input field vector is a fine choice.

This is the data I collected and this is the output from magneto that gives me values of about 1 for the diagonal values in the matrix

data.zip (3.9 KB)

So can I just use this or the data collected needs to be scaled down? I'm confused because the blog I read said the following

“Magneto expects to receive raw data in +- format (a value of zero indicating a null field in the current axis), but not necessarily normalized to +-1.0.

If your sensors have SPI or I2C outputs, they will usually directly produce the required format. For example, the MicroMag3 magnetometer directly produces counts from -3411 to +3411, and the the SCA3000 accelerometer directly produces counts from -1333 to 1333, and Magneto can process directly these values, without the need to normalize them to +- 1.0. I understand that a normalization may be desirable to avoid machine precision problems, but this has not been the case with these sensors.

If your sensors produce voltage levels that you have to convert to counts with an ADC, you have indeed to subtract a zero field value from the ADC output before using Magneto. You would then normally choose the maximum positive value as input to the ‘Norm of Magnetic or Gravitational field’.

The magneto result is excellent, and allows you to vastly improve the accuracy of the magnetometer readings.

Whether the corrected data need to be scaled depends on your actual application.

It's for a small hovercraft I am trying to build and I want it to guide itself autonomously.
In the sketch where I have to add the corrected values I got

// vvvvvvvvvvvvvvvvvv  VERY VERY IMPORTANT vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//These are the previously determined offsets and scale factors for accelerometer and magnetometer, using MPU9250_cal and Magneto 1.2
//
//The scale constants should *approximately* normalize the vector magnitude for accel and mag to 1.0
//The AHRS will NOT work well or at all if these are not correct

float A_cal[6] = {515.0, 279.0, 751.0, 5.96e-5, 6.26e-5, 6.06e-5}; // 0..2 offset xyz, 3..5 scale xyz
float M_cal[6] = {18.0, 28.3, -39.6, 0.01403, 0.01414, 0.01387}; // can make both 3x3 to handle off-diagonal corrections
float G_off[3] = {-45.0, 334.0, 141.2}; // newly calculated raw offsets

I replace the gyro offsets given by the sketch that calculates the raw values however, the raw data given to magneto included 6 columns: first 3 (xyz) for accelerometer and last 3 (xyz) for magnetometer. Do I need to separate them into 2 files and calculate them separately with magneto? I assume so since the offset values I have right now are way too high for the magnetometer.

Yes. Although it is much, much more important to calibrate the magnetometer.

In that case do you suggest I just calibrate the magnetometer or should I still do both for good measure?

It is always best to calibrate both.

alright I will do them both and just to be sure I understood it correctly. The combined biases calculated in magneto will go here as x, y and z and the diagonal values of the computed matrix A as scale factors diagonal_1,diagonal_2,diagonal_3 ?

float A_cal[6] = {x, y, z, dialogal_1,dialogal_2,dialogal_3}; // 0..2 offset xyz, 3..5 scale xyz

To do the calibration right requires use of the full matrix. Since the MPU-9250 was discontinued several years ago, and I no longer have one to test, I never bothered to implement that correction.

It is done correctly for its much improved successor, the ICM_20948, so you can take a look at that code here:

This helps clear up my confusion so much. Thank you.

//Gyro default scale 250 dps. Convert to radians/sec subtract offsets
float Gscale = (M_PI / 180.0) * 0.00763; //250 dps scale sensitivity = 131 dps/LSB
float G_offset[3] = {74.3, 153.8, -5.5};

//Accel scale: divide by 16604.0 to normalize
float A_B[3]
{   79.60,  -18.56,  383.31};

float A_Ainv[3][3]
{ {  1.00847,  0.00470, -0.00428},
  {  0.00470,  1.00846, -0.00328},
  { -0.00428, -0.00328,  0.99559}
};

//Mag scale divide by 369.4 to normalize
float M_B[3]
{ -156.70,  -52.79, -141.07};

float M_Ainv[3][3]
{ {  1.12823, -0.01142,  0.00980},
  { -0.01142,  1.09539,  0.00927},
  {  0.00980,  0.00927,  1.10625}
};

Where you say Mag scale divide by 369.4 to normalize and Accel scale: divide by 16604.0 to normalize. Those scale values are taken from the mpu_9250_cal sketch where it calculates and displays rms for A and M at the end?

Those numbers were notes to myself. The code should normalize the vectors automatically.

In looking back, I see that I did add the full matrix correction to this MPU-9250 code. If you look at the function get_MPU_scaled(); you will see where the vectors are normalized.

Thank you so much I was going crazy trying to understand how all of it ties up together. I understand it now. I will rerun the calculation sketch and separate the accelerometer and the magnetometer readings into 2 files and use them separately in magneto to get my matrices.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.