3-Axis Magnetometer with Arduino Uno

Last updated June 2019

Introduction

Welcome to ProteShea – in this project, we’ll be interfacing the HMC5883L 3-axis magnetometer to an Arduino Uno (rev 3). This device can measure the magnitude and direction of the Earth’s magnetic field. It’s a low-power device and can be found in mobile phones or navigation systems to provide an accurate compass heading. You can also use them to detect ferrous (contains iron) metals since the iron within the metal changes the magnetic field when it’s in close proximity to the sensor.

Don’t get lost out there, let’s get started!

Disclaimer

ProteShea, LLC is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com

Some links may be affiliate links, in which ProteShea, LLC earns a commission if you use that affiliate link. Please note that this is at no additional cost to you and helps us in creating more content.

20x4 Character LCD

Please see Project 10 on how to interface the 20×4 LCD in 4-bit mode. You should have pins 4, 6, and 11-14 of the LCD connected to Uno pins 2, 3, and 4-7, respectively. The LCD is mounted to the Modulus Canister via the 16-pin, right-angle female header soldered to the 1-to-1 link, as shown in the image below. We recommend wire wrapping 30 AWG wire to the male header pins so you can stack Adapticon on top of Modulus. Otherwise, you can use 12″ F/M jumper wires.

Wire wrapping 30 AWG wire to male header pins to mount LCD to Modulus
16x2 LCD Mounted to Modulus

HMC5883L 3-Axis Magnetometer

The HMC5883L 3-axis magnetometer can accurately measure the magnitude and direction of the Earth’s magnetic field in the x, y, and z direction. As a result, it can be used to provide a compass heading which is why it is also referred to as a digital compass. It is a low-powered device in a small form factor, allowing you to embed it in just about any project that requires a compass heading. A table is provided below that gives some specifications about the module.

HMC5883L Sensor Specifications

The breakout board from Although the datasheet for the HMC5883L IC consists of 5 pins: GND, VIN, DRDY, SCL, and SDA (image shown below). The GND and VIN pins are used to power the device. Although Parallax’s datasheet says that the module can operate from  2.7V to 6.5V, we had trouble getting the magnetometer to work at 5V and thus, we recommend using 3.3Vdc. The GND and VIN pins will connect to GND and 3.3V pins on the Uno, respectively.

To communicate with the device, we use the I2C protocol which only uses two pins, SCL and SDA. We use this to configure the registers on the device (i.e., setting the measurement mode and output rate), and acquire the X, Y, and Z magnetic field measurements. The device can only be 7-bit addressed at 0x1E, so you cannot have more than one of these devices on the I2C bus at one time. The SCL and SDA pins will connect to the Uno analog pins A5 and A4, respectively.

The DRDY (data ready) pin is used to tell the master device (Uno) that data is ready in the X, Y, and Z registers. The maximum output rate is 75Hz, but by using the DRDY pin, you can achieve up to 160Hz. You can connect this pin to an interrupt pin on the Uno for an efficient way to obtain the data. However, we will not be using this DRDY pin in this project.

Front view of HMC5883L breakout board
Pinout of HMC5883L Breakout Board

This device has a magneto-resistive sensor on each of its 3 axes to measure the magnetic fields. In the presence of a magnetic field, the resistance of these elements changes which causes a change in voltage across the outputs. This change in voltage is measured on each axis by the device’s 12-bit ADC and then the measurement is written to the corresponding X, Y, and Z 8-bit data registers. 

An address map of each register is shown in the table below. The registers highlighted in yellow indicate the register we will be reading from to obtain the measurements of the magnetic field on each axis. To learn more about the details of each register, please consult the datasheet for the HMC5883L IC.

Address Map for HMC5883L Registers

As you rotate the device about the X, Y, and Z axes, the magnetic field of each axis will change, as shown in the image below. The device must be oriented so that the X-Y plane (top plane of the board) is parallel to the ground, and also pointing upwards. 

Rotating the HMC5883L about the X, Y, and Z axes
Rotating the Device About the X, Y, and Z Axes

Mounting the Magnetometer to Adapticon

You could mount the magnetometer to Adapticon to provide stabilization. You will need an M2 male-to-female hex standoff, M2 nut, and an M2 screw to mount it. This keeps the X-Y plane parallel to the ground and allows you to rotate the FuelCan about the Z-axis, so you can get accurate compass headings. Make sure to use non-ferrous mounting hardware to avoid interference with the magnetic field. An image of the magnetometer mounted to Adapticon is shown below.

We just left the device attached to the 12″ jumper wires so we can freely move it around in all directions.

magnetometer mounted to adapticon canister with nylon M2 hardware
Magnetometer Mounted to Adapticon with Nylon Hardware

Solderless Breadboard

If you are using a solderless breadboard, use the schematic below to make the necessary connections for the 16×2 LCD. The magnetometer connects directly to the Uno with 12″ F/M jumper wires. We are using the 3V3 supply from the Uno instead of the 3V3 rail of the FuelCan since the 0.1″ pitch of the male header pins is too close to mount the test-lead clip cables next to each other.

NOTE: The schematic shows a 16×2 character LCD, but the 20×4 LCD is pin compatible. The only change you have to make is in the software. 

Breadboard Circuit Schematic

FuelCan Wiring

If you haven’t mounted the Uno onto the prototyping area of the FuelCan, go ahead and do that. If you are using a breadboard instead of Modulus, place the breadboard in the bottom storage compartment to limit the length of the jumper wires. You’ll need to supply +5V and GND to the power and ground rails on the breadboard by using the provided banana jack to test-lead clip cables. You will need two male header pins to mount the test-lead clips on the breadboard side. This is used to power the LCD. 

Next, plug the Type A side of the USB cable into USB1 receptacle and the Type B side into the Uno’s receptacle. Plug in the 6′ Type A to Type A cable – one end into the external USB connector and the other end into the host (i.e., computer). Power up the FuelCan with the AC-DC power adapter.

For additional information about the Fuelcan-910, click here.

Software Explanation

We communicate with the device via I2C, so be sure to include the Wire.h library. Before we can start acquiring data from the device, we first have to configure it using functions setOperatingMode() and setSamples() to set the operating mode to continuous and set the number of samples averaged per measurement output to 8. Everything else will be left as default. 

Now that the registers are configured, we can start acquiring the raw X, Y, and Z data with the function getXYZ(). This function grabs each of the 16-bit data for X, Y, and Z. The Wire.requestFrom() function within getXYZ() is used to request the 6 bytes of data.

Once we have the raw X, Y, and Z values, the function convert() is called to convert the raw count to Gauss (unit used to measure magnetic field). To make the conversion, we must consult Table 9 (Gain Settings) of the IC’s datasheet. Since the Gain was left as default, we are using a gain of 1090. We can simply divide each raw count by the gain to convert the count into units of Gauss.

The last thing to do before we output the data to the Serial Monitor is to calculate the heading. If the device is oriented with the X-Y plane parallel to the ground, we can use the X and Y values to obtain the vector that indicates the heading. This is done with the function getHeading(). The arctangent is calculated between the (X, Y) point and the x-axis, as shown in the image below. The reason we use atan2 is to be able to calculate the arctangent in all four quadrants.

Calculating the Compass Heading

atan2 returns the angle in radians, so we can convert this to degrees. A compass only gives a heading from 0 to 360 degrees, and if we get a heading outside of this range, we can add 360 if it is negative or subtract 360 if it is greater than 360. Now that the data has been normalized and the heading has been calculated, we can display it via the Serial Monitor.

The next example displays the data on the 20×4 LCD by calling the function writeLCD().

magnetometer data being displayed on 20x4 LCD
Displaying Data on 20x4 LCD

About Author

Eric Shea is the founder of ProteShea and is an electrical engineer. He wishes to have a major impact on bridging the gap between engineering theory and real-world applications. He has worked at Kratos Defense, SpaceX, Air Force Research Laboratory, and Polaris Industries. He received a M.S. in electrical engineering from the University of Pittsburgh and a B.S. in electrical engineering from the University of Florida.

Categories
Share on facebook
Share on twitter
Share on linkedin
Share on pinterest
Share on google
0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
ProteShea

Learn. Apply. Create.

290 NW Peacock Blvd #880143
Port Saint Lucie, FL 34988