Build an Arduino LED ring compass using the HMC5883L

Got Questions? Click here and post them in the Brainy-Bits Forum to get help!


In this second part tutorial we will again use the HMC5883L 3-Axis Compass module and use it to tell us were magnetic North is so we can find our way. 

To visually display the position of magnetic North, we will use an RGB NeoPixel ring that has 16 WS2812 RGB LEDs. 

We will use a library that was written to simplify extracting and calculating the heading information that the HMC5883L can provide.

You can find links for the libraries we used in this tutorial and the end of the page.


Arduino LED ring Compass HMC5883L

The HMC5883L 3-axis sensor is connected to 3.3V, GND, A4 and A5 from the Arduino.

*The sensor will also accept 5V voltage if you want to.


The NeoPixel RGB ring uses 5V and GND from the Arduino.

We then connect the DIN pin of the NeoPixel to digital pin 3.


It’s good to know that to get the most accurate readings as possible from the HMC5883L, it should be positioned as far way from metal, power cable, etc…  Since these will interfere with the accuracy.


We will use the Wire, FastLED and HMC5883L libraries in our code. 

The Wire library is used to communicate with the sensor and is included with the installation of the Arduino IDE software.

The FastLED is used to control the WS2812 RGB LED RING, link to download is at the end of the page.

The HMC5883L library is used to simplify extracting the heading information that will be used to find magnetic North. Again you can find a link to download at the end of the page.


As always for more information about the tutorial and explanation of the code please watch our tutorial video.


/* Start of Code */

#include <Wire.h>
#include "FastLED.h"
#include <HMC5883L.h>

#define NUM_LEDS 16 // Number of LEDs on Ring
#define DATA_PIN_RING 3 // Pin 3 connected to RGB Ring


HMC5883L compass;
int fixedHeadingDegrees; // Used to store Heading value

void setup()

// Set measurement range

// Set measurement mode

// Set data rate

// Set number of samples averaged

// Set calibration offset. See HMC5883L_calibration.ino
compass.setOffset(41, -196);

void loop()
Vector norm = compass.readNormalize();

// Calculate heading
float heading = atan2(norm.YAxis, norm.XAxis);

// Set declination angle on your location and fix heading
// You can find your declination on:
// (+) Positive or (-) for negative
// For Montreal,QC declination angle is -14'35W (negative)
// Formula: (deg + (min / 60.0)) / (180 / M_PI);
float declinationAngle = (14.0 - (35.0 / 60.0)) / (180 / M_PI);
heading -= declinationAngle;

// Correct for heading < 0deg and heading > 360deg
if (heading < 0)
heading += 2 * PI;

if (heading > 2 * PI)
heading -= 2 * PI;

// Convert to degrees
float headingDegrees = heading * 180/M_PI; 

// To Fix rotation speed of HMC5883L Compass module
if (headingDegrees >= 1 && headingDegrees < 240)
fixedHeadingDegrees = map (headingDegrees * 100, 0, 239 * 100, 0, 179 * 100) /100.00;
else {
if (headingDegrees >= 240)
fixedHeadingDegrees = map (headingDegrees * 100, 240 * 100, 360 * 100, 180 * 100, 360 * 100) /100.00;

int headvalue = fixedHeadingDegrees/18;
int ledtoheading = map(headvalue, 0, 15, 15, 0);


if (ledtoheading == 0){
leds_RING[15] = CRGB::Red; 
leds_RING[0] = CRGB::Green; 
leds_RING[14] = CRGB::Green;
else {
if (ledtoheading == 15){
leds_RING[0] = CRGB::Red; 
leds_RING[15] = CRGB::Green; 
leds_RING[1] = CRGB::Green;
else {
leds_RING[ledtoheading] = CRGB::Red;
leds_RING[ledtoheading+1] = CRGB::Green;
leds_RING[ledtoheading-1] = CRGB::Green;


/* End of Code */



Just copy the above Sketch code you want to use above in your Arduino IDE software to program your Arduino.


Your can download the HMC5883L library here: HMC5883L Library download

You can download the FastLED library here


Once downloaded, just extract the content of the zip files inside your “arduino/libraries” folder.

Got Questions? Click here and post them in the Brainy-Bits Forum to get help!

Leave a comment

Comments have to be approved before showing up