Easy Hard and Soft Iron Magnetometer Calibration

20,868

132

25

Introduction: Easy Hard and Soft Iron Magnetometer Calibration

About: Electronics Engineer / Embedded Systems Programmer

If your hobby is RC, drones, robotics, electronics, augment reality or similar then sooner or later you will meet with the task of magnetometer calibration. Any magnetometer module must be calibrated, because the measurement of magnetic field subjected to some distortions. There are two kinds of these distortions: the hard iron distortions and the soft iron distortions. The theory about these distortions you can find here. To get the accurate measurements you should calibrate magnetometer for hard and soft iron distortions. This instructable describes the easy way how to do it.

Step 1: Stuff You Need

Hardware:

*But you can easily adopt this instructable for another magnetometer module or arduino board.

Software:

Firmware:

*This sketch is written for the HMC5883L module, but you can easily adopt it for your module.

Others:

Step 2: Making the Calibration Box

For the calibration process you should make the special calibration box (picture 2.1). For making this I used a paper box, but you can use a plastic one, a wooden bar or something else too. You should join the magnetometer module with the box (for example with glue) as shown in the picture 2.1. On the faces of the box you should draw the coordinate system according to the coordinate system of the magnetometer module.

Step 3: Electrical Connection

Connect the magnetometer module and arduino board as shown in the picture 3.1. Note that the supply voltage of magnetometer module can be 3,3 V (as in my case with HMC5883L GY-273 version).

Step 4: Installing the Software and Firmware

Download the software and firmware here.
This archive contains files:

  • MagMaster.exe - the magnetometer calibration program
  • MagViewer.exe - the magnetometer measurements visualisation program
  • Arduino_Code - the arduino sketch for the calibration process
  • Arduino_Test_Results - the arduino sketch for testing calibration results
  • Arduino_Radius_Stabilisation - the arduino sketch for testing calibration results with sphere radius stabilization algorithm
  • MagMaster Files and MagViewer Files - the system files for MagMaster.exe and MagViewer.exe

Copy all these files to any folder. Upload the "Arduino_Code" sketch to the arduino board. This arduino sketch requires the HMC5883L library, copy the folder "HMC5883L" (placed in "Arduino_Code" folder) to the folder "C:\Program Files\Arduino\libraries" before sketch uploading.

Step 5: Calibration

Introduction

Calibration of magnetometer is the process of getting the transformation matrix and bias.

To get the calibrated measurements of the magnetic field you should use these transformation matrix and bias in your program. In your algorithm you should apply the bias to the vector of non calibrated magnetometer data (X, Y, Z coordinates) and then multiply the transformation matrix by this resulting vector (picture 5.4). The C algorithm of these calculations you can find in "Arduino_Test_Results" and "Arduino_Radius_Stabilization" sketches.

Calibration process

Run MagMaster.exe and select the serial port of the arduino board. The green strings on the program window indicates the coordinates of magnetometer vector (picture 5.1).

Place the magnetometer module (calibration box with attached magnetometer module) as shown on the picture 5.2.1 and click "Point 0" button of the "Axis X+" groupbox. Note that the calibration box is not stationary relatively to fixed horizontal plane. Then place the magnetometer as shown on the picture 5.2.2 and click "Point 180" button of the "Axis X+" groupbox and so on. You should do in the following way (see picture 5.3 too):

  • Picture 5.2.1: "Point 0", "Axis X+"
  • Picture 5.2.2: "Point 180", "Axis X+"
  • Picture 5.2.3: "Point 0", "Axis X-"
  • Picture 5.2.4: "Point 180", "Axis X-"
  • Picture 5.2.5: "Point 0", "Axis Y+"
  • Picture 5.2.6: "Point 180", "Axis Y+"
  • Picture 5.2.7: "Point 0", "Axis Y-"
  • Picture 5.2.8: "Point 180", "Axis Y-"
  • Picture 5.2.9: "Point 0", "Axis Z+"
  • Picture 5.2.10: "Point 180", "Axis Z+"
  • Picture 5.2.11: "Point 0", "Axis Z-"
  • Picture 5.2.12: "Point 180", "Axis Z-"

You should fill the table. After that click "Calculate Transformation Matrix and Bias" and get the transformation matrix and bias (picture 5.3).

The transformation matrix and bias are got! The calibration is complete!

Step 6: Testing and Visualisation

The non calibrated measurements visualisation

Upload the "Arduino_Code" sketch to the arduino board. Run the MagViewer.exe, select the serial port of the arduino board (the boud rate of the seraial port should be 9600 bps) and click "Run MagViewer". Now you can see the coordinates of the magnetometer data vector in 3D space on a real-time (picture 6.1, video 6.1, 6.2). These measurements are non calibrated.

The calibrated measurements visualisation

Edit the "Arduino_Radius_Stabilization" sketch, replace the default transformation matrix and bias data with your obtained during calibration data (your transformation matrix and bias). Upload "Arduino_Radius_Stabilization" sketch to the arduino board. Run the MagViewer.exe, select serial port (the boud rate is 9600 bps), click "Run MagViewer". Now you can see the calibrated measurements in 3D space on a real-time (picture 6.2, video 6.3, 6.4).

By using these sketches you can easy write the algorithm for your magnetometer project with calibrated measurements!

First Time Author Contest

Participated in the
First Time Author Contest

Be the First to Share

    Recommendations

    • Microcontroller Contest

      Microcontroller Contest
    • Automation Contest

      Automation Contest
    • Make it Glow Contest

      Make it Glow Contest

    25 Comments

    0
    minhnhatledinh.vn
    minhnhatledinh.vn

    8 days ago

    Hi, thank you for your post and it is really great.
    Could you mind show me some theoritical source about how to find the Transformation matrix and Bias value?

    0
    rodgerschins
    rodgerschins

    10 months ago

    Hello Yuri.
    Thanks for your incredible work.
    I try to use it with QMC5883 but can't.. can you give me some tips ?
    Thanks

    0
    AstroHarry
    AstroHarry

    Reply 8 weeks ago

    Hello Rodger,
    perhaps it's still useful for you. This is how i did with a regular "GY-271" magnetometer and Arduino. I have used the MechaQMC5583 library. Just google for that. My complete sketch looks like below. Sure, it could be streamlined and beautified. Was just a proof of concept. Be aware, that it already includes the transformation matrix and bias values of MY GY-271 model. You need to put in your values. This is an absolute must-do. I even tried several different GY-271 modules from one supplier. But everyone behaves absolutely different. So a calibration for each module is definitely MUST.

    #include "Wire.h"
    #include <MechaQMC5883.h>

    MechaQMC5883 compass;

    float xv, yv, zv;
    float calibrated_values[3];

    void transformation(float uncalibrated_values[3])
    {
    //calibration_matrix[3][3] is the transformation matrix
    //replace M11, M12,..,M33 with your transformation matrix data
    double calibration_matrix[3][3] =
    {
    {1.242, -0.033, 0},
    {-0.073, 1.271, 0.038},
    {-0.005, -0.038, 1.339}
    };
    //bias[3] is the bias
    //replace Bx, By, Bz with your bias data
    double bias[3] =
    {
    682.001,
    4.729,
    -45.234
    };
    //calculation
    for (int i=0; i<3; ++i) uncalibrated_values[i] = uncalibrated_values[i] - bias[i];
    float result[3] = {0, 0, 0};
    for (int i=0; i<3; ++i)
    for (int j=0; j<3; ++j)
    result[i] += calibration_matrix[i][j] * uncalibrated_values[j];
    for (int i=0; i<3; ++i) calibrated_values[i] = result[i];
    }

    void setup()
    {
    Serial.begin(9600);
    // Wire.Init is already done inside the compass library
    compass.init();
    }

    void loop()
    {
    float values_from_magnetometer[3];

    getHeading();
    values_from_magnetometer[0] = xv;
    values_from_magnetometer[1] = yv;
    values_from_magnetometer[2] = zv;
    transformation(values_from_magnetometer);

    int a = atan2( calibrated_values[1], calibrated_values[0] ) * 180.0 / PI;
    int value = a < 0 ? 360 + a : a;

    Serial.print("heading=");
    Serial.println(value);

    delay(100);
    }


    void getHeading()
    {
    int x,y,z;
    compass.read(&x, &y, &z);

    xv = (float)x;
    yv = (float)y;
    zv = (float)z;
    }

    0
    AstroHarry
    AstroHarry

    Question 8 weeks ago on Step 6

    Hi Yuri,
    first, top work you did. This is the only calibration stuff which REALLY results in useful values from any magnetometer.
    Now i have a challenge for myself. I want to put more or less all the math into an arduino-sketch. For this to accomplish, i would need to know how to calculate the "transformation matrix" and "bias" values from all the X,Y,Z measurements. Could you please tell me about that?

    Thanks and greets from Bavaria,

    Harry

    0
    stumpy0143
    stumpy0143

    Question 1 year ago on Introduction

    This looks like a great calibration program. Everything you read says you have calibrate but no one goes into this detail. Has anyone modified this for a LSM303DLHC? First that's what I have and second the HMC5883L is no longer available. But Yuri says it can be but I don't know enough about these to make the code modification.

    thanks
    John

    0
    VolkerP1
    VolkerP1

    Question 2 years ago on Step 6

    Yuri,

    could you send me your source code and/or the math to compute the 3D hard- and soft-iron calibration?

    0
    Juszczak96
    Juszczak96

    2 years ago

    Hi Yuri, could you show your code, which you used to calculate matrix transformation and bias in your program?

    0
    ROVGuy92
    ROVGuy92

    3 years ago

    I am also having the issue where MagViewer is just blank, there is no box to click or any buttons to interact with for that matter, Adruino Serial monitor is showing activity but nothing on Magviewer. Would really like a solution to know if my compass works.

    0
    ROVGuy92
    ROVGuy92

    Reply 3 years ago

    I've now purchased and tried another magnetometer and now on my screen I get heading updates, but still with your instructions Magviewer cant find any serial connection. I'm using your Arduino code and following instructions to the dot, all I've been able to do so far is either have information on my lcd screen or see some serial information in the serial plotter. Neither magviewer or magmaster do anything. More information is needed as it seems more people fail than succeed with this instructables document.

    0
    IvanK106
    IvanK106

    Reply 2 years ago

    for work MagViewer set COM1 .... COM7 not COM39 e.t.s.

    0
    Muhammad AtifS1
    Muhammad AtifS1

    3 years ago

    my magviewer have no information.please check the image.

    i Select the correct COM Port. the Baud rate is 9600.you can check in the code.

    only one thing is different that i am passing the integer value to the serial. you can also check the output on the arduino serial image.

    Arduino_Serial.pngcode.pngMagViewer.png
    0
    m4rv1nc
    m4rv1nc

    Reply 3 years ago

    same thing for me, MagViewer is empty. Serial monitor is talking..

    Maybe a Unity or Windows issues ?

    0
    nidhink299
    nidhink299

    Reply 3 years ago

    Can you solve this issue?. could u please reply as soon as possible I am also stuck

    0
    nidhink299
    nidhink299

    Reply 3 years ago

    the same thing happened to me also. How you solve this issue.

    0
    d madhuS
    d madhuS

    5 years ago

    I had calibrated the magnetometer data.

    I am able to see the sphere after calibration by as per

    IGRF data (http://www.ngdc.noaa.gov/geomag-web/#igrfwmm) at my location Magnetic field intensity is 0.42Gauss but after calibration the Magnetic field intensity is 0.46Gauss.

    How to get my data close to IGRF data.

    0
    AlyssonR2
    AlyssonR2

    Reply 5 years ago

    This method corrects for differences in the individual magnetometer sensors, but is not a callibration method on its own. If you are performing geomagnetometric measurements, you need to take the magnetometer to a location away from stray magnetic fields and take some readings. These (when averaged) will be Br and the IGRF field intensity at that location will be Bi

    The calibrated value Bc for any arbitrary measurement B will then be given by:

    Bc = B * Bi/Br

    0
    YuriMat
    YuriMat

    Reply 5 years ago

    This calibration algorithm is created for the direction of magnetic field finding.
    It is has no enough accuarcy for the magnetic field intensity finding.

    0
    d madhuS
    d madhuS

    Reply 5 years ago

    Can you suggest any algorithm for finding magnetic field intensity

    0
    nwanda
    nwanda

    5 years ago

    I tried using this program to calibrate my HMC5883L. Since the magnetometer inside a robot with some metal components around I had to change the gain of the HMC5883L since witht he previous one it was saturating (overflow in some of the registers).

    However I'm now unable to calibrate the magnetometer with this program. After calibration, I change the matrix and offset of the "test_result" arduino sketch and plot the data with the magViewer and it still shows up displaced.

    Added an image of one of the calibration attemps.

    mag_calib4.png
    0
    YuriMat
    YuriMat

    Reply 5 years ago on Introduction

    nwanda,

    can you add the screenshots of the MagViewer data before and after calibration?