hmc5883l wrong results

Hello, I'm using the HMC5883l magnetometer.
I've been trying to measure a rotation angle and it always have given me tremendously wrong results, for example: if I turned the compass about 90 degrees, it showed 40 degrees turn, I've tried to change the gain, but it didn't affect the results and I noticed when I took measurements from different places on my desk, the results were different.

Can someone advise me how to get accurate measurements?

Here's the code I'm using:

#include <Wire.h> 

#define address 0x1E //0011110b

int x, y, z;
float alpha = 0, beta = 0, prevbeta = -1, angle_1 = 0;

void setup() {

  Serial.begin(9600);
  Wire.begin();

  Wire.beginTransmission(address); 
  Wire.write(0x02); //mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();

delay(6);
}


void loop() {


  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();


  //Read data from each axis, 2 registers per axis
  Wire.requestFrom(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 ls
  }


  beta = atan2(y,x) * (180 / 3.14) + 180;

if(prevbeta != -1)
{
    if (prevbeta >= 270 && prevbeta <= 360 && beta >= 0 && beta <= 90) {
    angle_1 -= (beta + (360 - prevbeta));

    }

    else if (prevbeta >= 0 && prevbeta <= 90 && beta >= 270 && beta <= 360) {
      angle_1 += (prevbeta + (360 - beta));

    }
    else
    angle_1 += (prevbeta - beta);

}

 
  Serial.println(angle_1);
  prevbeta = beta;
  delay(67);
}

Thank you, Dan.

Can you look at the raw x,y,z values only ? Print the x,y,z values.
Did you use the right axis for the calculation ? In Europe, the vector is pointing downwards into the earth.
Do you have a real compass ? to check if that location is good enough. A computer, or wires, or speakers, they all can disturb the earth magnetic field. Can you move it away from the computer ?

Dear Keopel, I'm glad you answered me, I modified the code to this:

beta = atan2(y,z) * (180 / 3.14) + 180;

now I get much closer results, thank you.

But it brought one another issue - how do I attach the compass to my breadboard?

A few percent wrong is normal. I think there are sketches to calibrate the seperate x,y,z-axis.

Which Arduino board do you have and which HMC5883L module ? Can you give links to them, or make a photo ?

I have a regular Arduino Uno and this compass module:

Thank you, Dan.

For best results all magnetometers need to be properly calibrated, and kept away from local magnetic fields or magnetic materials. Here is the best of many approaches.

DanAro, that is the same module as I have on my table at the moment :wink:
Solder the pins, and attach it in a breadboard.

GND to GND
sensor VCC to Arduino 5V
SDA to SDA (or A4 for an Arduino Uno)
SCL to SCL (or A5 for an Arduino Uno)

Thank you all for answering,

Keopel - I've actually run the module on 3.3v untill now, after supplying 5v, the results changed by approximately 20 degrees towards the real heading, but it's still not precise.

The voltage should not have to do anything with the values.
Print an error message if not all of the 6 bytes are received, and show the sketch.

Could you let this sketch run for a while to test if your I2C communication with the HMC5883L is stable.

#include <Wire.h>

const int HMC5883L_address = 0x1E;

void setup() 
{
  Serial.begin(9600); 
  Serial.println("HMC5883L test.");

  Wire.begin();
  Wire.setClock( 100000L);   // set to 50000L for lower speed

  // Write zero to register 2 of the HMC5883L for continuous mode.
  Wire.beginTransmission( HMC5883L_address);
  Wire.write( 2);
  Wire.write( 0x00);
  int error = Wire.endTransmission();
  if( error != 0)
    Serial.println( "Error 1");

  Serial.println( "The ID of the HMC5883L is H43");
}

void loop() 
{
  int error, n;
  
  // Read the ID registers (ASCII value: 'H', '4', '3')
  Wire.beginTransmission( HMC5883L_address);
  Wire.write( 10);        // set register to 10 for the start of the ID registers.
  error = Wire.endTransmission( false);    // parameter "false" to test with repeated start
  if( error != 0)
    Serial.println( "Error 2");

  n = Wire.requestFrom( HMC5883L_address, 3);
  if( n != 3)
    Serial.println( "Error 3");

  Serial.print( "ID = ");
  Serial.write( Wire.read());  // write the ASCII value.
  Serial.write( Wire.read());  // write the ASCII value.
  Serial.write( Wire.read());  // write the ASCII value.
  
  
  Wire.beginTransmission( HMC5883L_address);
  Wire.write( 3);        // set register to 3 for the start of the x,z,y values.
  error = Wire.endTransmission( false);     // parameter "false" to test with repeated start
  if( error != 0)
    Serial.println( "Error 4");

  byte buf[6];
  n = Wire.requestFrom( HMC5883L_address, 6);
  if( n != 6)
    Serial.println( "Error 5");
  Wire.readBytes( buf, 6);

  // The order of the registers is x-z-y
  int x = word( buf[0], buf[1]);  // highbyte first
  int z = word( buf[2], buf[3]);
  int y = word( buf[4], buf[5]);

  Serial.print( "   x,y,z = ");
  Serial.print( x);
  Serial.print( ", ");
  Serial.print( y);
  Serial.print( ", ");
  Serial.println( z);

  delay(700);
}

The output should be:

HMC5883L test.
The ID of the HMC5883L is H43
ID = H43   x,y,z = 84, -300, -600
ID = H43   x,y,z = 84, -302, -602
ID = H43   x,y,z = 82, -302, -600
ID = H43   x,y,z = 86, -301, -598
ID = H43   x,y,z = 86, -301, -600
ID = H43   x,y,z = 86, -301, -600
ID = H43   x,y,z = 88, -298, -598
ID = H43   x,y,z = 87, -302, -598
ID = H43   x,y,z = 87, -302, -599
ID = H43   x,y,z = 86, -301, -603
ID = H43   x,y,z = 86, -302, -600
ID = H43   x,y,z = 85, -302, -601
ID = H43   x,y,z = 86, -301, -602
ID = H43   x,y,z = 84, -302, -601

Can you copy the output and show it ?

Hello Koepel my output is:

HMC5883L test.
The ID of the HMC5883L is H43
ID = H43   x,y,z = 311, -434, -457
ID = H43   x,y,z = 310, -435, -454
ID = H43   x,y,z = 313, -435, -457
ID = H43   x,y,z = 310, -435, -455
ID = H43   x,y,z = 312, -434, -459
ID = H43   x,y,z = 311, -431, -456
ID = H43   x,y,z = 311, -434, -454
ID = H43   x,y,z = 311, -435, -456
ID = H43   x,y,z = 311, -434, -457
ID = H43   x,y,z = 312, -434, -456
ID = H43   x,y,z = 309, -432, -452
ID = H43   x,y,z = 309, -433, -455

That is good, it means you are communicating with the sensor without errors.
Are there no problems if you let it run for a while ?

The strange results might be magnetic interference, or perhaps you are in a building with a lot iron (reinforced concrete).
Could you try with a longer usb cable and walk around the room to see what happens with the values.
Keep it near a mains wire, and the values could dramatically change.
For the best results, take a laptop and go to an open field and use a 5 meter long usb cable to the Arduino and magnetometer to keep the magnetometer away from the laptop :wink:
I have strange results when the magnetometer is near my computer.

The HMC5883L needs a capacitor to work. Perhaps your module has the wrong capacitor. I think it is very unlikely, but you could buy a different module with the HMC5883L from a different seller, to compare them. Perhaps your HMC5883L is damaged inside, or it was a wrong batch from the factory and should have been destroyed, or it is a counterfeit one. All these things have happened with other chips, so it could happen.

Hello, thank you for helping me, I tested both of my hmc5883l modules, running the same sketch (heading calculation by y and x axis), both took measurements from the same point on my desk.
One showed the result of 103 degrees, the second showed 141 degrees and my phone showed 129 degrees.
I put them away from my computer while testing.
How is that possible?

I mention that I only want it to calculate the rotation angle as in the first code I posted, so the basic heading can be not accurate but, it also doesn't calculate the rotation (difference) of angles properly - I think it has to do with the basic heading results.

the basic heading can be not accurate

That happens when you have not calibrated the device. See reply #5.

jremington, thank you for answering.

I noticed that most of the results I'm getting can be fixed to the real rotation angle by proportion, if the rotation angle returned by the module is 45, and I actually turned it about 90 degrees, then I add 44 degrees, by the next equation:

angle1 = abs(angle_1) + 0.9565*abs(angle_1);

after a few measurements from different places, the result were very close to reality.
Do you think that a gyroscope can do the same job (but more accurately)?

You must really, really not want to calibrate that device!

Hello jremington, thank you for helping, I followed all of your instructions.
When I open a txt file in the calibrator I get the message "please check the raw file data", I put to a txt file the next module output:

325    -415    -519
325    -417    -515
326    -417    -518
327    -416    -516
332    -418    -513
328    -416    -516
328    -415    -516
327    -416    -518
327    -414    -513
327    -413    -514
326    -416    -519
327    -416    -516
326    -416    -516
327    -417    -513
327    -417    -517
325    -419    -515
328    -416    -515
328    -416    -516
327    -415    -515
328    -417    -515
329    -417    -514
328    -415    -515
327    -418    -513
328    -416    -515
327    -416    -518
328    -415    -514
327    -414    -515
326    -414    -515
326    -416    -514
329    -416    -515
327    -418    -514
328    -416    -515
326    -417    -516
328    -418    -517
326    -416    -516
328    -415    -514
328    -417    -516
329    -415    -515
326    -417    -512
328    -416    -515
326    -416    -518
328    -418    -518
327    -416    -514
327    -417    -516
326    -419    -516
326    -418    -516
327    -415    -516
327    -415    -516
329    -418    -515
327    -418    -514
329    -417    -517
326    -415    -518
327    -414    -515
327    -415    -516
329    -416    -516
326    -416    -514
327    -416    -517
329    -417    -518
327    -415    -514
325    -416    -516
326    -418    -515
326    -414    -516
328    -417    -515
329    -417    -516
325    -416    -515
327    -416    -516
327    -417    -515
328    -417    -515
327    -414    -516
325    -416    -517
327    -417    -518
325    -416    -514
326    -419    -512
327    -414    -515
326    -417    -514
327    -413    -517
328    -417    -518
327    -414    -518
327    -416    -516
327    -418    -516
326    -418    -516
325    -415    -516
327    -417    -514
327    -416    -514
327    -414    -517
327    -414    -514
328    -415    -514
327    -414    -515
325    -418    -514
327    -416    -513
326    -413    -514
326    -416    -517
326    -414    -516
327    -418    -517
325    -418    -514
328    -419    -516
327    -419    -513
325    -415    -515
328    -417    -515
326    -417    -516
329    -416    -513
326    -419    -516
325    -416    -515
327    -416    -514
326    -418    -514
327    -416    -516
328    -416    -516
328    -415    -516
326    -414    -517
325    -417    -516
330    -417    -517
328    -417    -516
326    -417    -514
325    -416    -516
327    -416    -519
326    -415    -516
328    -416    -515
325    -416    -515
327    -414    -514
328    -417    -513
326    -419    -513
327    -416    -514
327    -417    -513
326    -414    -515
325    -417    -516
328    -417    -515
327    -417    -516
329    -415    -514
328    -417    -514
325    -415    -516
327    -413    -515
330    -413    -515
327    -414    -514
329    -419    -517
328    -414    -512
326    -415    -517
327    -417    -513
325    -418    -517
327    -415    -516
328    -415    -516
326    -416    -515
327    -413    -514
326    -414    -516
330    -417    -515
328    -417    -518
326    -417    -515
330    -413    -515
325    -416    -513
327    -416    -515
324    -414    -516
330    -418    -515
326    -417    -516
326    -416    -514
329    -415    -512
328    -417    -513
327    -416    -515
326    -416    -515
326    -412    -514
328    -414    -513
327    -417    -513
325    -416    -515
327    -417    -513
326    -414    -513
323    -416    -515
327    -415    -514
324    -415    -514
329    -413    -515
327    -417    -515
327    -417    -514
326    -415    -512
332    -414    -516
326    -414    -516
328    -418    -516
328    -416    -516
328    -412    -515
327    -416    -512
327    -417    -514
322    -417    -514
328    -417    -514
327    -415    -515
327    -415    -518
326    -418    -516
326    -416    -517
325    -419    -515
326    -413    -514
329    -415    -513
330    -415    -516
326    -416    -515
325    -418    -515
325    -412    -516
326    -415    -516
328    -418    -516
323    -417    -513
329    -416    -515
326    -416    -517
328    -416    -515
328    -414    -514
328    -416    -513
325    -413    -513
325    -416    -516
325    -419    -515
326    -415    -516
325    -416    -515
330    -417    -513
329    -413    -514
326    -416    -516
328    -417    -515
327    -415    -514
325    -418    -515
328    -418    -513
329    -415    -512
325    -416    -515
328    -417    -515
325    -417    -513
329    -416    -516
327    -416    -517
327    -414    -515
328    -415    -514
326    -414    -514
327    -415    -515
328    -417    -516
326    -414    -514
327    -415    -516
327    -415    -515
324    -417    -515
326    -417    -517
326    -414    -514
324    -415    -514
327    -419    -515
328    -415    -513
326    -414    -513
324    -417    -517
326    -417    -516
325    -413    -514
329    -415    -515
328    -414    -514
325    -413    -513
327    -419    -516
327    -418    -514
327    -414    -515
328    -415    -514
326    -415    -515
327    -415    -516
325    -415    -516
329    -417    -514
327    -416    -514
328    -414    -515
325    -416    -516
328    -416    -513
327    -414    -516
326    -417    -514
327    -414    -513
325    -416    -514
325    -415    -514
325    -414    -514
329    -416    -515
327    -416    -515
327    -415    -514
329    -418    -516
327    -412    -515
328    -417    -516
325    -416    -515
328    -414    -512
325    -417    -515
327    -416    -515
328    -415    -514
326    -414    -516
325    -414    -514
328    -414    -515
328    -415    -515
326    -416    -516
328    -416    -511
326    -415    -514
327    -415    -514
325    -412    -516
326    -413    -513
326    -416    -514
325    -415    -513
327    -415    -514
326    -416    -514
325    -416    -513
326    -413    -514
327    -416    -514
329    -417    -512
328    -414    -512
326    -418    -514
329    -416    -515
326    -416    -513
328    -416    -511
326    -414    -513
325    -413    -517
327    -413    -515
325    -414    -512
326    -415    -514
329    -414    -513
325    -414    -514
328    -413    -513
327    -415    -518
326    -416    -515
328    -416    -514
329    -417    -511
329    -415    -515
327    -412    -515
328    -414    -513
328    -415    -513
327    -415    -513
324    -414    -512
323    -416    -514
324    -417    -514
325    -416    -513
326    -416    -513
328    -416    -516
328    -415    -514
328    -416    -513
327    -418    -513
328    -414    -515
325    -412    -515
326    -416    -514
327    -413    -514
328    -414    -511
324    -414    -515
324    -416    -513
329    -413    -513
325    -415    -516
327    -414    -512
325    -414    -515
330    -416    -512
327    -416    -515
327    -415    -511
327    -414    -514
329    -415    -515
325    -416    -513
327    -413    -515
328    -415    -514
324    -415    -513
328    -417    -512
325    -413    -515
327    -414    -513
329    -411    -513
327    -415    -516
327    -417    -512
326    -416    -514
326    -413    -514
326    -417    -512
326    -412    -513
325    -413    -516
322    -413    -513
324    -412    -515
324    -412    -513
323    -413    -514
325    -413    -513
323    -413    -514
324    -412    -512
323    -416    -515
323    -414    -514
325    -415    -514
324    -415    -512
326    -415    -516
328    -415    -511
331    -417    -513
328    -414    -514
330    -414    -514
329    -415    -515
328    -412    -513
329    -412    -515
330    -413    -512
332    -411    -513
326    -416    -513
329    -415    -514
330    -413    -511
331    -416    -516
330    -414    -515
330    -417    -514
333    -413    -514
331    -417    -512
330    -415    -513
333    -415    -512
329    -414    -515
330    -414    -512
329    -415    -513
329    -416    -515
330    -414    -513
327    -415    -511
331    -417    -512
330    -415    -512
330    -417    -515

What should I do in order to fix that problem?
In my area the magnetic field strength is 45089.5 nT, how should I put that info in the calibrator?
What do the results of the calculation mean?

Which calibration program did you use? There are two on the sailboatinstruments site.

However, that text file won't work no matter what you do, because it is clear that you did not put the accelerometer in various orientations, as required. You do need to understand the material and follow instructions.

The sailboatinstruments site describes the best approach, which produces a matrix and offset vector that corrects the raw readings. If you are not familiar with matrix operations, there are other, simpler approaches. A good overview is here, or try this one specific to your sensor.

After calibration, compass orientation readings should be correct to within 1-2 degrees around a full circle.

jremington, thank you for replying, I used a different calibrator and now it works fine.

hello koepal,

my output from the HMC5883 is varying a lot even when kept at a stable place. I have checked it with the code you provided. What shall I do ?