### Magnetometer, accelerometer calibration

Posted:

**Fri Mar 05, 2010 5:05 pm**While I was bench testing hardware platforms with experimental filters, I noticed I was getting inaccurate magnetometer measurements ie a 90 degree rotation was not a 90 degree rotation in all quadrants. This was prevalent in all of my methods. I was trying to work around this but the errors were sufficient to cause problems.

I explored calibration methods and found a very nice solution. Similiar methods are outlined in multiple papers but I found this method already simulated in matlab, thus it only took a few hours to implement. The code is based on a paper by Merayo et al "Scalar calibration of vector magetometers". Essentially, a data set of real magnetometer measurements is collected from all quadrants (a complete sphere of rotations). This data is really a displaced, distorted 3 dimensional ellipse due to magnetometer calibration errors.

A Matlab routine crunches through the data and produces coefficients that best fit a sphere to the data.

The result is a matrix U[3x3] and a vector c[3] such that the calibrated measurement w = U*(v-c)

This is easily implemented in code using something like this:

void calibrate_magnetometer(void)

{

// float 3x3 matrix for elliptical magnetometer corrections

m3x3 U= {

{ 1.765e-03, 1.635e-04, -4.247e-05 },

{ 0.000, 1.734e-03, -8.498e-05 },

{ 0.000, 0.000, 1.944e-03 } };

// float 3 vector for center point corrections

vector3 c= { -2.368e+001, -4.000e+001, -8.719e+001 };

vector3 tmp; // temporary for calcs

// subtract c from magnetometer readings to correct center point tmp = magbuf - c

tmp[0] = (float)magbuf.x.i16 - c[0];

tmp[1] = (float)magbuf.y.i16 - c[1];

tmp[2] = (float)magbuf.z.i16 - c[2];

// multiply mag = U * tmp (this is matrix * vector with zeros on bottom left)

mag[0] = U[0][0] * tmp[0] + U[0][1] * tmp[1] + U[0][2] * tmp[2];

mag[1] = U[1][1] * tmp[1] + U[1][2] * tmp[2];

mag[2] = U[2][2] * tmp[2];

}

I thought this was very cool. I've attached a zip with the matlab code and some data. A similiar method could work for accelerometer triads also. I'm exploring that.

I explored calibration methods and found a very nice solution. Similiar methods are outlined in multiple papers but I found this method already simulated in matlab, thus it only took a few hours to implement. The code is based on a paper by Merayo et al "Scalar calibration of vector magetometers". Essentially, a data set of real magnetometer measurements is collected from all quadrants (a complete sphere of rotations). This data is really a displaced, distorted 3 dimensional ellipse due to magnetometer calibration errors.

A Matlab routine crunches through the data and produces coefficients that best fit a sphere to the data.

The result is a matrix U[3x3] and a vector c[3] such that the calibrated measurement w = U*(v-c)

This is easily implemented in code using something like this:

void calibrate_magnetometer(void)

{

// float 3x3 matrix for elliptical magnetometer corrections

m3x3 U= {

{ 1.765e-03, 1.635e-04, -4.247e-05 },

{ 0.000, 1.734e-03, -8.498e-05 },

{ 0.000, 0.000, 1.944e-03 } };

// float 3 vector for center point corrections

vector3 c= { -2.368e+001, -4.000e+001, -8.719e+001 };

vector3 tmp; // temporary for calcs

// subtract c from magnetometer readings to correct center point tmp = magbuf - c

tmp[0] = (float)magbuf.x.i16 - c[0];

tmp[1] = (float)magbuf.y.i16 - c[1];

tmp[2] = (float)magbuf.z.i16 - c[2];

// multiply mag = U * tmp (this is matrix * vector with zeros on bottom left)

mag[0] = U[0][0] * tmp[0] + U[0][1] * tmp[1] + U[0][2] * tmp[2];

mag[1] = U[1][1] * tmp[1] + U[1][2] * tmp[2];

mag[2] = U[2][2] * tmp[2];

}

I thought this was very cool. I've attached a zip with the matlab code and some data. A similiar method could work for accelerometer triads also. I'm exploring that.