Skip to content

Understanding the calibration of the LSM303 magnetometer (compass)

ActionNerd edited this page Jan 30, 2015 · 5 revisions

Calibration Data Example from the LSM303

Calibration

The LSM303 magnetometer is very easy to calibrate if you understand the concept. See above diagram regarding the offset from origin (0, 0) that needs to be corrected. Use the readAxes function to gather data continuously as you spin the breakout board / chip on a flat surface. This will allow you to collect X, Y data as the board turns within the magnetic field. What you are looking for is the max and min values on each axis.

Using the above diagram as an example, you can see the center of the uncorrected calibration run is offset to the left. To find the uncorrected origin X value, calculate (Xmin + Xmax) / 2. In this case, it is approximately (-250 + 200) / 2 = -25. Visually, this makes sense. Y in this case is (-180 + 280) / 2 = 50. This makes the uncorrected origin (-25, 50). To add your calibration data, simple use mag.setOffset(X, Y, Z). In this case, it would be mag.setOffset(-25, 50, 0).

readHeading is not yet tilt compensated, so the Z value is not needed.

To get min / max values of X, Y, and Z, you can run a program like this below while spinning the board in the X/Y plane:

var magIntervalObj = setInterval(function() {
    // Returns heading vector in x, y, z cartesian coordinates
    mag.readAxes(function(err, axes) {
      if(err) {
        console.log("Error reading Magnetometes Axes : " + err);
      }
        if (axes) {
          axesTemp = axes;
      }
    });
    magIntervalCounter++;
    if (magIntervalCounter == 5000) {
      clearInterval(magIntervalObj)
    }
    console.log(headingTemp, axesTemp);
}, 200);

Obviously, not the full code. When starting the application, you can send console output to a text file like this: node app > caldata.txt. Continue spinning slowly until you have made several revolutions. When complete, open caldata.txt up in Excel. Open it as space delimited in the open data wizard. This will break your data out in columns. Then, it is simply a matter of finding the min and max values of each. You can use =min() or =max() in Excel.

Another option is simply to write an easy app which looks for min / max values while spinning and throws out previously min / max numbers. Like:

var magIntervalObj = setInterval(function() {
    mag.readAxes(function(err, axes) {
      if (magIntervalCounter == 1) {
        xMin = axes.x;
        xMax = axes.x;
        yMin = axes.y;
        yMax = axes.y;
        zMin = axes.z;
        zMax = axes.z;
      }
      if(err) {
        console.log("Error reading Magnetometes Axes : " + err);
      }
        if (axes) {
          axesTemp = axes;
          if (axes.x < xMin) {
            xMin = axes.x;
            console.log("New xMin = " + xMin);
          }
          if (axes.x > xMax) {
            xMax = axes.x;
            console.log("New xMax = " + xMax);
          }
          if (axes.y < yMin) {
            yMin = axes.y;
            console.log("New yMin = " + yMin);
          }
          if (axes.y > yMax) {
            yMax = axes.y;
            console.log("New yMax = " + yMax);
          }
          if (axes.z < zMin) {
            zMin = axes.z;
            console.log("New zMin = " + zMin);
          }
          if (axes.z > zMax) {
            zMax = axes.z;
            console.log("New zMax = " + zMax);
          }
      }
    });
    magIntervalCounter++;
    if (magIntervalCounter == 5000) {
      clearInterval(magIntervalObj)
    }
}, 200);

Obviously, not the full code. #ToDo -- Will make a few examples and move these over to examples in the code.

Clone this wiki locally