Magnetometer Compass with Raspberry PI Pico: GY-271 HMC5883L wiring and use with MicroPython


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 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.

HMC5883L pinout

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 to continue with the project or remove them from the shopping cart. So, hardware will be only:

raspberry pi pico microcontroller

Check hardware prices with the following links:

amazon raspberry pi pico box
Amazon GY-271 hmc5883l box
Amazon Breadboard box
Amazon Dupont Wiring box

Step-by-Step Procedure

Prepare Wiring

Please arrange cabling according to the following diagram, according to Raspberry PI Pico pinout:

Raspberry PI Pico HMC5883L wiring diagram

Also, please find below some pictures from my small lab:

Raspberry PI Pico HMC5883L details 01
Raspberry PI Pico HMC5883L details 02
Raspberry PI Pico HMC5883L details 03
Raspberry PI Pico HMC5883L details 04
Raspberry PI Pico HMC5883L details 05

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:

Raspberry PI Pico HMC5883L folder 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.


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, point it in your position and keep their degrees. The following picture shows what are mine results for my position (Rome):

Rome Magnetic Declination

Put only the integer part of those values (which are 3 and 58 in my case). Open the 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

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 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:

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 file and, this time, identify the following part of code:

# Correction to be set after calibration

Change also these parameters with the number you get in the calibration test. In my case, these become:

# Correction to be set after calibration

Run the Code

At this point, you can discard the calibration script and use the code together with 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.
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.

Final Thoughts

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.

What’s Next

Wishing to test new devices with your Raspberry PI Pico board? Try looking at my Raspberry PI Pico tutorials for useful and funny projects!


How useful was this post?

Click on a star to rate it anonymously!

Average rating 4.7 / 5. Vote count: 12

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?