HMC5883L
Datasheet link: http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf
Schematic
Dimension, schematic
Demo code
Arduino demo code
#define HMC5883_WriteAddress 0x1E // i.e 0x3C >> 1
#define HMC5883_ModeRegisterAddress 0x02
#define HMC5883_ContinuousModeCommand 0x00
#define HMC5883_DataOutputXMSBAddress 0x03
int regb=0x01;
int regbdata=0x40;
int outputData[6];
void setup()
{
Serial.begin(9600);
Wire.begin(); //Initiate the Wire library and join the I2C bus as a master
}
void loop() {
int i,x,y,z;
double angle;
Wire.beginTransmission(HMC5883_WriteAddress);
Wire.send(regb);
Wire.send(regbdata);
Wire.endTransmission();
delay(1000);
Wire.beginTransmission(HMC5883_WriteAddress); //Initiate a transmission with HMC5883 (Write address).
Wire.send(HMC5883_ModeRegisterAddress); //Place the Mode Register Address in send-buffer.
Wire.send(HMC5883_ContinuousModeCommand); //Place the command for Continuous operation Mode in send-buffer.
Wire.endTransmission(); //Send the send-buffer to HMC5883 and end the I2C transmission.
delay(100);
Wire.beginTransmission(HMC5883_WriteAddress); //Initiate a transmission with HMC5883 (Write address).
Wire.requestFrom(HMC5883_WriteAddress,6); //Request 6 bytes of data from the address specified.
delay(500);
//Read the value of magnetic components X,Y and Z
if(6 <= Wire.available()) // If the number of bytes available for reading be <=6.
{
for(i=0;i<6;i++)
{
outputData=Wire.receive(); //Store the data in outputData buffer
}
}
x=outputData[0] << 8 | outputData[1]; //Combine MSB and LSB of X Data output register
z=outputData[2] << 8 | outputData[3]; //Combine MSB and LSB of Z Data output register
y=outputData[4] << 8 | outputData[5]; //Combine MSB and LSB of Y Data output register
angle= atan2((double)y,(double)x) * (180 / 3.14159265) + 180; // angle in degrees
/*
Refer the following application note for heading calculation.
http://www.ssec.honeywell.com/magnetic/datasheets/lowcost.pdf
----------------------------------------------------------------------------------------
atan2(y, x) is the angle in radians between the positive x-axis of a plane and the point
given by the coordinates (x, y) on it.
----------------------------------------------------------------------------------------
This sketch does not utilize the magnetic component Z as tilt compensation can not be done without an Accelerometer
----------------->y
|
|
|
|
|
|
\/
x
N
NW | NE
|
W----------E
|
SW | SE
S
*/
//Print the approximate direction
Serial.print("You are heading ");
if((angle < 22.5) || (angle > 337.5 ))
Serial.print("South");
if((angle > 22.5) && (angle < 67.5 ))
Serial.print("South-West");
if((angle > 67.5) && (angle < 112.5 ))
Serial.print("West");
if((angle > 112.5) && (angle < 157.5 ))
Serial.print("North-West");
if((angle > 157.5) && (angle < 202.5 ))
Serial.print("North");
if((angle > 202.5) && (angle < 247.5 ))
Serial.print("NorthEast");
if((angle > 247.5) && (angle < 292.5 ))
Serial.print("East");
if((angle > 292.5) && (angle < 337.5 ))
Serial.print("SouthEast");
Serial.print(": Angle between X-axis and the South direction ");
if((0 < angle) && (angle < 180) )
{
angle=angle;
}
else
{
angle=360-angle;
}
Serial.print(angle,2);
Serial.println(" Deg");
delay(100);
}
Demo Code with library V2
Wiring
- Arduino GND -> HMC5883L GND
- Arduino 3.3V -> HMC5883L VCC
- Arduino A4 (SDA) -> HMC5883L SDA
- Arduino A5 (SCL) -> HMC5883L SCL
Library
- get the library Here and put in your library folder.
Simplied Arduino Code
- Use the example or demo code below, Open the Arduino serial monitor to see the results (X plane angle, Y plane angle, Z plane angle):
#include <Wire.h>
#include <HMC5883L.h>
HMC5883L compass;
void setup()
{
Serial.begin(9600);
Wire.begin();
compass = HMC5883L();
compass.SetScale(1.3);
compass.SetMeasurementMode(Measurement_Continuous);
}
void loop()
{
MagnetometerRaw raw = compass.ReadRawAxis();
MagnetometerScaled scaled = compass.ReadScaledAxis();
float xHeading = atan2(scaled.YAxis, scaled.XAxis);
float yHeading = atan2(scaled.ZAxis, scaled.XAxis);
float zHeading = atan2(scaled.ZAxis, scaled.YAxis);
if(xHeading < 0) xHeading += 2*PI;
if(xHeading > 2*PI) xHeading -= 2*PI;
if(yHeading < 0) yHeading += 2*PI;
if(yHeading > 2*PI) yHeading -= 2*PI;
if(zHeading < 0) zHeading += 2*PI;
if(zHeading > 2*PI) zHeading -= 2*PI;
float xDegrees = xHeading * 180/M_PI;
float yDegrees = yHeading * 180/M_PI;
float zDegrees = zHeading * 180/M_PI;
Serial.print(xDegrees);
Serial.print(",");
Serial.print(yDegrees);
Serial.print(",");
Serial.print(zDegrees);
Serial.println(";");
delay(100);
}