Magnetometer incorrect measurement

Hello,

So earlier I had a problem reading form the HMC5883L 3-axis magnetometer and it solved when I changed the board.

Now I'm facing another problem and its that the readings seem consistent but incorrect, and I want to know how I can correct them.

Here is the code Im using:

/***************************************************************************
  This is a library example for the HMC5883 magnentometer/compass

  Designed specifically to work with the Adafruit HMC5883 Breakout
  http://www.adafruit.com/products/1746
 
  *** You will also need to install the Adafruit_Sensor library! ***

  These displays use I2C to communicate, 2 pins are required to interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Kevin Townsend for Adafruit Industries with some heading example from
  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/>.

 ***************************************************************************/

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>


/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

void displaySensorDetails(void)
{
  sensor_t sensor;
  mag.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" uT");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" uT");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" uT");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void setup(void) 
{
  Serial.begin(9600);
  Serial.println("HMC5883 Magnetometer Test"); Serial.println("");
  
  /* Initialise the sensor */
  if(!mag.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
  
  /* Display some basic information on this sensor */
  displaySensorDetails();
}

void loop(void) 
{
  /* Get a new sensor event */ 
  sensors_event_t event; 
  mag.getEvent(&event);


  
  /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
  Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print("  ");
  Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print("  ");
  Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print("  ");Serial.println("uT");
  
  delay(500);
}

I keep it with default gain configuration.

This is the output that I get when I rotate the sensor around the Z axis:
rotation z.JPG

Around the Y axis:


Around the X axis:
rotation x.JPG
scatter y z.JPG

It seems that Y value is shifting by -30~-40, would adding this amount to the Y reading fixes the issue? And I don't know where exactly is the problem and what is the exact correction value.

Those reading looks good to me.
Find how earths mag. field is directed at your location. add calibrating numbers for each axis.

The most important parameter is headingDegrees, computed inside of the acquisition routine:

    CompassX=event.magnetic.x;
    CompassY=event.magnetic.y;
    CompassZ=event.magnetic.z;
  
    heading = atan2(event.magnetic.y, event.magnetic.x);
  
    float declinationAngle = 0.22;
    heading += declinationAngle;
  
    if(heading < 0)
    heading += 2*PI;
    
    if(heading > 2*PI)
    heading -= 2*PI;
   
    float headingDegrees = heading * 180/M_PI;

The triplet depends on your latitude/longitude datas

With my setup:

-30 < event.magnetic.x <30
-49 < event.magnetic.y <22
  6 < event.magnetic.z <28

MCU: STM32F429I-DISCO
Screen: Riverdi FT813, 5"
Sensor: HMC5883L

Video: F429ZI-DISCO + FT813 + HMC5883L

FT81Xmania team

How to calibrate magnetometers and accelerometers.

No MEMS magnetometer will work out of the box, they must have hard/soft iron correction applied. This
is especially true if on a circuit board, as all sorts of components have steel as part of their construction.