Last Updated on 2nd September 2023 by peppe8o
In this tutorial, I’m going to show you how to wire, calibrate (X / Y axes) and use an HMC5883L device, also known as a magnetometer, with Raspberry PI Pico using MicroPython.
Many projects (like robotic ones) need to get info about spacial position and direction. In this sense, one of the most useful devices for projects involving Raspberry PI Pico is an HMC5883L magnetometer compass
If you want to deep on compasses, like the one we are going to setup, you can look at Outdoorsgenerations.com guide on how to use a compass: that’s a great guide explaining how to use this tool, also explaining some concepts like Magnetic Declination with the difference between True North & Magnetic North that we’re going to manage with HMC5883OL.
HMC5883L Main Features
This module is not new to the market and is one of the most used. Before digging into details, please note that the market is also full of the QMC5883L module. From what I know, this should make the same job but has a different hardware logic, so requiring a different code (and the code within this guide hardly will work for QMC5883L).
The HMC5883L is a multi-chip module able to measure magnetic sensing. It can communicate with an I2C digital interface with other devices in order to let creating applications such as low-cost compass, being used in many electronic fields like mobile phones, netbooks, consumer electronics, auto navigation systems, and personal navigation devices.
The module works with a low voltage supply (from 2.16 to 3.6V) and also has a low power consumption (100 μA).
HMC5883L has a 1° to 2° degrees heading accuracy, which is enough for a wide number of applications. It also allows setting its internal gain to increase resolution with a 3-bit gain control register. But increasing gain also increases noise effects.
The HMC5883L pinout has 5 PINs:
- Vcc -> common positive PIN for power supply, goes to the 3,3V PIN from Raspberry PI Pico
- GND -> common ground pin, goes to one of GND PINs from Raspberry PI Pico
- SCL -> Serial clock pin for I2C communication
- SDA -> Seria data pin for I2C communication
- DRDY -> Data Ready, Interrupt Pin. It is a PIN warning the master device when data are ready in registers to be read. It is optional and communication, as well as readings, work also without using this PIN.
More details on the HMC5883L chip are available from HMC5883L_3-Axis_Digital_Compass_IC datasheet pdf file available from Adafruit pages.
Finally, GY-271 HMC5883L module requires calibration in order to get the right values for application use. This tutorial also includes a code to calibrate your compass and get it simpler.
Please, be aware that this tutorial is intended for the Raspberry PI Pico microcontroller board, as the other Raspberry PI boards are computers (which require different coding).
What We Need
As usual, I suggest adding from now to your favourite e-commerce shopping cart all the needed hardware, so that at the end you will be able to evaluate overall costs and decide if continue with the project or remove them from the shopping cart. So, hardware will be only:
- A common computer (maybe with Windows, Linux or Mac). It can also be a Raspberry PI Computer board
- Raspberry PI Pico microcontroller (with a common micro USB cable)
- GY-271 HMC5883L module
- dupont wirings
Check hardware prices with the following links:
Please arrange cabling according to the following diagram, according to Raspberry PI Pico pinout:
Also, please find below some pictures from my small lab:
Getting MicroPython Codes
Start preparing your Raspberry PI Pico firmware according to my First steps with Raspberry PI Pico for Beginners tutorial.
To get HMC5883L working with MicroPython, you will need a copy of the following library:
This is the main library, forked from Gvalkov esp8266 MicroPython library for hmc5883l.
Moreover, you will need the following 2 MicroPython codes:
Copy all the 3 files to your Raspberry PI Pico root folder, so having the following files:
Set Your Location Declination
Before starting, we need to keep track in our library about the Declination.
Magnetic declination, or magnetic variation, is the angle on the horizontal plane between magnetic north (the direction the north end of a magnetized compass needle points, corresponding to the direction of the Earth’s magnetic field lines) and true north (the direction along a meridian towards the geographic North Pole). This angle varies depending on position on the Earth’s surface and changes over time.ref. https://en.wikipedia.org/wiki/Magnetic_declination
So, to keep our compass pointing to the Geographic north we need to add a correction that manages the difference between the 2 Norths and depends on our location. To get this, which is composed of 2 values (declination and inclination), please use the free online service available at https://www.magnetic-declination.com/, point it in your position and keep their degrees. The following picture shows what are mine results for my position (Rome):
Put only the integer part of those values (which are 3 and 58 in my case). Open the hmc5883l.py file and identify the following part of the code:
def __init__(self, scl=15, sda=14, address=0x1e, gauss='1.9', declination=(0, 0)):
change declination so that it keeps your position delta. In my case, this becomes:
def __init__(self, scl=15, sda=14, address=0x1e, gauss='1.9', declination=(3, 58)):
Save these changes
Calibrate the HMC5883L module
A very important phase of using our module with Raspberry PI Pico is calibration. Without calibration, you will get useless values and your applications will simply point in the wrong direction. The calibration has to be done only the first time, then the offset will work for the following usages.
There is to say that it calibrates only X and Y values, so getting correct results when the compass will rotate only on a horizontal plane. If someone is wishing to help in improving these calibration maths, please let me know so that I can improve the code also including the Z axis.
Back to us, I wrote a simple script which is registering the X and Y axes values for the scope, keeping their min and max values which will define offset corrections to be applied on hmc5883l.py.
To run the calibration, please put your HMC5883L module on a horizontal, plane surface so that you will be able to easily rotate it by 360 degrees.
So, from Thonny run the HMC5882Lcalibration.py code. During the execution, you will start seeing magnetic measures from HMC5883L module, with min and max values for X and Y axes. Rotate slowly the HMC5883L with its breadboard, to perform at least one complete 360 degrees round. The more rounds you do, the better results you will. Moreover, try to move slowly, especially at points near the X and Y min and max values. Once done, click on the Thonny shell area and press CTRL+C.
Differently from the Thonny “Stop” button, the CTRL+C will generate an interrupt signal that will trigger final calculations on the script, by getting an output like the following:
... ... X: 437.9800, Y: -453.8400, Z: -581.9400, Heading: 317° 57′ Xmin=8.54; Xmax=462.38; Ymin=-572.18; Ymax=-148.84 X: 434.3200, Y: -456.2800, Z: -577.0600, Heading: 317° 33′ Xmin=8.54; Xmax=462.38; Ymin=-572.18; Ymax=-148.84 X: 434.3200, Y: -452.6200, Z: -583.1600, Heading: 317° 47′ Xmin=8.54; Xmax=462.38; Ymin=-572.18; Ymax=-148.84 X: 434.3200, Y: -451.4000, Z: -584.3800, Heading: 317° 52′ Xmin=8.54; Xmax=462.38; Ymin=-572.18; Ymax=-148.84 Got ctrl-c Calibration corrections: xs=1 xb=-235.46 ys=1.072046 yb=360.51
In my case, I get the following parameters at the end:
- xs = 1
- xb = -235.46
- ys = 1.072046
- yb = 360.51
Re-open the hmc5883l.py file and, this time, identify the following part of code:
# Correction to be set after calibration xs=1 ys=1 xb=0 yb=0
Change also these parameters with the number you get in the calibration test. In my case, these become:
# Correction to be set after calibration xs=1 ys=1.072046 xb=-235.46 yb=360.51
Run the picoHMC5883L.py Code
At this point, you can discard the calibration script and use the picoHMC5883L.py code together with hmc5883l.py library.
You have just to run it from Thonny and you will get an output similar to the following:
MicroPython v1.17 on 2021-09-02; Raspberry Pi Pico with RP2040 Type "help()" for more information. >>> %Run -c $EDITOR_CONTENT X: 218.3800, Y: -25.3194, Z: -639.2800, Heading: 357° 21′ X: 220.8200, Y: -26.6273, Z: -638.0600, Heading: 357° 5′ X: 217.1600, Y: -27.9351, Z: -638.0600, Heading: 356° 38′ X: 209.8400, Y: -50.1694, Z: -639.2800, Heading: 350° 31′ X: 209.8400, Y: -42.3220, Z: -640.5000, Heading: 352° 34′ X: 211.0600, Y: -48.8615, Z: -634.4000, Heading: 350° 56′ X: 209.8400, Y: -46.2457, Z: -636.8400, Heading: 351° 32′ X: 218.3800, Y: -50.1694, Z: -638.0600, Heading: 351° 2′ X: 213.5000, Y: -47.5536, Z: -638.0600, Heading: 351° 25′ X: 215.9400, Y: -46.2457, Z: -639.2800, Heading: 351° 53′ X: 218.3800, Y: -58.0168, Z: -638.0600, Heading: 349° 5′ X: 220.8200, Y: -59.3246, Z: -639.2800, Heading: 348° 56′ X: 220.8200, Y: -61.9405, Z: -638.0600, Heading: 348° 18′ X: 218.3800, Y: -58.0168, Z: -639.2800, Heading: 349° 5′ X: 215.9400, Y: -50.1694, Z: -638.0600, Heading: 350° 53′
The Heading value will show the degrees to refer to the North. As you spin the module around the same horizontal plane, you will get the angle value.
As said in this tutorial, the calibration process involves only the X and Y axes. So any help on how to mathematically involve also the Z axis is really welcome and I will update the code. Anyway, for horizontal plane measurements, it will work giving you a reliable angle.
Wishing to test new devices with your Raspberry PI Pico board? Try looking at my Raspberry PI Pico tutorials for useful and funny projects!
We are sorry that this post was not useful for you!
Let us improve this post!
Tell us how we can improve this post?