HMC5883L Arduino Compass Tutorial

HMC5883L 3-Axis Compass Module Arduino interface

The compass module consists of an HMC5883L three-axis (Cartesian axes x, y, and z) magnetic field chip which consists of 3 magneto-resistive sensors arranged in axes perpendicular to each other.

Magneto-resistive sensors work by the Magneto-resistance property of a material. That is, the ability to change its value of electrical resistance with respect to the applied external magnetic field. Thus it can generate a differential output in relation to the intensity of the incident magnetic field in the sensitive axis directions. Hence an HMC5883L 3-Axis module can also be used to measure the magnetic field.

HMC5883L module Arduino pin connection

Arduino Pin HMC5883L  pin
3.3V VCC
GND GND
Analog input pin A4 SDA (Serial Data – I2C Master/Slave Data)
Analog input pin A5 SCL (Serial Clock – I2C Master/Slave Clock)

The hmc5883l module uses a communication standard of IIC or 12C (Inter-Integrated Circuit) protocol.
DRDY (Data Ready) is an optional connection and so it is not used in the circuit.

hmc5883l arduino connection circuit, gy-273 hmc5883l arduino

To run programs with this module arduino Library for HMC5883L is required to be installed, here we are using an Adafruit Sensor framework library.

Download a Library file for Sensor and HMC5883. Then extract it to your library folder in your Arduino installation,

Or add the ZIP file by,  Sketch –> Include Library –> Add.ZIP Library.

True bearing arduino digital compass

The true bearing compass is the most commonly used type of compass, which measures the bearing to a point by an angle measured in degrees from the north in a clockwise direction. The true bearing is referred to as True North-based azimuths or the bearing.arduino digital compass The compass shows heading degree measurements from 0° to 360°. The four cardinal points of the compass are North – 0° or 360°, East – 90°, South – 180°, and West  – 270° in a clockwise direction. The reference plane for an azimuth will be true north at a 0° azimuth.

Here the 0° to 360° angular measurement will be in the direction of the x-axis of the module with the north point. The direction of the axes with respect to the module position is labeled in the module.

Hmc5883l heading code

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

void setup(void)
{
  Serial.begin(9600);
}

void loop()
{
  sensors_event_t event;
  mag.getEvent(&event);
  float heading = atan2(event.magnetic.y, event.magnetic.x);
  float declinationAngle = 0.22;
  heading += declinationAngle;
  if (heading < 0) {
    heading += 2 * PI;
  }
  if (heading > 2 * PI) {
    heading -= 2 * PI;
  }
  float headingDegrees = heading * 180 / M_PI;
  Serial.print("Heading : ");
  Serial.print(headingDegrees);
  Serial.println(" degree");
  delay(500);
}

Conventional bearing Arduino compass

A magnetic compass uses the earth’s magnetic field to determine the directions relative to the cardinal points.

The four cardinal points are north, east, south, and west represented as N, E, S, W directions. In the clockwise direction, the cardinal points are followed in the sequence as North, East, South, and West; with a right angle from one cardinal to another.

The conventional bearing or compass bearing of a point is the angle of degrees east or west from north or south cardinal points.digital compass project, conventional compass

 The intermediate directions between the four cardinal points are northeast (NE), south-east (SE), south-west (SW), and north-west (NW).

The direction of a point in a conventional bearing is denoted as the angle measured in degrees from the north or south point towards the East or West direction.

eg: – true bearing  in degrees from 0 to 360 denoted in conventional bearing,

True bearing               Conventional  bearing

45°                                     N 45° E

100°                                   S 80°  E

210°                                   S 30° W

300°                                   N 60° W

The heading of the X-axis of the HMC5883L module obtains the true bearing values from 0° to 360°  and is converted to a conventional bearing form, through determining the position of heading direction in the four quadrants from 0° to 360°.

Conventional bearing Arduino compass code

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

void setup(void)
{
  Serial.begin(9600);
}

void loop()
{
  sensors_event_t event;
  mag.getEvent(&event);
  float heading = atan2(event.magnetic.y, event.magnetic.x);
  float declinationAngle = 0.22;
  heading += declinationAngle;
  if (heading < 0) {
    heading += 2 * PI;
  }
  if (heading > 2 * PI) {
    heading -= 2 * PI;
  }
  float headingDegrees = heading * 180 / M_PI;
  if (headingDegrees == 0 || headingDegrees == 360 ) {
Serial.println("N");
}
if (headingDegrees > 0 && headingDegrees < 90 ) {
Serial.print("N");
// Degree from north towards east direction
Serial.print(headingDegrees);
Serial.write(176);
Serial.println("E");
}
if (headingDegrees == 90) {
Serial.println("E");
}
if (headingDegrees > 90 && headingDegrees < 180 ) {
// Degree from south towards east direction
headingDegrees = 180 - headingDegrees;
Serial.print("S");
Serial.print(headingDegrees);
Serial.write(176);
Serial.println("E");
}
if (headingDegrees == 180) {
Serial.println("S");
}
if (headingDegrees > 180 && headingDegrees < 270 ) {
// Degree from south towards west direction
headingDegrees = headingDegrees - 180;
Serial.print("S");
Serial.print(headingDegrees);
Serial.write(176);
Serial.println("W");
}
if (headingDegrees == 270) {
Serial.println("W");
}
if (headingDegrees > 270 && headingDegrees < 360 ) {
// Degree from North towards west direction
headingDegrees = 360 - headingDegrees;
Serial.print("N");
Serial.print(headingDegrees);
Serial.write(176);
Serial.println("W");
}
delay(500);
}

Hmc588l compass module raw and scaled axes values

Using this program the serial monitor displays the Magnetic vector values of the magnetic field on three axes (X, Y, and Z axes) in micro-Tesla (uT).

Magnetic vector values code

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

void setup() 
{
  Serial.begin(9600);
}

void loop(void) 
{
  sensors_event_t event; 
  mag.getEvent(&event);
  Serial.print("X axis: "); Serial.print(event.magnetic.x); Serial.print(" uT   ");
  Serial.print("Y axis: "); Serial.print(event.magnetic.y); Serial.print(" uT   ");
  Serial.print("Z axis: "); Serial.print(event.magnetic.z); Serial.println(" uT");
  delay(500);
}

Digital compass – Arduino + Processing + Hmc5883l Magnetometer

Arduino + Processing code »

20 Responses

  1. Fareed Ahmad says:

    Can you provide the libraries for this code?

  2. Manoj Madanani says:

    Hello Sir, I have referred code from your website , on compass code with arduino ,,

    #include
    #include
    #include

    Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

    void setup(void)
    {
    Serial.begin(9600);
    }

    void loop()
    {
    Serial.println(“1”);
    sensors_event_t event;
    Serial.println(“2”);
    mag.getEvent(&event); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< AT THIS POINT
    Serial.println("3");
    float heading = atan2(event.magnetic.y, event.magnetic.x);
    float declinationAngle = 0.22;
    heading += declinationAngle;
    Serial.println("2");
    .
    .
    .

    But the see the point I have commented at this point the programs stucks. I have debugged with the print statement so the Serial Monitor gives 1 than 2 and than stuck

    • admin says:

      Did you have properly installed Adafruit_Sensor.h and Adafruit_HMC5883_U.h library functions?

      • Dom says:

        How do I install Adafruit_Sensor.h and Adafruit_HMC5883_U.h library function? Thank you

        • admin says:

          Download zip files, then in the Arduino IDE go to Sketch –> Include Library –> Add.ZIP Library
          OR sketch > Manage libraries > Search Adafruit_Sensor & Adafruit_HMC5883 libraries > Install.

  3. ie kara says:

    Hi, I have a problem with sensor results. Actualy there is no problem with sensor setup and codes. But if the sensor moved to vertical line (changed angel) the result is comes different. How can i take fix result? I just want X arrow side compas degree. I need your help. Thank you.

  4. Doan says:

    I get the error ‘import’ does not name a type; did you mean ‘qsort’?
    How to fix it?

    • admin says:

      In which IDE you used to run the code, in Arduino IDE or in the Processing IDE?
      Upload the Arduino code to the board using Arduino IDE and run the processing code in processing IDE.

  5. Doan says:

    Thank you for sharing, I have followed your instructions but until running Processing IDE, my compass did not turn.
    And how can this command be modified to run normally?
    port_1 = new Serial(this, Serial.list()[1], 9600);
    How to determine the port port that I am 0.1,2, or a certain number, on my Arduino is COM4

    • admin says:

      you can add this line “printArray(Serial.list());” to list all serial ports.
      If your Arduino is in COM4 then it is “Serial.list()[3]”.

  6. toni says:

    Hey sir! is it possible to check if there is a wire in the wall with this sensor and is there a diffrent code that i should use to check the change in the magnetic field???

  7. toni says:

    Hey sir can you help me , I have to measure intensity of magnetic field with this sensor what code should I write what should I change, I got to do this for a school project!

    • admin says:

      Use the code under the heading “Magnetic vector values code” which gives the magnetic field in each vector x,y,z in micro-Tesla. You can take one of these vectors (for example x-axis) to measure the magnetic field with respect to the direction of the same vector labeled (x-axis) in your HMC5883L sensor.

  8. ThetPaingPhyoe says:

    I wanna know M_PI is what mean in float headingDegrees = heading * 180 / M_PI;

  9. cent says:

    Hello thanks for the tutorial

    I have some problems, when tested in Arduino IDE, the output only showed 273.61 deg even though I rotated the sensor, while in the Processing IDE, it returned with

    map(NaN, 0, 360, 0, 6.283) called, which returns NaN (not a number)

    Was there something that I miss? Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *