Problem with HMC5883L

hi, last week i received my new HCM5883L magnetometer breakout board , i connected it to arduino according to pin configuration that is SCL to pin 5, SDA to pin 4 with 5.6 k pullup resistor but i received just a raw data between 0 and 5 of x and y and the value of z is constant i-e -4096 ,and when i brought a magnet near to the sensor and move around, the value get high and then start fluctuate btw 0 and 5 . i m not getting what happened to this , whether the board is faulty or there is some other reason.i attached the screen shot of the serial monitor with code. plz if some one knows then help me .thanks in advance

/*
HMC5883L_Example.pde - Example sketch for integration with an HMC5883L triple axis magnetomerwe.
Copyright (C) 2011 Love Electronics (loveelectronics.co.uk)

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/>.

*/

// Reference the I2C Library
#include <Wire.h>
// Reference the HMC5883L Compass Library
#include <HMC5883L.h>

// Store our compass as a variable.
HMC5883L compass;
// Record any errors that may occur in the compass.
int error = 0;

// Out setup routine, here we will configure the microcontroller and compass.
void setup()
{
  // Initialize the serial port.
  Serial.begin(9600);

  Serial.println("Starting the I2C interface.");
  Wire.begin(); // Start the I2C interface.

  Serial.println("Constructing new HMC5883L");
  compass = HMC5883L(); // Construct a new HMC5883 compass.
    
  Serial.println("Setting scale to +/- 1.3 Ga");
  error = compass.SetScale(1.3); // Set the scale of the compass.
  if(error != 0) // If there is an error, print it out.
    Serial.println(compass.GetErrorText(error));
  
  Serial.println("Setting measurement mode to continous.");
  error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
  if(error != 0) // If there is an error, print it out.
    Serial.println(compass.GetErrorText(error));
}

// Our main program loop.
void loop()
{
  // Retrive the raw values from the compass (not scaled).
  MagnetometerRaw raw = compass.ReadRawAxis();
  // Retrived the scaled values from the compass (scaled to the configured scale).
  MagnetometerScaled scaled = compass.ReadScaledAxis();
  
  // Values are accessed like so:
  int MilliGauss_OnThe_XAxis = scaled.XAxis;// (or YAxis, or ZAxis)

  // Calculate heading when the magnetometer is level, then correct for signs of axis.
  float heading = atan2(scaled.YAxis, scaled.XAxis);
  
  // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
  // Find yours here: http://www.magnetic-declination.com/
  // Mine is: 2? 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
  // If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
  float declinationAngle = 0.0457;
  heading += declinationAngle;
  
  // Correct for when signs are reversed.
  if(heading < 0)
    heading += 2*PI;
    
  // Check for wrap due to addition of declination.
  if(heading > 2*PI)
    heading -= 2*PI;
   
  // Convert radians to degrees for readability.
  float headingDegrees = heading * 180/M_PI; 

  // Output the data via the serial port.
  Output(raw, scaled, heading, headingDegrees);

  // Normally we would delay the application by 66ms to allow the loop
  // to run at 15Hz (default bandwidth for the HMC5883L).
  // However since we have a long serial out (104ms at 9600) we will let
  // it run at its natural speed.
  // delay(66);
}

// Output the data down the serial port.
void Output(MagnetometerRaw raw, MagnetometerScaled scaled, float heading, float headingDegrees)
{
   Serial.print("Raw:\t");
   Serial.print(raw.XAxis);
   Serial.print("   ");   
   Serial.print(raw.YAxis);
   Serial.print("   ");   
   Serial.print(raw.ZAxis);
   Serial.print("   \tScaled:\t");
   
   Serial.print(scaled.XAxis);
   Serial.print("   ");   
   Serial.print(scaled.YAxis);
   Serial.print("   ");   
   Serial.print(scaled.ZAxis);

   Serial.print("   \tHeading:\t");
   Serial.print(heading);
   Serial.print(" Radians   \t");
   Serial.print(headingDegrees);
   Serial.println(" Degrees   \t");
}

I have also problems with the returned raw data. But all raw x,y,z values change with a magnet, or with the earth magnetic file (if I rotate the breakout board).

Is only your raw z-axis changing with a magnet ?
Can you add a link to the library and the breakout board ?
Can you paste the output of the serial monitor in your message ?

Those pullups are going to +3.3V I hope....

Did you solve this problem ?

I have ordered one of these gadgets and I am worried about ruining it.

Do you need to have a resistor pair as a "voltage divider" when connecting a 3.3V I2C device to a 5V Arduino, or do you just use one pullup resistor connected to 3.3V, which would make it a pulldown resistor, I guess...

Mine was difficult to calibrate. I couldn't figure it out, so I just used X,Z instead of X,Y for 2D. Seems Y was bad somehow, off by 50-100 degrees at times, combining X,Y. Rotate the unit 90 degrees to use X,Z.

Hello,
I have a problem with HMC5883L magnetometer:
card: Arduino 2009
Soft: HMC5883L_Example.pde

The sketch is loaded into the card (arduino) but in the serial monitor I have this:

Constructing new HMC5883L
Setting scale to +/- 1.3 Ga
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
Setting measurement mode to continous.
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
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: -18176 -15872 322 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees

and so on.

What's happened ?

Thanx

1 Like

I use the standard "HMC5883L_Example.INO" and it seems to work but I still get the error:

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

I have tried all those values but I always get this error and changing these numbers doesn't seem to make any difference to the readings.
Why do I get this error?

ciucianebbia:
Hello,
I have a problem with HMC5883L magnetometer:
card: Arduino 2009
Soft: HMC5883L_Example.pde

The sketch is loaded into the card (arduino) but in the serial monitor I have this:

Constructing new HMC5883L
Setting scale to +/- 1.3 Ga
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
Setting measurement mode to continous.
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
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: -18176 -15872 322 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees
Raw: 875 1795 883 Scaled: 805.00 1651.40 812.36 Heading: 1.16 Radians 66.63 Degrees

and so on.

What's happened ?

Thanx

I get the same errors. Any ideas to get this fixed?

..in HMC5883L.cpp change to:

char* HMC5883L::GetErrorText(int errorCode)
{
	if(errorCode == ErrorCode_1_Num)
		return ErrorCode_1;
	
	return "Error not defined."; //or "No error" ??
}

Also such stuff like:

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;
..

is of course not to recommend, I would rather use int "gauss" values instead of floats there..

This library does not calibrate the sensor, so when you move a magnet around the values changes and stay off (and you may get wrong heading). Google for HMC58X3 v04 - that driver includes calibration..
https://launchpad.net/hmc58x3

I found three lots of code on the net for that device, and they all had obvious mistakes.

One was so bad, it had obviously never been attempted to actually use.

In the end, I wrote my own.

As for the magnet-waving around, these devices are intended to detect the very weak magnetic
field of the earth. Waving a magnet around near them is going to impose a much larger magnetic field,
possibly overload them, and cause problems with overflows in the readings. If you want to detect magnets,
you need to turn the sensitivity of the device down.

You need to calibrate the device by setting the offset and scaling factor for each axial direction, so that
the magnitude of the apparent field vector remains approximately constant no matter which way you
orient the device.

I've got the sensor today :slight_smile: and I am quite surprised that moving a magnet (ie in 3-5cm distance) around does change the values PERMANENTLY :~ (when the sensor stays in a fixed position). Currently looking how to degauss the sensors (it shall include "automatic degaussing")..

If you want to detect a magnet, you are probably better off using a "hall effect" sensor.

2017 Update

I have been battling with this GY-271 problem for many hours. I know this thread is very old, but it's prominent in the search results. Maybe my addendum can save other people hours of searching and frustration. I too were getting a constant, occasionally glitchy, unresponsive output and thought I'd bricked the board even though the I2C scanner "saw" it.

The GY-271 should have the HMC5883L chip, which nearly all of the libraries and example code you're likely to find on google/arduino rely on. Some, presumably "fake," boards don't, they have the QMC5883L. Note Q, not H. The I2C register addresses are not the same.

The HMC is made by Honeywell, and the QMC is a Chinese version. (source: http://wiki.epalsite.com/index.php?title=HMC5883L(Or_QMC5883L)_Electronic_Compass )

If you run the I2C scanner -> Arduino Playground - I2cScanner

and it finds the address 0x0D then you have one of these QMC chips.

More info on the register addresses is here in the datasheet -> https://github.com/luckypm/commn-informations/blob/master/地磁文档/航纬5983替代料资料/QMC5883L%20Datasheet%201.0%20.pdf

You could use the register info in that datasheet to update one of the preexisting libraries from adafruit, or the vanilla HMC5883L library, or you could do what I did, and find...

...DFrobot. My unending gratitude goes to dfrobot.com for creating a library that works with the QMC5883L. It took me far too long to find it, hence this post, but it has saved me from a very unhappy & vexing evening :slight_smile:
GitHub - DFRobot/DFRobot_QMC5883

There is also alternative library for QMC5883 at GitHub - keepworking/Mecha_QMC5883L: Arduino lib for QMC5883
its a bit easier to understand as it doesn't attempt to do both chipsets like the DFRobot one does.

Hi @nanopilot , have you successfully make QMC5883 work with dfrobot library? As I found some obvious overflow (divided by 0 when calculating the average value of XAxis ... in readRaw and readNormalize). Fortunately someone already fixed it. But when I use this library, it often enter endless loop while won't enter endless loop if I use some other similar library.

nanopilot:
2017 Update

I have been battling with this GY-271 problem for many hours. I know this thread is very old, but it's prominent in the search results. Maybe my addendum can save other people hours of searching and frustration. I too were getting a constant, occasionally glitchy, unresponsive output and thought I'd bricked the board even though the I2C scanner "saw" it.

The GY-271 should have the HMC5883L chip, which nearly all of the libraries and example code you're likely to find on google/arduino rely on. Some, presumably "fake," boards don't, they have the QMC5883L. Note Q, not H. The I2C register addresses are not the same.

The HMC is made by Honeywell, and the QMC is a Chinese version. (source: http://wiki.epalsite.com/index.php?title=HMC5883L(Or_QMC5883L)_Electronic_Compass )

If you run the I2C scanner -> Arduino Playground - HomePage

and it finds the address 0x0D then you have one of these QMC chips.

More info on the register addresses is here in the datasheet -> https://github.com/luckypm/commn-informations/blob/master/地磁文档/航纬5983替代料资料/QMC5883L%20Datasheet%201.0%20.pdf

You could use the register info in that datasheet to update one of the preexisting libraries from adafruit, or the vanilla HMC5883L library, or you could do what I did, and find...

...DFrobot. My unending gratitude goes to dfrobot.com for creating a library that works with the QMC5883L. It took me far too long to find it, hence this post, but it has saved me from a very unhappy & vexing evening :slight_smile:
GitHub - DFRobot/DFRobot_QMC5883

hey , i will be so happy if you answer my question about M_PI & PI in HMC5883l library .what are they exactly defined for?

Hello,

I had the same problem with a cheap HMC5883L.
The x-values were ok but the y-values were always negativ between -300 and -900.

With the serial-plotter I found out, that the y-values were nearly a sin-wave while rotating the sensor.

So I adjusted the code and added a linear offset (+600) to the y-value.
Since then the heading-value matches my old analog compass.

I dont know the reason for this measurment error, maybe a current on the pcb or something else...

Maybe you have the same problem and have searched through the web and nearly gave up... just like me

Kind regards,
David B.

Need Help !!
Its been almost 3 days am trying everything but the output is just not coming through. Not sure if the sensor is working well (I tried 3 of them)

My output remains unchanged no matter which liabrary I use or which code I use on my UNO.

x axis: 0 y axis: 0 z axis: 0
x axis: 0 y axis: 0 z axis: 0
x axis: 0 y axis: 0 z axis: 0
x axis: 0 y axis: 0 z axis: 0
x axis: 0 y axis: 0 z axis: 0

Can someone please help me with the right code and the correct liabraries.

My Code: Copied from Sparkfun
/*
An Arduino code example for interfacing with the HMC5883

by: Jordan McConnell
SparkFun Electronics
created on: 6/30/11
license: OSHW 1.0, OSHW - Definition of Free Cultural Works

Analog input 4 I2C SDA
Analog input 5 I2C SCL
*/

#include <HMC5883L.h>
#include <Wire.h> //I2C Arduino Library

#define HMC5883L_Address 0x1E //0011110b, I2C 7bit address of HMC5883
#define X 3
#define Y 7
#define Z 5
void setup(){
//Initialize Serial and I2C communications
Serial.begin(9600);
Wire.begin();
//Init_HMC5883L();

//Put the HMC5883 IC into the correct operating mode
Wire.beginTransmission(HMC5883L_Address); //open communication with HMC5883
Wire.write(0x02); //select mode register
Wire.write(0x00); //continuous measurement mode
Wire.endTransmission();
}

void loop(){

int x,y,z; //triple axis data

//Tell the HMC5883 where to begin reading data
Wire.beginTransmission(HMC5883L_Address);
Wire.write(0x03); //select register 3, X MSB register
Wire.endTransmission();

//Read data from each axis, 2 registers per axis
Wire.requestFrom(HMC5883L_Address, 6);
if(6<=Wire.available()){
x = Wire.read()<<8; //X msb
x |= Wire.read(); //X lsb
z = Wire.read()<<8; //Z msb
z |= Wire.read(); //Z lsb
y = Wire.read()<<8; //Y msb
y |= Wire.read(); //Y lsb
}

//Print out values of each axis
Serial.print("x axis: ");
Serial.print(x);
Serial.print(" y axis: ");
Serial.print(y);
Serial.print(" z axis: ");
Serial.println(z);

delay(500);
}