Arduino HMC5883 magnetometer – a tutorial

This tutorial shows how to explore an inexpensive HMC5883 3 axis magnetometer module with Arduino.

It is an ideal low cost project for a first exploration of explore I2C, and the basis for a digital compass. This particular module breaks out DRDY which is useful for interrupt driven applications.

Fig 1
Fig 1

Fig 1 shows the test setup:

  • at the top is a Arduino Pro 328 with Opti bootloader and FTDI adapter for programming;
  • middle is the HMC5883L module; and
  • bottom is a Logic Shrimp for logic tracing.

The code

/*
An Arduino code example for interfacing with the HMC5883

by: Jordan McConnell
SparkFun Electronics
created on: 6/30/11
license: OSHW 1.0, http://freedomdefined.org/OSHW

Analog input 4 I2C SDA
Analog input 5 I2C SCL
*/

//Modified by Owen Duffy 2013/12/10 for Arduino 1.05 compatibility

#include <Wire.h> //I2C Arduino Library

#define address 0x1E //0011110b, I2C 7bit address of HMC5883

void setup(){
//Initialize Serial and I2C communications
Serial.begin(9600);
Wire.begin();

//Put the HMC5883 IC into the correct operating mode
Wire.beginTransmission(address); //open communication with HMC5883
Wire.write(0x02); //select mode register
Wire.write(0x00); //continuous measurement mode
Wire.endTransmission();
}

void loop(){

int x,y,z; //triple axis data

//Tell the HMC5883 where to begin reading data
Wire.beginTransmission(address);
Wire.write(0x03); //select register 3, X MSB register
Wire.endTransmission();


//Read data from each axis, 2 registers per axis
Wire.requestFrom(address, 6);
if(6<=Wire.available()){
x = Wire.read()<<8; //X msb
x |= Wire.read(); //X lsb
z = Wire.read()<<8; //Z msb
z |= Wire.read(); //Z lsb
y = Wire.read()<<8; //Y msb
y |= Wire.read(); //Y lsb
}

//Print out values of each axis
Serial.print("x: ");
Serial.print(x);
Serial.print(" y: ");
Serial.print(y);
Serial.print(" z: ");
Serial.println(z);

delay(250);
}

Above shows the example source code. The project uses v1.05 Arduino IDE. Arduino libraries to not maintain backwards compatibility and this code may not run in earlier versions. The project uses an example sketch from Sparkfun. The source code is modified for compatibility with Arduino v1.05 Wire library.

Fig03

Fig 3 shows the waveforms captured on the SCL and SDA pins, the I2C
transaction to read the clock. Only the first bytes of the transaction are
shown.

 

Fig 4:
Index Time Hex
0 -1.75 μs START
1 3.25 μs 0x3c
2 93.75 μs ACK
3 98.75 μs 0x03
4 190.00 μs ACK
5 210.00 μs STOP
6 220.00 μs START
7 225.00 μs 0x3d
8 315.50 μs ACK
9 320.50 μs 0x01
10 410.25 μs ACK
11 415.25 μs 0x63
12 506.50 μs ACK
13 511.50 μs 0x04
14 602.75 μs ACK
15 607.75 μs 0x31
16 699.00 μs ACK
17 704.00 μs 0x00
18 795.25 μs ACK
19 800.25 μs 0x63
20 891.25 μs NACK
21 912.75 μs STOP

Fig 4 shows an analysis of the complete read transaction.

The student of I2C should be able to take the data sheet and the dump
in Fig 5 and verify the reading process.

Links

Changes

Version Date Description
1.01 07/12/2013 Initial.
1.02  20/07/2015 Copied from VK1OD.net
1.03
1.04
1.05