I have a HMC5883L module connected to an Arduino Mega 2560 via +5, GND, SCL, SDA. The Arduino code is from the MagMaster-master example, as follows:
#include "Wire.h"
#include "HMC5883L.h"
HMC5883L compass; //Copy the folder "HMC5883L" in the folder "C:\Program Files\Arduino\libraries" and restart the arduino IDE.
float xv, yv, zv;
void setup()
{
Serial.begin(9600);
Wire.begin();
compass = HMC5883L();
setupHMC5883L();
}
void loop()
{
getHeading();
Serial.flush();
Serial.print(xv);
Serial.print(",");
Serial.print(yv);
Serial.print(",");
Serial.print(zv);
Serial.println();
delay(100);
}
void setupHMC5883L()
{
compass.SetScale(0.88);
compass.SetMeasurementMode(Measurement_Continuous);
}
void getHeading()
{
MagnetometerRaw raw = compass.ReadRawAxis();
xv = (float)raw.XAxis;
yv = (float)raw.YAxis;
zv = (float)raw.ZAxis;
}
When I run the code, I get the following output on the serial monitor
-15872.00,-27601.00,1.00
-15872.00,3264.00,1.00
-15872.00,19536.00,1.00
-15872.00,-18208.00,1.00
-15872.00,12401.00,1.00
-15872.00,-27647.00,1.00
-15872.00,1170.00,1.00
-15872.00,17442.00,1.00
-15872.00,-21326.00,1.00
-15872.00,7235.00,1.00
-15872.00,21715.00,1.00
-15872.00,-15261.00,1.00
-15872.00,15604.00,1.00
-15872.00,-22396.00,1.00
-15872.00,7189.00,1.00
-15872.00,23717.00,1.00
-15872.00,-13259.00,1.00
-15872.00,14534.00,1.00
-15872.00,-24490.00,1.00
-15872.00,3303.00,1.00
-15872.00,17527.00,1.00
-15872.00,-20473.00,1.00
-15872.00,9368.00,1.00
-15872.00,26664.00,1.00
-15872.00,-8008.00,1.00
-15872.00,8265.00,1.00
-15872.00,23769.00,1.00
-15872.00,-14231.00,1.00
-15872.00,13562.00,1.00
-15872.00,-24438.00,1.00
-15872.00,3099.00,1.00
-15872.00,17579.00,1.00
-15872.00,-19397.00,1.00
-15872.00,11468.00,1.00
As can be seen from the above, only the Y (middle column) values change when I move the sensor around. If I plot these values in Excel, I get a plot that looks like this:
I have looked through the code, and the HMC5883L library code (below) and nothing seems amiss. I tried a different HMC5883L module and got the same (bad) result. I know I must be doing something wrong, but I can't for the life of me figure it out. Any hints would be appreciated! ;-)
HMC5883L.cpp:
/*
HMC5883L.cpp - Class file for the HMC5883L Triple Axis Magnetometer Arduino Library.
Copyright (C) 2011 Love Electronics (loveelectronics.co.uk)/ 2012 bildr.org (Arduino 1.0 compatible)
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/>.
WARNING: THE HMC5883L IS NOT IDENTICAL TO THE HMC5883!
Datasheet for HMC5883L:
http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf
*/
#include <Arduino.h>
#include "HMC5883L.h"
HMC5883L::HMC5883L()
{
m_Scale = 1;
}
MagnetometerRaw HMC5883L::ReadRawAxis()
{
uint8_t* buffer = Read(DataRegisterBegin, 6);
MagnetometerRaw raw = MagnetometerRaw();
raw.XAxis = (buffer[0] << 8) | buffer[1];
raw.ZAxis = (buffer[2] << 8) | buffer[3];
raw.YAxis = (buffer[4] << 8) | buffer[5];
return raw;
}
MagnetometerScaled HMC5883L::ReadScaledAxis()
{
MagnetometerRaw raw = ReadRawAxis();
MagnetometerScaled scaled = MagnetometerScaled();
scaled.XAxis = raw.XAxis * m_Scale;
scaled.ZAxis = raw.ZAxis * m_Scale;
scaled.YAxis = raw.YAxis * m_Scale;
return scaled;
}
int HMC5883L::SetScale(float gauss)
{
uint8_t regValue = 0x00;
if(gauss == 0.88)
{
regValue = 0x00;
m_Scale = 0.73;
}
else if(gauss == 1.3)
{
regValue = 0x01;
m_Scale = 0.92;
}
else if(gauss == 1.9)
{
regValue = 0x02;
m_Scale = 1.22;
}
else if(gauss == 2.5)
{
regValue = 0x03;
m_Scale = 1.52;
}
else if(gauss == 4.0)
{
regValue = 0x04;
m_Scale = 2.27;
}
else if(gauss == 4.7)
{
regValue = 0x05;
m_Scale = 2.56;
}
else if(gauss == 5.6)
{
regValue = 0x06;
m_Scale = 3.03;
}
else if(gauss == 8.1)
{
regValue = 0x07;
m_Scale = 4.35;
}
else
return ErrorCode_1_Num;
// Setting is in the top 3 bits of the register.
regValue = regValue << 5;
Write(ConfigurationRegisterB, regValue);
}
int HMC5883L::SetMeasurementMode(uint8_t mode)
{
Write(ModeRegister, mode);
}
void HMC5883L::Write(int address, int data)
{
Wire.beginTransmission(HMC5883L_Address);
Wire.write(address);
Wire.write(data);
Wire.endTransmission();
}
uint8_t* HMC5883L::Read(int address, int length)
{
Wire.beginTransmission(HMC5883L_Address);
Wire.write(address);
Wire.endTransmission();
Wire.beginTransmission(HMC5883L_Address);
Wire.requestFrom(HMC5883L_Address, length);
uint8_t buffer[length];
if(Wire.available() == length)
{
for(uint8_t i = 0; i < length; i++)
{
buffer[i] = Wire.read();
}
}
Wire.endTransmission();
return buffer;
}
char* HMC5883L::GetErrorText(int errorCode)
{
if(ErrorCode_1_Num == 1)
return ErrorCode_1;
return "Error not defined.";
}
HMC5883L.h:
/*
HMC5883L.h - Header file for the HMC5883L Triple Axis Magnetometer Arduino Library.
Copyright (C) 2011 Love Electronics (loveelectronics.co.uk) / 2012 bildr.org (Arduino 1.0 compatible)
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/>.
WARNING: THE HMC5883L IS NOT IDENTICAL TO THE HMC5883!
Datasheet for HMC5883L:
http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf
*/
#ifndef HMC5883L_h
#define HMC5883L_h
#include <Arduino.h>
#include <Wire.h>
#define HMC5883L_Address 0x1E
#define ConfigurationRegisterA 0x00
#define ConfigurationRegisterB 0x01
#define ModeRegister 0x02
#define DataRegisterBegin 0x03
#define Measurement_Continuous 0x00
#define Measurement_SingleShot 0x01
#define Measurement_Idle 0x03
#define ErrorCode_1 "Entered scale was not valid, valid gauss values are: 0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6, 8.1"
#define ErrorCode_1_Num 1
struct MagnetometerScaled
{
float XAxis;
float YAxis;
float ZAxis;
};
struct MagnetometerRaw
{
int XAxis;
int YAxis;
int ZAxis;
};
class HMC5883L
{
public:
HMC5883L();
MagnetometerRaw ReadRawAxis();
MagnetometerScaled ReadScaledAxis();
int SetMeasurementMode(uint8_t mode);
int SetScale(float gauss);
char* GetErrorText(int errorCode);
protected:
void Write(int address, int byte);
uint8_t* Read(int address, int length);
private:
float m_Scale;
};
#endif
