Calibrating the Compass

My approach to development so far had been to bench test the components and the code and then move them over into the car.  This meant that most of my testing and calibration was done outside the scope of the electrical and magnetic environment added by the cars components, such the DC permanent magnet drive motor, the steering servo (which also contains a PM motor) and the various magnetic-field-altering aspects of the car.  I quickly learned that all my carefully calibrated subsystems did not behave as I expected when I took the car outside for test runs.  In fact, the car seemed at times to have a mind of its own, steering wildly from side to side one minute, then seeming to driver rather well the next.  I had two culprits in mind; the GPS subsystem and the magnetic compass.  As it turns out, both needed work, and for different reasons than I first suspected.  This section will focus on the compass and what it took to get it operating correctly.

To be more precise, my car uses a 3 axis magnetometer, not a compass.  A compass is a magnetized needle that swings under influence of the earth's magnetic field until it aligns itself along the N/S lines of force.  The magnetometer in my car, however, contains three sensors that sense the relative strength of the magnetic field in three perpendicular axes; X, Y and Z.  The some of these three readings then form a vector that supposed to point in the direction as a compass needed.  However, how well this works depends on several things.  First, it assumes that all three magnetic sensors are all functionally equivalent and would all return the same reading if their positions in the device were interchanged.  However, due to manufacturing tolerances and variations, this is usually not true.  So, as a first step, we need some way to compensate for these differences.  Second, the big permanent magnet motor at the rear of the car does exert a distorting effect on the Earth's magnetic field, as do the other magnetic components in the car.

One easy way to visualize the effect of all these distortions is to spin the magnetometer around, for example, the Z axis while recording the values returned by the X and Y sensors.  I did this using my original HMC5883L magnetometer, then used Excel to display an X/Y point plot of the data.  If the magnetometer was properly calibrated, the result should have been a circle centered on the X/Y axes.  Instead, this is what I got:

As you can see, the circle is not centered on X and Y but is, instead, shifted down and to the left.  So, this started to explain some of my car's erratic behavior.  However, this data was gathered on my desktop with the HMC5883L magnetometer no where near the big PM motor in the car.  So, the next step was to perform the same check using the new magnetometer contained in the LSM303DLM chip in the Pololu MinIMU-9.  I was very curious to see what this test would show, as the car had seemed to perform worse once I replaced the HMC5883L with the MinIMU-9 and had gone to all the trouble of adding in the complex code needed to perform tilt compensation.  The result was more surprising than I expected:

As the plot shows, the origin was outside the circle formed by the 
X/Y readings!  So, it was instantly clear why car performed worse with this new magnetometer.  In thinking about the graph, I realized that my car's motor was located to the left rear of the car, so it seems quite likely that this explains the distortion.  Fortunately, the fix is rather easy, I simply calculate the offset from the origin and subtract it from the readings before performing the trigonometric math needed to compute the compass heading.