The HMC5843 is a three axis magnetometer. There is now a newer one called HMC5883L but this one with the HMC5843 works also. Looking to buy or find the datasheetLook here.

You can get the breakout board for the HMC5843 from here. https://www.sparkfun.com/products/9371?
The new board is here. https://www.sparkfun.com/products/10530?

  • Simple I2C interface with adress at 0x1E
  • 2.5 to 3.3VDC supply range
  • Low current draw
  • 7 milli-gauss resolution

Dimensions: 0.5×0.5″ (12.7×12.7mm)

shop button

There were some problems with one of the capacitors on the innitial boards with the HMC5843. I was lucky enough not to have this.
If you are having problems you can get replacement capacitors.
http://sg.element14.com/kemet/c1206c106z8vac/capacitor-1206-10uf-10v/dp/9227903
http://nl.mouser.com/ProductDetail/TDK/C2012Y5V1A106Z/?qs=sGAEpiMZZMvQvaS66kI3ThQcAFV5t1/gCgHq1CKma/o=

HMC5843frontHMC5843back

There are also various libraries out there ready to make use of the HMC5843.
I found the best one for me a Fabio Varesano’s site. This because it already has some calibration factors included in the cpp code. This is based on the following logic.

To check the HMC5843 for proper operation, a self test feature in incorporated in which the sensor offset straps are  excited to create a nominal field strength (bias field) to be measured. To implement this self test, the least significant bits (MS1 and MS0) of configuration register A are changed from 00 to 01 (0x12 or 0b000xxx01). By placing the mode register into single-conversion mode (0x01), two data acquisition cycles will be made on each magnetic vector. The first acquisition will be a set pulse followed shortly by measurement data of the external field. The second acquisition will have the offset strap excited in the positive bias mode (~5.5mA in offset straps) to create about a 0.55 gauss self test field plus the external field. The first acquisition values will be subtracted from the second acquisition, and the net measurement will be placed into the data output registers.
If the configuration register B is left at the factory default value of 0x20, values around +715 ADC counts (0.55Ga * 1300 counts/Ga) will be placed in the data output registers. To leave the self test mode, change MS1 and MS0 bit of the configuration register A back to 0x00. Also change the mode register if single-conversion mode is not the intended next mode of operation.
Using the method described above in section self test operation, user can scale sensors’ sensitivity to match each other. Since placing device in positive bias mode (or alternatively negative bias mode) applies the same artificial field on all three axis, the resulting ADC measurement in data output registers can be used to scale the sensors.

There are quite some other libraries which also work.
http://code.google.com/p/ardupilot-mega/source/browse/#git%2Flibraries%2FAP_Compass%253Fstate%253Dclosed
http://eclecti.cc/hardware/hmc5843-magnetometer-library-for-arduino
https://bitbucket.org/rowoflo/hmc5843/src/d1d484ef0fe8

Inside the HMC5843 magnetometer are three magneto-resistive sensors, one for each axis. The effect of magnetic fields on these sensors adjust the current flow through the sensor.
By applying a scale to this current, we can tell the magnetic force (measured in Gauss) on this sensor.
For a detailed explanation to magneto-resistive sensors use this application note: Magneto-Resistive Sensors.
By combining information about two or more of these axis we can start to use the difference in the magnetic fields in the sensors to infer our bearing to magnetic north.
The Arduino sketch will tell us the which direction we are pointing in degrees, so it should read 0° for when we are point at magnetic north, and 180° when we are pointed south.
The compass will be a little off  if there are any ferreous material close to your compass. Also any kind of radio waves will cause interference (mobile phone, loud speakers)
It is possible to make some corrections for different kind of errors which can result from using the manetometer. Here are someexamples of correction.

HMC5843 Magnetic Declination

Compasses point to magnetic north, and not true north. The difference is called Magnetic declination.
Magnetic declination can vary depending on where you are and  it also changes slowly over time.
Here you can see the magnetic declination changing by year.

HMC5843Earth_Magnetic_Field_Declination_from_1590_to_1990

You can look up your Magnetic declination here. and also here http://magnetic-declination.com/#
For me (Netherlands) here is the output for this calculation. So for my location the magnetic declination is 0.5 degrees East at the moment.

HMC5843magnetic-declinationHMC5843magdeclination

Using the formula: angle in radians = angle in degrees * PI / 180 you can then calculate the result in mrad milli radians (8.7266 mrad)
In this link you can make this calculation on the web. http://www.analyzemath.com/Calculators_2/convert_degrees_radians.html
You can simply add this value in radians with the heading to correct for the magnetic declination. In this case +0.0087266 radians.
This is also done in the enclosed arduino mprogram.

HMC5843 Tilt compensation

A problem with this approach is that the HMC5843 needs to be held flat to function. If you hold the magentometer at right angles it will not work at all, and if you tilt it to 45 degrees the reading will be more inaccurate the further the mognetometer is tilted. This problem occurs because the magnetometer is only using the X and Y axis of the earths magnetic field . When the compass is not parallel to these axis the amount of magnetism felt by the magnetometer will change based on how out of alignment the magnetometer is to these axis.
So if we want to be able to compensate our magnetometer for tilt up to 40 degrees, we will need a way to include in our calculations the third axis, Z, which (when tilted) now collects the magnetic field lost by X and Y when they are tilted out of alignment.
Of course, one cannot simply add this value to the result to get an accurate heading. We first need to know how the device is tilted, so we know how to integrate the Z axis measurement properly, thus correct for our tilt. In other words, we need to know our orientation first. You can use a tripple axis  accelrometer eg BMA180 to provide a tilt corrected implementation.
The accelerometer is a device which measures acceleration. Simple enough, but there are two different types of acceleration: static acceleration (tilt) and dynamic acceleration (movement).
The accelerometer outputs a measurement telling the user in what direction on its axis force is being applied. Usually when dealing with an accelerometer, we want to get the orientation of the sensor, which basically means which way is the sensor tilted. When the device is tilted, pitch and roll angles are not 0°.  The diagram below the pitch and roll angles are measured by a 3 axis accelerometer. XM, YM and ZM (the measurement axis on the magnetometer) will be compensated to obtain Xh and Yh. Once have corrected the Xh and Yh  measurements, we can use the first equation to calculate our heading.

HMC5843tiltcompass-calc2

Xh = XM * cos(Pitch) + ZM * sin(Pitch)
Yh = XM * sin(Roll) * sin(Pitch) + YM * cos(Roll) – ZM * sin(Roll) * cos(Pitch)
Once we have tilt compensated Xh and Yh, we can now use the same equation as before to find our heading!
Heading = arctan(Yh/Xh)
Again the enclosed arduino program uses a BMA180 accelerometer with the HMC5843 to compensate for tilt.

HMC5843 Iron distortion compensation

The effect of a magnetic disturbance on the heading will be to distort the circle shown on the left . Magnetic distortions can be categorized as two types—hard iron and soft iron effects. Hard iron distortions arise from
permanent magnets and magnetized iron or steel on the compass platform. These distortions will remain constant and in a fixed location relative to the compass for all heading orientations. Hard iron effects add a constant
magnitude field component along each axes of the sensor output. This appears as a shift in the origin of the circle equal to the hard iron disturbance in the Xh and Yh axis (see middle graph). To compensate for hard iron distortion, the offset in the center of the circle must be determined. This is usually done by rotating the compass and platform in a circle and measure enough points on the circle to determine this offset. Once found, the (X,Y) offset can be stored in memory and subtracted from every reading. The net result will be to eliminate the hard iron disturbance from the heading calculation.
The soft iron distortion arises from the interaction of the earth’s magnetic field and any magnetically soft material surrounding the compass. Like the hard iron materials, the soft metals also distort the earth’s magnetic field lines. The difference is the amount of distortion from the soft iron depends on the compass orientation. Soft iron influence on the field values measured by X and Y sensors are depicted on the right.

HMC5843pic1HMC5843pic2HMC5843pic3

Hard and soft iron distortions will vary from location to location within the same platform. The magnetometer has to be mounted permanently to its platform to get a valid calibration. A particular calibration is only valid for that location of the magnetometer. If the compass is reoriented in the same location, then a new calibration is required. Most ferrous material in vehicles / aircraft  tend to have hard iron characteristics.
The best approach is to eliminate any soft iron materials near the compass and deal with the hard iron effects directly as described above.
In the enclosed arduino program we take care only of the hard iron effects and leave out the soft iron ones.

Connecting HMC5843 to the arduino.

Hooking you HMC5843 up to your arduino is pretty simple. The HMC5843 is an I2C device, a type 2-wire serial connection, so we just need to connect the SDA (Data) and SCL (Clock) lines to your Arduino for communication. On your Arduino SDA is on analog pin 4, and SCL is on analog pin 5. Other than these 2 lines, we just need to connect power(3.3v), ground and we are all set.
Although you can use a level converter such as  http://www.sparkfun.com/products/8745 or this one http://www.sparkfun.com/products/10403 it is not really required if you are able to disable the pullups on the Arduino. Fabio Varesano gives a description of how to do this on his site.
http://www.varesano.net/blog/fabio/how-disable-internal-arduino-atmega-pullups-sda-and-scl-i2c-bus
Here are two different level shift circuits if you decide to use this. The first one is based on the PCA9306 as per the link above the second one is from the second link.

HMC5843leveladapterHMC5843levelshift

Three different ways to adapt the voltages to the HMC5843.

Visualizing the output of the HMC5843

One of the things you want to do when you first start getting some data is to visualise the data. Below is the output from a processing program which does this.
The Arduino communicates with it displaying the heading as if it were a compass. Its rather cool. Here you can see a small video of what it looks like.
Here you can download the processing sketch including the required pictures and font. The arduino code needed you can view below. You can also download it here.
[spoiler]

/*
HMC5843_basic.pde - Basic reading example for the HMC5843 library
Copyright (C) 2011 Fabio Varesano <fabio at varesano dot net>
This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

*/

#include <Wire.h>
//#include <DebugUtils.h>
#include <HMC58X3.h>

HMC58X3 magn;

void setup(void) {
Serial.begin(38400);
Wire.begin();

// no delay needed as we have already a delay(5) in HMC5843::init()
magn.init(false); // Dont set mode yet, we'll do that later on.
// Calibrate HMC using self test, not recommended to change the gain after calibration.
magn.calibrate(1, 32); // Use gain 1=default, valid 0-7, 7 not recommended.
// Single mode conversion was used in calibration, now set continuous mode
magn.setMode(0);
}

void loop() {
int ix,iy,iz;
float fx,fy,fz;
delay(10);
// Get values, as ints and floats.
magn.getValues(&ix,&iy,&iz);
magn.getValues(&fx,&fy,&fz);
// also available HMC5843::getValues(float *xyz) you can pass to it an array of 3 floats

// a simple heading, assuming it's close to horizontal. See:
// M.J. Caruso. Applications of magnetic sensors for low cost compass systems.
// In Position Location and Navigation Symposium, IEEE, 2000. Available from:
// http://hnc.ru/lib/a%26c%20%28automatic%20%26%20controls%29/sensors/DataSheet/Magnit/Honeywell/lowcost.pdf

// Serial.print(" Heading: ");
float heading = atan2(fy, fx);
if(heading < 0) {
heading += 2 * M_PI;
}
Serial.println(heading * 180/M_PI);
delay(500);
// x and y axis are swapped above with respect to the above paper as our Z axis points to the sky while in the paper it points to the bottom
}

[/spoiler]

HMC5843magnetometer

Visualization of the HMC5843 outpout.

There is a another nice program for this at the evilmadscientist site. It is also written in processing.
Here you get a three dimentional view so that you can correct for the errors that i have described above by measuring them.
The chart below shows a two dimentional view of the magnetometer without iron distortion.  You can tell this because the circle is in the centre and circular.
The processing sketch had some small errors when using it for windows which i corrected. The modified sketch is here.

HMC5843circle

evilscientist visualization of HMC5843 data.

To put all the things together and get a tilt compensating, magnetic declination corrected and iron effect corrected magnetic compass bearing requires the use of an accelerometer as is shown in the fisrt part of this article.
For that reason it is the topic of another article.

Some other articles dealing with this chip.

http://www.ssec.honeywell.com/position-sensors/datasheets/sae.pdf
http://www.kionix.com/sites/default/files/AN006%20eCompass%20Rev%20C.pdf
http://powet.eu/2011/03/19/tilt-compensation-azimuth-pitch-le-roll/?lang=en
http://www.pololu.com/file/download/LSM303DLH-compass-app-note.pdf?file_id=0J434
http://www.sparkfun.com/products/10703
http://n0m1.com/2012/02/27/6dof-arduino-compass-accelerometer/
http://myahrs.wordpress.com/2012/04/20/magnetometer-thoughts/

3D scatter plot in processing

http://code.google.com/p/digital-ahrs/downloads/list

EEPROM storage of iron distortion compensation
http://www.bildr.org/forum/viewtopic.php?f=29&t=650
https://sites.google.com/site/wayneholder/self-driving-rc-car/steering-to-a-heading
https://github.com/n0m1/Comp6DOF_n0m1
http://home.arcor.de/dreckes/digCompass.htm
http://www.instructables.com/id/Car-No-05-Fourth-Stage-Strawberry-version/step8/To-be-continued/
http://forum.sparkfun.com/viewtopic.php?f=14&t=22252&start=0

 

Leave a Comment