Triple Axis Magnetometer HMC5883L interfacing with AVR ATmega16

Overview of Magnetometer


HMC5883L Magnetometer Module


HMC5883L is a 3-axis magnetometer that is used for measuring the direction and magnitude of the Earth’s magnetic field. It is used for low cost compassing and magnetometry.

It measures the Earth’s magnetic field value along the X, Y, and Z axes from milli-gauss to 8 gauss.

It can be used to find the direction of the heading of the device.

It uses the I2C protocol for communication with the microcontroller.

For more information about Magnetometer HMC5883L and how to use it, refer to the topic HMC5883L Magnetometer Module in the sensors and modules section.


Programming for HMC5883L Magnetometer

Let’s interface the triple-axis magnetometer HMC5883L module with AVR ATmega16 and calculate its heading angle.

HMC5883L uses the I2C protocol for communication. Here we are connecting AVR based ATmega16 as a master device and HMC5883L as a slave device. Its I2C device address is 0x3C. Its read and write operation addresses are:

Slave device write address (SLA+W): 0x3C

Slave device read address (SLA+R): 0x3D


Connection Diagram of HMC5883L with ATmega16/32

Interfacing HMC5883L Magnetometer Module With ATmega 16 


HMC5883L Programming steps

First, we need to set configuration register A for an average of 8-sample measurement with a 15 Hz default data output rate

Set Gain using Configuration Register B i.e. here it's 0xA0. (or we can choose any other desired gain)

Select Continuous measurement mode of operation in Mode Register. Hence Mode Register value will become 0x00.

After initialization, Write the start location of output data registers X, Y, and Z i.e. 0x03, and read all six registers' raw values.

Calculate the Heading value by using the formula,

Magnetic Heading = atan2(\frac{y}{x})   (Radian)

True Heading = Magnetic Heading + declination Angle    (Radian)


HMC5883L Magnetometer Code for ATmega16/32

 * ATmega16_Magnetometer.c

#define F_CPU 8000000UL		/* Define CPU Frequency e.g. here its 8MHz */
#include <avr/io.h>		/* Include AVR std. library file */
#include <stdlib.h>		/* Include std. library file */
#include <math.h>		/* Include math header file */
#include "LCD_16x2_H_file.h"	/* Include LCD header file */
#include "I2C_Master_H_file.h"	/* Include I2C header file */
#define PI	3.14159265359	/* Define Pi value */
#define Declination	-0.00669/* Define declination of location from where measurement going to be done. e.g. here we have added declination from location Pune city, India. we can get it from */

void Magneto_init()		/* Magneto initialize function */
	I2C_Start(0x3C);	/* Start and write SLA+W */
	I2C_Write(0x00);	/* Write memory location address */
	I2C_Write(0x70);	/* Configure register A as 8-average, 15 Hz default, normal measurement */
	I2C_Write(0xA0);	/* Configure register B for gain */
	I2C_Write(0x00);	/* Configure continuous measurement mode in mode register */
	I2C_Stop();		/* Stop I2C */

int Magneto_GetHeading()
	int x, y, z;
	double Heading;
	I2C_Start_Wait(0x3C);	/* Start and wait for acknowledgment */
	I2C_Write(0x03);	/* Write memory location address */
	I2C_Repeated_Start(0x3D);/* Generate repeat start condition with SLA+R */
	/* Read 16 bit x,y,z value (2's complement form) */
	x = (((int)I2C_Read_Ack()<<8) | (int)I2C_Read_Ack());
	z = (((int)I2C_Read_Ack()<<8) | (int)I2C_Read_Ack());
	y = (((int)I2C_Read_Ack()<<8) | (int)I2C_Read_Nack());
	I2C_Stop();		/* Stop I2C */
	Heading = atan2((double)y,(double)x) + Declination;
	if (Heading>2*PI)	/* Due to declination check for >360 degree */
		Heading = Heading - 2*PI;
	if (Heading<0)		/* Check for sign */
		Heading = Heading + 2*PI;
	return (Heading* 180 / PI);/* Convert into angle and return */


int main(void)
	char buffer[10];
	LCD_Init();		/* Initialize LCD */
	I2C_Init();		/* Initialize I2C */
	Magneto_init();		/* Initialize magneto */
	LCD_String("Magnetometer");/* Print title on LCD */
	while (1)
		itoa (Magneto_GetHeading(),buffer,10);
		LCD_String_xy(2,0,"Heading = ");/* Print Heading on 2nd row of LCD */
		LCD_Char(0xDF);	/* ASCII of Degree symbol */
		LCD_String("   ");


Note that heading also gets affected by device tilt and nearby magnetic devices effect. There are compensating methods provided in the attached document.


Video of HMC5883L Magnetometer Angle Measurement using ATmega16/32

Components Used

ATmega 16
ATmega 16
HMC5883L Magnetometer Module
Magnetometer HMC5883L is developed by Honeywell. It gives the heading direction.
LCD16x2 Display
LCD16x2 Display


ATmega16 Magnetometer Project file Download
Applications of Magnetic Sensors for Low Cost Compass Systems Download
Applications of Magneto-resistive Sensors in Navigation Systems Download
HMC5883L 3-Axis Digital Compass IC Download