HMC5883L magnetometer problem

Hey I'm having a problem with my HMC5883L sainsmart breakout board where I only get degree values between 139 and 155. I have it mounted vertically and thus I changed this: float heading = atan2(scaled.YAxis, scaled.XAxis); to this: float heading = atan2(scaled.ZAxis, scaled.XAxis);

I ordered another one thinking that I had damaged the module but I am having the same problem. I had it working before and I cant seem to figure out what is different. The example code is below. I also 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" even though it is set to 1.3.

/*
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.ZAxis, 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");
}

Hi!

Here

HMC5883L compass;

u get a fresh instance of HMC5883L.

And here in setup()

  Serial.println("Constructing new HMC5883L");
 compass = HMC5883L(); // Construct a new HMC5883 compass.

u overwrite it with a second instance.

I think now u have 2 instances that deal with the same chip...

Did u try to test ur chip again without ur software changes?

Bye

That is the example that comes with the hmc5883l library. The first instance is a declaration that is needed. The only change I made was from y,x axis to z, x axis but I have tried every other combination.

I also 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" even though it is set to 1.3.

That is a bug in the library.

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

Have you experienced the same issue where the bearing only changes minimally when rotating 360 degrees?

Asking me? The only arduino lib which works somehow imho is the HMC58X3v04 (Varesano.net). You have to calibrate the sensor before using it as there could be a significant offset. Also you need a proper math there to compensate tilt (not easy, btw). The sensor is extremely sensitive so it depends on its environment where it points :slight_smile:

PS: varesano.net -

Ok tried that library instead. Same problem.

that error message is probably not important.

Are you getting any usable response from the device at all. Suggest you print the actual x,y,z values
of the magnetic field vector. You can then see if it is working. This vector should point along the
direction of the earths magnetic field at your location, which will be inclined to the earth's surface, there
is an adequate explanation at wikipedia.

Once you get the device working, then you can worry about getting a value corresponding to the
horizontal plane direction.

The you can calibrate the device properly with the offset and scale differences in each sensor direction.

It seems that I have created an electromagnet with all the wires I have connected to the arduino and a breadboard. I moved the magnetometer farther away and the problem isnt as bad but It still makes the device fairly unusable. Can anyone explain to me how I can (easily) calibrate the mag so as to compensate for the electromagnetic field?

I have not had this problem with the Arduino and a breadboard. What else do you have there
which could be creating a magnetic field? motors or servos or solenoids might.

There are several approaches to calibration. It depends partly on what you want to do.

You want to have an offset value so that the field has the same value when you point the
positive end of the device or the negative end of the device at it.

You want to have a scaling value so that the field has the same magnitude when you point
the x,y or z axis at it.