Advanced hard and soft iron magnetometer calibration for dummies

If you bought the cheap magnetomter module like HMC5883L you can not use it without calibration. Measurement of magnetic field will be subjected to distortion. There are two categories of these distortions: the hard iron distortions and the soft iron distortions. The hard iron errors refer to the presence of magnetic fields around the sensor (magnets, power supply wires) and are related to measurement offset errors, while the soft iron errors refer to the presence of ferromagnetic materials around the sensor, which skew the density of the Earth's magnetic field locally and are related to scaling offset errors. You can read more information about these distortions here.

In other words, to get the correct magnetometer data you should get the calibrated magnetometer data. One of the ways to resolve this problem: you should apply the bias to the vector of the non calibrated magnetometer data (X, Y, Z coordinates) and then multiply the transformation matrix by this resulting vector:

Picture 1

In this case the magnetometer calibration is the process of getting the transformation matrix and the bias. To get these data you can use the MagMaster program.

You can download MagMaster here.

Example of using the MagMaster



  • MagMaster (placed in MagMaster folder)
  • MagViewer (placed in MagMaster folder)


  • Arduino Sketch (placed in MagMaster folder)

Picture 2

Picture 3

Picture 4

Connect the magnetometer module to the arduino board via I2C bus (picture 4). Upload the arduino sketch to the arduino board (see "Arduino_Code" folder in the "MagMaster" folder). This arduino sketch requires the HMC5883L library, copy the folder "HMC5883L" (placed in "Arduino_Code" folder)  to the folder "C:\Program Files\Arduino\libraries".

Then 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 5, video 1, 2). These data are not calibrated yet.

Picture 5

Video 1

Video 2

If you see the points of the magnetometer vector coordinates in 3D space the arduino board and the PC connection works right.

Now close the MagViewer window and run the MagMaster.exe (picture 6). Select the serial port of the arduino board. The green strings X, Y, Z will indicates the coordinates of the magnetometer vector.

Picture 6

Place the magnetometer module as shown on the picture 8.1 and click "Point 0" button of the "Axis X+" groupbox. For the placement of the module you can use the wooden bar or the paper box (picture 7). If you can not connect your magnetometer device to PC then you can use any other way to get to know the magnetometer data. You can enter these data in the program manually.

Picture 7

Place the magnetometer as shown on the picture 8.2 and click "Point 180" button of the "Axis X+" groupbox and so on. You should do in the following way:

  • Picture 8.1: "Point 0", "Axis X+"
  • Picture 8.2: "Point 180", "Axis X+"
  • Picture 8.3: "Point 0", "Axis X-"
  • Picture 8.4: "Point 180", "Axis X-"
  • Picture 8.5: "Point 0", "Axis Y+"
  • Picture 8.6: "Point 180", "Axis Y+"
  • Picture 8.7: "Point 0", "Axis Y-"
  • Picture 8.8: "Point 180", "Axis Y-"
  • Picture 8.9: "Point 0", "Axis Z+"
  • Picture 8.10: "Point 180", "Axis Z+"
  • Picture 8.11: "Point 0", "Axis Z-"
  • Picture 8.12: "Point 180", "Axis Z-"

Picture 8

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

Picture 9

The transformation matrix and the bias are got. Now you can calculate the calibrated magnetometer data in your device on a real time with using the matrix and the bias as shown on picture 1. The example of the arduino sketch of using this calculation you can find in the "Arduino_Test_Results" folder.

You can apply the sphere radius stabilization algorithm to your program (use for it the Arduino_Radius_Stabilization folder placed in MagMaster folder).

The calibrated magnetometer vector coordinates in 3D space with the radius stabilization shown on the picture 10 and video 3, 4.

Picture 10

Video 3

Video 4

Using of the arduino is only example, you can easy adopt the arduino code for any other system and use the MagMaster program with it.

Views: 123309

Comment by Harry on July 13, 2016 at 6:07am

I want to try that, but I'm still messing with my own app.  Here's a shot of 3DScatter which I modified to show the difference between Yuri's calibrated data and the raw data.

Comment by Phil on July 25, 2016 at 8:57pm

Ok some weird things going on here…


I am using a Arduino Nano Clone with an onboard CH340 USB<->Serial bridge.

At the beginning I had the same problems as Tim C (page 3-4) and could see the changing values in the SerialMonitor using your Arduino_Code.ino.

The bad thing: MagViewer.exe did not show any dots and also MagMaster.exe didn’t work.


I changed the port on my Windows 7 PC from COM14 to COM5, because I read that high COM-Port numbers causes issues.

Then it started to work.

I could use MagViewer and MagMaster with no problem for about 30min.

I did a screenshot after calibration.

I then wanted to play a little with MagViewer and also do it later again with my values from to increase the accuracy but after some time, MagViewer stopped doing the dots!

I started MagViewer again: only 1 dot... no more.

Reconnecting the Arduino and try it again.



I then changed the COM-Port on the PC again (this time to COM6). This didn’t solve it.

I also used the Arduino_Code.ino and the values did not change when I move the HMC5883L.


I didn’t check before (cause Arduio_Code.ino worked from the start), but I used an I2C scanner and saw that the address is 0x68. The weird thing is, that I see that the 0x1E address, that is set in the HMC5883L.h, was working before.

Don’t know if the address could have changed or something.

I am able (with another library and my own sketch) to test the compass and is still working. (so a hardware damage is not the case).


In the library (the one given here) I used the HMC5883L_Example.ino.

It gives me


Starting the I2C interface.

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:      929   1667   808                  Scaled: 852.84   1533.64   743.36               Heading:             1.11 Radians      63.54 Degrees                  

Raw:      929   1667   808                  Scaled: 852.84   1533.64   743.36               Heading:             1.11 Radians      63.54 Degrees 



The values doesn’t change when I move the HMC5883L.

The same for the Arduino_Code.ino.

It puts out:









When I change the address in the HMC5883L.h from 0x1E to 0x68 it gives me:



Starting the I2C interface.

Constructing new HMC5883L

Setting scale to +/- 1.3 Ga

Setting measurement mode to continous.

Raw:      -8208   -18698   -8702      Scaled: -7551.36   -17202.16   -8005.84                   Heading:             4.34 Radians      248.92 Degrees             

Raw:      -8208   -18698   -8702      Scaled: -7551.36   -17202.16   -8005.84                   Heading:             4.34 Radians      248.92 Degrees 


The values also doesn’t change here but the “Entered scale was not valid” error is gone…


On the Arduino_Code.ino the values also doesn’t change:









This was all confirmed at 3 different Arduino Nanos, that all never did any faults.

I also did check this on an Arduino Uno and have the same problems here.


Any ideas or hints are really appreciated.

I have no ideas left.

Comment by Guntram on March 14, 2017 at 11:01am
Hi Yuri, you have done a great Job with this blog! Now I'm able to understand the challanges. I've downloaded the rar file immediately, but a few years later I have recived on the importand file some compiler Errors. I've used an arduino megaADK IDE 1.6.9. Later a BN 880 with a HMC5883L should be calibrated.
Can you help me some how, to get the code running?
Comment by Ian Steward on August 10, 2018 at 5:33pm

I have tried to get MagMaster and MagViewer to connect to a serial port without success. I can succesfully connect the device my Arduino(Mega) on my PC. and I can see all the data flowing. I have tried COM1, COM6 and COM72 but nothing works. I get no data points shown in Magviewer and MagMaster tells me that I have no port name or just port error. Has anyone come across the same issues. Help would be appreciated. Also any other options to get my HMC5883L calibrated??

Comment by Frank Paynter on August 10, 2018 at 5:54pm

Try my magnetometer calibration tool, based on an Matlab script written  by Alain Barraud.  For the whole saga start with and then parts 2, 3, & 4.  If you want to skip to the end, all the required code (except Octave itself) is on my GitHub site at 

Hope this helps,


Comment by Pablo on January 4, 2019 at 5:33am

Hello, I would like to use the software that you have created but with the MPU9250, for that I would have to occupy any scketch for MPU9250 in such a way that it throws through the serial port MagX, MagY, MagZ ?, or I must calibrate before the gyroscope and accelerometer and then print on the serial MagX, MagY, MagZ?

Comment by Faruk Sözüer on January 9, 2020 at 5:43am

Hello Yuri;

Thanks for the work. I couldn't run MagViewer. The data is not processed.  MagMaster works fine. 

My serial port data outputs are as follows. Baudrate 9600, message send 10Hz.



You need to be a member of DIY Drones to add comments!

Join DIY Drones

© 2020   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service