HMC6343 3-axis Compass Hookup Guide
Example Code
Now that your electronic compass breakout is electrically connected to your Arduino, it's time to dive into the code. The full library (SFE_HMC6343_Library) and example sketches can be found in the Github Repository. If you need help with GitHub, visit our tutorial. The same goes for installing an Arduino library.
Once the library is installed, open the example labeled HMC6343_basics.ino. This sketch will teach you how to get a heading direction, pitch, and roll angles as well as accelerometer measurements.
The first lines of this example sketch include the necessary libraries, one for I2C and the other so we can declare and interact with the compass object.
language:c
// Libraries for I2C and the HMC6343 sensor
#include <Wire.h>
#include "SFE_HMC6343.h"
SFE_HMC6343 compass; // Declare the sensor object
The variable compass
will be used for all interactions with the sensor itself.
Next we use the setup()
function in initialize serial communication, I2C bus, and the HMC6343. If the HMC6343 is not detected, an error message will be reported to the Serial Monitor. We also wait half a second before we try to initialize the HMC6343 since it takes that long to be responsive after being powered on.
language:c
void setup()
{
// Start serial communication at 115200 baud
Serial.begin(115200);
// Give the HMC6343 a half second to wake up
delay(500);
// Start I2C
Wire.begin();
// Initialize the HMC6343 and verify its physical presence
if (!compass.init())
{
Serial.println("Sensor Initialization Failed\n\r"); // Report failure, is the sensor wiring correct?
}
}
In the loop()
function, we call two functions to read the sensor data and two more to print the data to the Serial Monitor in an easily readable format. compass.readHeading()
is a library function that commands the sensor to collect heading direction, pitch angle, and roll angle and then store these values. We will see how to use and print these values in the printHeadingData()
function. compass.readAccel()
gets a reading from the IC's 3-axis accelerometer values and these are used and printed in printAccelData()
. Here is the loop in full:
language:c
void loop()
{
// Read, calculate, and print the heading, pitch, and roll from the sensor
compass.readHeading();
printHeadingData();
// Read, calculate, and print the acceleration on the x, y, and z axis of the sensor
compass.readAccel();
printAccelData();
// Wait for two seconds
delay(2000); // Minimum delay of 200ms (HMC6343 has 5Hz sensor reads/calculations)
}
After calling compass.readHeading()
, the variables compass.heading
, compass.pitch
, and compass.roll
carry the heading, pitch, and roll values given by the sensor in tenths of degrees. In the printHeadingData()
function, we print these raw values and also print the value converted to degrees. Let's look at how we do this using the heading direction as an example:
language:c
Serial.print("Heading: ");
Serial.print(compass.heading); Serial.print(" "); // Print raw heading value
Serial.print((float) compass.heading/10.0);Serial.write(176);Serial.println(); // Print heading in degrees
In the first line, we print the label. In the second line, we print the actual raw value returned by the sensor, compass.heading
and a couple spaces. In the third line, we scale the heading direction by dividing it by 10 so that we can print it in degrees. Serial.write(176)
draws a degree symbol and then we print a new line.
Within printHeadingData()
, the same process is followed for pitch and roll. When running the program, the Serial Monitor's output of this function will look like the following:
language:c
Heading Data (Raw value, in degrees):
Heading: 3249 324.90°
Pitch: 28 2.80°
Roll: 24 2.40°
If you have the breakout board parallel to the ground, pitch and roll will be about 0 degrees and you will see the heading angle change as you slowly rotate the board. Try angling the board relative to the X and Y axis and see how that affects your pitch and roll angles.
Printing accelerometer values is very similar. Under the printAccelData()
function, we print the acceleration measured on the x axis as follows:
language:c
Serial.print("X: ");
Serial.print(compass.accelX); Serial.print(" "); // Print raw acceleration measurement on x axis
Serial.print((float) compass.accelX/1024.0);Serial.println("g"); // Print x axis acceleration measurement in g forces
Again, in the first line we print the label. On the second line, we print the raw acceleration measurement felt on the x axis using the variable compass.accelX
. Acceleration measurements for y and z are accessed with the variables compass.accelY
and compass.accelZ
respectively. On the third line above, we scale the raw value by dividing it by 1024 to get the accleration in g forces. We print that scaled value as well as the unit symbol, g.
Here an example of what you'll see in the Serial Monitor after calling the printAccelData()
function:
language:c
Accelerometer Data (Raw value, in g forces):
X: -52 -0.05g
Y: -44 -0.04g
Z: -1047 -1.02g
At the end of loop()
there is a delay of two seconds before new sensor data is read and printed. The fastest you can consecutively acquire new sensor readings is 5Hz or every 200ms.
Advanced Features
All the additional features of the HMC6343 device library are covered in the HMC6343_advanced
sketch. However, I'll overview some of the more appealing features here.
If you want to save power, you'll want to be able to use the sleep or standby modes. The IC in standby draws 1.0mA as opposed to 4.5mA under normal run mode operation. Under sleep mode, the IC only uses 10µA however it takes the device longer to wake up after entering that low power state. Here are examples of how the two modes can be entered and exited:
language:c
// Enter and exit standby mode (4.5mA draw in run mode, 1.0mA in standby)
// HMC6343 requires 1 ms before it can receive commands after switching modes
compass.enterStandby();
delay(1);
compass.exitStandby(); // Exit standby, enter run mode (default)
delay(1);
// Enter and exit sleep mode (4.5mA draw in run mode, 10uA in sleep)
// HMC6343 requires 1ms after entering sleep and 20ms after exiting before it's able to receive new commmands
compass.enterSleep();
delay(1);
compass.exitSleep();
delay(20);
If you don't want to mount the HMC6343 breakout board parallel to the ground, then you'll need to know how to set the new orientation of the board in order to get correct heading, pitch, and roll values. Here is a list of the three possible orientations and the command to configure the HMC6343 to use a new orientation:
language:c
// Possible orientations:
// LEVEL X = forward, +Z = up (default)
// SIDEWAYS X = forward, +Y = up
// FLATFRONT Z = forward, -X = up
compass.setOrientation(LEVEL);
delay(1); // 1 ms before sensor can receive commands after setting orientation
Those are the most important additional features. However, the advanced example covers reading/printing raw 3-axis magnetometer values and raw 'tilt' values (pitch, roll, and temperature). It also covers reading the primary status register (OPMode1) as well as reading and writing to the EEPROM registers of the sensor. There is also a command to reset the processor of the HMC6343 as well as a way to enter and exit user calibration mode.
While the library provides a convenient way to do all these things (every HMC6343 command in the datasheet is used by the library), if you want to know the details of each EEPROM register or how to properly calibrate the sensor, consulting the datasheet is a must.
My hope is that the library allows you to read sensor data and interact with the HMC6343 as easily as possible and allows you to quickly integrate the breakout board into your project.