Introduction: Configure, Read Data & Calibrate the HMC5883L Digital Compass Using Python

As in other blogs, this one also contains information that can be found elsewhere on the web. I just structured it to make it easy to use for beginning robot hobbyists.

Connecting the compass is quite simple. When mounting the sensor to the bot, be aware of the x-y-z marker on the sensor and assure that the x-> points towards the front of the bot.

The compass uses the I2C protocol. Connect the sensor to the (I2C-) GPIO pins on the Pi as follows:

  • Connect VCC to pin-1 (3.3.V)
  • Connect SDA to pin-3 (SDA = System Data)
  • Connect SCL to pin-5 (SCL = System Clock)
  • Connect GND to pin 7 (GND)

First of all the Raspberry Pi needs to be configured for using the I2C protocol. This is disabled by default on the Raspberry. You’ll find an excellent tutorial at: Adafruit: configuring Raspberry Pi for I2C

To calibrate the compass the bot will have to be turned several times. This can be done by hand. I used a rotating snack display to make turning the bot, while keeping it horizontal, easy.When testing the I2C connection as explained at the end of the Adafruit lesson, the 0x1e address will most likely be shown for the HMC5883L sensor. If you get a different address you’ll have to change the address variable in the scripts.

The next step is reading and displaying data from the sensor. For this I used a very simple script which can be found here:

Calibrate step 1

How to use the sensor registers for binary reading and writing can be found in the sensor data sheet and in the script. I won’t go into that details here. The script initializes the sensor as follows:

  • 8 samples at 15 Hz,
  • LSb gain 1.5 (default),
  • Gauss 1090 (default),
  • continuous sampling,
  • scaling 0.92

If you don’t want to dive into the sensor characteristics, just leave the values as in the script. They are pretty generic and will suffice for almost all situations.

Now the script reads the x, y and z registers, calculates the arctangent of x and y and converts the outcome into degrees. Just run the script and you’ll get a first bearing e.g. 46.53891942 (46° 53’ 89.2”) Start rotating the bot until you get close to 0 degrees. Then rotate it through four 90° positions, reading the sensor data at every step. Most probably you might see that the values deviate and are not fully right.

So let’s figure out what is happening. For this you can use the next simple script:

Calibrate step 2

This script gathers 500 readings and writes the values to a CSV file which can easily be imported into Excel and be plotted in a scattered graph.Run the script ( sudo python HMC5883L_calibrate_step_2.py ) and start rotating the bot back and forwards through 360° while the script is running.The outcome should be something like in the picture.

Now the offset (just a slight one in my case) is visualized. To get a more specific value for the x and y offset, you can use the third script, which can be found here:

Calibrate step 3

This script again takes 500 reading, keeps the minimum and maximum values of x and y and calculates the offsets. Run the script in the same way as the former script, constantly rotating the bot. You should get something like this:

  • minx: -212
  • miny: -246
  • maxx: 262
  • maxy: 239
  • x offset: 25
  • y offset: -4

Now these offsets can easily be applied to the script, which is done in this example:

Calibrate step 4

(To make a new plotting, the script can be combined with step 2 to have the values saved into a CSV file.)

The last step to get a rather accurate working compass, is applying the declination. You’ll find your specific declination through this page: magnetic declination

Bear in mind that the declination is in degrees, so subtract the declination when the bearing is calculated in degrees. An example can be found here:

Calibrate step 5

Now the calibrating is done, you can run the last script and repeat the first test by rotating the bot through 90° steps and even compare the bearing with another digital compass (on your cell phone for example).

That’s it !