A compass is a navigational instrument that measures directions in a frame of reference that is stationary relative to the surface of the earth.
We can use magnetometer to build a compass.
Magnetic distortions can be categorized as two types—hard iron and soft iron effects. Hard iron distortions arise from permanent magnets and magnetized iron or steel on the compass platform. These distortions will remain constant and in a fixed location relative to the compass for all heading orientations. Hard iron effects add a constant magnitude field component along each axes of the sensor output. The soft iron distortion arises from the interaction of the earth’s magnetic field and any magnetically soft material surrounding the compass.
This Python script implements a simple Magnetometer calibration routine to estimate soft and hard iron correction values.
The magnetomer calibration consist of collecting raw values from the magnetometer placing it in varios orientation.
Then the raw data collected are computed by one of the two script provided.
The math of the computation scripts is out of this document.
Script references:
* "ellipsoid fit" by Yury Petrov - http://www.mathworks.com/matlabcentral/fileexchange/24693-ellipsoid-fit
* "magneto" by http://www.sailboatinstruments.blogspot.com - http://sites.google.com/site/sailboatinstruments1/home
The bias obtained will correct hard iron errors, the scale factor will correct soft iron errors.
To obtain values, run this python script and follow the instructions.
A processing script is also provided to collect raw values.
Once you obtain those values you can get calibrated data by applying this formula:
xt_raw = x_raw - offsetx;
yt_raw = y_raw - offsety;
zt_raw = z_raw - offsetz;
x_calibrated = scalefactor_x[1] * xt_raw + scalefactor_x[2] * yt_raw + scalefactor_x[3] * zt_raw;
y_calibrated = scalefactor_y[1] * xt_raw + scalefactor_y[2] * yt_raw + scalefactor_y[3] * zt_raw;
z_calibrated = scalefactor_z[1] * xt_raw + scalefactor_z[2] * yt_raw + scalefactor_z[3] * zt_raw;
Once you obtain raw values using the script provided, to compute offset and
scale factor values, you can use the matlab script or magneto12 program provided.
On the microcontroller side you have to setup a function that print out to UART
raw values read from your chip.
Given 2 bytes (int16_t) variables for every axis, output the LSB and then MSB
byte ((uint8_t)(int16_t>>0) + (uint8_t)(int16_t>>8)), follow by a '\n' char.
Snippets are provided for AVR Atmega and Arduino, but it can be setup for other micro too.
Code
Notes
- read risk disclaimer
- excuse my bad english
Fantastic!!! Thank you very very much for your work. There is finally a place where one can easily get a transparent idea about making Soft Iron Calibration. Site found, steps followed, Hard and Soft Iron Calibration done.
ReplyDeleteMaría Jesús Sogorb Amorós
thank you for your feedback :)
DeleteDear Avide Gironi,
ReplyDeletethat is really interesting, I have tried to do but not successful because I am beginner. I am working with sensor HMC5883L but the "processing software" can not read any data from this sensor this is Arduino code I got from Arduno example. can you please help me to send data to processing software.
million thanks you
kindly regards.
Hoang
#include //I2C Arduino Library
#define address 0x1E //0011110b, I2C 7bit address of HMC5883
void setup(){
//Initialize Serial and I2C communications
Serial.begin(9600);
Wire.begin();
//Put the HMC5883 IC into the correct operating mode
Wire.beginTransmission(address); //open communication with HMC5883
Wire.write(0x02); //select mode register
Wire.write(0x00); //continuous measurement mode
Wire.endTransmission();
}
void loop(){
int x,y,z; //triple axis data
//Tell the HMC5883 where to begin reading data
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 lsb
}
//Print out values of each axis
Serial.print("x: ");
Serial.print(x);
Serial.print(" y: ");
Serial.print(y);
Serial.print(" z: ");
Serial.println(z);
delay(250);
}
hello,
Deletechange the serial output part of your code (Serial.print... etc..) to something the processing script magn_collectandviewpoints.pde can read, look at the "readfromserial()" method. Now i can not check that code, but something like this should work:
Serial.write(ax);
Serial.write(ax>>8);
Serial.write(ay);
Serial.write(ay>>8);
Serial.write(az);
Serial.write(az>>8);
Serial.write('\n');
thank you very much it is working now
ReplyDeletegood!
Deleteyou are welcome ;)
HI,
ReplyDeleteI want to thank you for your magnetometer calibration work. I try to execute the magn_docalibration.py script by type python magn_docalibration.py -g, when successly conducted, it should plot the picture just like in your video and output a file named magnpoints.txt right? Thing is it output nothing just stop at move magn in every position to collect correct data, press any key to continue. I have no idea, cause in the chip side I have done this:
while(UART_ReceiveData(SC1_UART)!= 0x20);
UART_SendData(SC1_UART,(uint8_t)buf[3]);
UART_SendData(SC1_UART,(uint8_t)buf[2]);
UART_SendData(SC1_UART,(uint8_t)buf[5]);
UART_SendData(SC1_UART,(uint8_t)buf[4]);
UART_SendData(SC1_UART,(uint8_t)buf[7]);
UART_SendData(SC1_UART,(uint8_t)buf[6]);
UART_SendData(SC1_UART,'\n');
Those buf are configured just like you said.
Can you helo me, thanks a lot.
Hello, you could use the python script (using the - g option), or the processing script to collect points.
DeleteUsing the python script you should see how many point are been collected.
If you are skilled with Java, try debug it with the processing script. Try to understand what does is sent by the micro.
Hi Davide!
ReplyDeleteLooks great
By any chance do you have the Ellipsoid code in python too?
Thanks
Morgan
Hello. Thank you for the feedback.
DeleteAbout the python Ellipsoid version, not in the next future. I'm sorry.
Hi David, to ensure Im using your tool(magneto 1.2) correctly I have some questions can I send you a direct email? I connected with you on hangouts
ReplyDelete1) This is what I calculate for Norm of Magnetic field:
For LSM303DLHC Data Sheet
=========================
GN bits set to 001 - +/- 1.3Gauss
Gain (LSB/Gauss) - 1100
Cork - 48,709.0 nT
Latitude - 51° 53' 53"
Longitude - 8° 29' 28"
Total Field - 48,709.0 nT
Convert to Gauss - 0.48709
Raw Total Field - 535.799 Gauss
2) I have raw magnetometer data and use that as 'h' ....
3) I click calibrate and get the fields for 'b' and A^-1 filled in ...
The last matrix (3x£3) which is A I believe ? is this the inverse of A^-1 ? I entered A^-1 in Matlab and then computed inv(A) but A*A^-1 I dont get a unity matrix? I must be missing something
In the python code you have the following:
ce = [-99.7, -154.0, -22.7] .. (1)
m1 = [0.952017, 0.00195895, 0.0139661] ..(2)
m2 = [0.00195895, 0.882824, 0.00760243]...(3)
m3 = [0.0139661, 0.00760243, 0.995365] ..(4)
In Matlab I get :
>> magnetometer_calibration
Ellipsoid center :
0.115 0.0126 0.056 ... (5)
Ellipsoid radii :
0.474 0.375 0.346 .. (6)
Ellipsoid evecs
0.930281 -0.366051 0.0241799 ... (7)
0.265757 0.627023 -0.732268 ...(8)
0.252886 0.68764 0.680587 .. (9)
Ellpisoid comp evecs :
0.761667 0.0790756 0.00866253 .. (10)
0.0790756 0.93419 0.0371094... (11)
0.00866253 0.0371094 0.959287 ... (12)
Is (1) in the python equivalent to (5) from Matlab above ?
(2),(3),(4) equivalent then to (10),(11),(12) ?
Thanks for the help Davide
I have some sample data that I can share to do a quick sanity .. if it is okay to send you an email then I could explain better there?
Hello.
DeleteYes, Ellipsoid center (5) is ce vector (1), and yes, vestor m1,2,and 3 (2), (3), (4) are Ellipsoid comp evecs vectors (10), (11), (12)
Your offset values (ellpisoid center) seems too small to me, especially if compared to your ellipsoid shape.
Yes, send me that email, but i tell you beforehand that I do not have time to do this type of sanity check in this period.
This comment has been removed by the author.
ReplyDeleteHi Davide,
ReplyDeleteSeem to have some problems posting ... will try again
I have MagCal and Magneto matching alright using a 'Norm of Magnetic or Gravitational Field ' of 0.48709
Magneto computes inverse A but these values do not match the matlab:
Combined bias(b) :
0.105409 0.024840 0.064395
A^-1 :
1.166645 0.083580 0.013880
0.083580 1.376303 0.046656
0.013880 0.046656 1.388847
For Matlab I get the following
>> magnetometer_calibration
Ellipsoid center :
0.115 0.0126 0.056
Ellipsoid radii :
0.474 0.375 0.346
Ellipsoid evecs :
0.930281 -0.366051 0.0241799
0.265757 0.627023 -0.732268
0.252886 0.68764 0.680587
Ellpisoid comp evecs :
0.761667 0.0790756 0.00866253
0.0790756 0.93419 0.0371094
0.00866253 0.0371094 0.959287
The bias of both look similar(?) but the matrices look quite different. I notice that the Matlab does not factor in 'Hm' (the Earths Magnetic Field)?
ReplyDeleteHere is some of my data (I can share more if I could send you an email):
-0.21300000 0.20000000 0.11200000
-0.19500000 0.06900000 -0.13100000
0.26900000 0.17800000 0.30200000
-0.14700000 0.04300000 -0.19500000
0.41300000 -0.00800000 0.21400000
-0.07800000 0.16500000 -0.22400000
0.40800000 0.21300000 0.04800000
-0.12600000 0.01300000 -0.24300000
0.22100000 0.34300000 -0.02400000
-0.06900000 0.33000000 -0.04300000
0.26500000 0.15200000 -0.23400000
0.02600000 0.10400000 -0.26300000
-0.10400000 0.20800000 -0.17500000
-0.08200000 0.30000000 -0.06800000
0.41300000 0.26000000 0.06300000
-0.15200000 0.13400000 -0.17000000
0.34700000 0.26500000 -0.07300000
0.18600000 0.19100000 -0.23400000
0.26000000 0.20800000 -0.19000000
0.36900000 0.18200000 0.24800000
0.47300000 0.07300000 0.07300000
-0.22600000 0.17800000 0.01400000
-0.14700000 0.24700000 -0.11700000
0.23000000 0.30400000 0.24300000
0.03400000 0.22600000 -0.21900000
0.27800000 -0.07300000 0.35100000
0.27300000 -0.31300000 0.08700000
0.15200000 -0.33900000 0.14100000
0.01700000 0.38200000 0.18500000
0.20400000 -0.21700000 -0.16500000
0.29100000 0.31300000 0.15100000
0.40000000 0.05600000 0.25800000
0.41300000 -0.18600000 -0.02400000
0.44700000 -0.09500000 -0.02400000
0.33400000 0.32600000 -0.00900000
0.03900000 0.33400000 -0.13100000
-0.19100000 0.19500000 -0.08200000
-0.13000000 0.10400000 0.32600000
-0.08200000 -0.09100000 0.35600000
0.33000000 -0.23900000 0.23400000
0.00400000 0.31300000 0.29200000
0.27800000 0.13400000 -0.24300000
0.17300000 -0.02600000 0.39500000
0.18200000 -0.16500000 0.33100000
0.42600000 0.14300000 0.16500000
0.19500000 -0.33400000 0.02900000
0.26000000 -0.26900000 -0.08700000
0.19500000 -0.04300000 0.36500000
0.36000000 -0.06900000 0.28200000
0.39500000 0.18600000 0.17500000
0.35600000 -0.09500000 0.30200000
0.27300000 -0.30000000 -0.04300000
0.20800000 -0.32600000 -0.01400000
0.36900000 0.26900000 0.15600000
-0.13000000 0.26000000 0.23400000
-0.01700000 -0.27300000 0.25300000
0.45200000 -0.16000000 0.08700000
0.30000000 0.00800000 -0.24300000
0.39100000 -0.22600000 0.11200000
0.26500000 -0.17300000 -0.19500000
0.46500000 -0.06900000 0.10200000
0.09500000 0.28600000 -0.20000000
-0.01300000 0.23000000 -0.22400000
-0.07800000 0.30800000 0.22900000
0.22600000 -0.03000000 0.37500000
0.04300000 -0.02100000 -0.27300000
0.30000000 0.09100000 -0.23400000
0.25200000 -0.06000000 0.34100000
0.33400000 -0.04700000 0.29700000
0.20800000 0.29100000 0.25800000
-0.12600000 -0.09100000 0.32100000
0.10000000 -0.32600000 -0.01400000
0.48200000 0.00000000 0.00000000
0.35600000 -0.10800000 0.29200000
0.42600000 0.06000000 -0.11200000
ReplyDeleteI have put some of my data up on Google Docs ... when you have some time can you have a look for me thanks
https://docs.google.com/document/d/1hIvlzmd92Pt76edXUp1JY0g_7ydeiY2YPl4pvC8FhzY/edit?usp=sharing
Hello,
DeleteMagneto uses a slightly different math for the Ellipsoid calculation. But the values should be similar.
Try with another magnetometer, the one that's looks odds to me are the ellipsoid center (offset) values.
This comment has been removed by the author.
ReplyDeleteHello thank you for your good projects .I download this project and when I run python script I get this massage: "ImportError: No module named serial"
ReplyDeleteHello, You have to install pyserial on python.
Deletehello excuse me for these questions i'm not familiar to python i install pyserial on python and i no get this error:
ReplyDeleteTraceback (most recent call last):
File "C:\Users\mazir\Desktop\Elctronic Project\campass calibration software\magn_docalibration.py", line 18, in
from mpl_toolkits.mplot3d import Axes3D
ImportError: No module named 'mpl_toolkits'
No problem. "No module named" means that you have to install that module, So you have to install the mpl_toolkits module. More generally, you can find usefull information on Traceback googling aroud for the error. You should encounter a few if you have no module installed.
DeleteThis comment has been removed by the author.
DeleteThis comment has been removed by the author.
ReplyDeletehello I finally could run magn_docalibration.py and gave this massage :
ReplyDeleteNew folder\magn_docalibration.py
Magnetometer Calibration functions 01
Usage: magn_docalibration.py [options]
Options:
-h, --help show this help message and exit
-d, --debug debug output
-g, --get collect data from chip
-p, --plot plot raw values collected
-t, --testcalib compute estimation of collected data and do plot, need
calibration points to be setup with other script
Now what I should do to plot?
Hello.
DeleteIt's the python script help. As example run "magn_docalibration.py -g" to collect data.
Then you could use the matlab script provided to compute calibration values.
Tip: you can also collect the data using the processing sketch (like I do in the youtube video on this page)
hello
ReplyDeleteexcuse me I'm a little confused.I connect hmc5883l(gy_271) to AVR board and then to serial com1 on my computer and load hex file to AVR Atmega16l then run magn_docalibration.py in python shell and now what I have to do to plot like you do in youtube video? I can see hmc5883l send data to hyper terminal .
You have to collect data points. You can do this by the processing sketck, or using the magn_docalibration.py script.
Deleteand when I run magn_docalibration.py -g
ReplyDeleteI get the following error:
Traceback (most recent call last):
File "", line 1, in
magn_docalibration.py -g
NameError: name 'magn_docalibration' is not defined
This script is writte on Python 2.7, that may be the problem.
Deletejust right now I install python2.7 nothing change I will try some other code to do it .I'm new in python thank you
ReplyDeleteNo problem at all. It should have somthing to do with your version of python, here I've no problem. you could try python -V to check your python version. Also try the processing.org script to collect the data point. That could be easyer.
Deletewhere I should write python -V?in python shell or cmd?
ReplyDeleteIn your command prompt or terminal. Here you can find a Python tutorial that may help you: http://www.tutorialspoint.com/python/
Deletehello i can't run python script .I want to collect 100 point in then run ellipsoid fitting to these points .all in atmega16 without any PC. can you give me an algorithm to how can I do it?
ReplyDeleteHello, you can collect 100 point to an array, then use this array of points as you need.
Deletehello .i can't run python script .i want to run the ellipsoid fitting in atmega16 .collecting 100 point and then run fitting part. can you give me an algorithm how to do it?
ReplyDeleteIf you can not run the python script, you can run the processing.org script provided in the download link of this page in order to collect the points.
Deletei can't find processing.org script ? where is it?
ReplyDeleteIt's the magn_collectandviewpoints\magn_collectandviewpoints.pde file.
Deletehello . I connect hmc5883l to atmega16 and connect them to com1 and I can see numbers on hyperterminal and when run python script in windows cmd , first i get this massage:
ReplyDelete"Usage: magn_docalibration.py [options]
Options:
-h, --help show this help message and exit
-d, --debug debug output
-g, --get collect data from chip
-p, --plot plot raw values collected
-t, --testcalib compute estimation of collected data and do plot, need
calibration points to be setup with other script "
and then i type "magn_docalibration.py -g" i get this massage " move magn in every position to collect correct data, press any key to continue" . and then i move magn in every position and then press enter nothing happened what should i do? no point collected
I suppose there's something wrong in your python library, you should get points collected to a magnpoints.txt file. You have to debug the python script, check the collectpoints method.
Deleteis there any manipulation of code to do it right? which code have to be programmed to avr?
ReplyDeleteThe avr firmware sample can be found in the readme file, the "avr-gcc snippet" part, if you are using avrgcc as compiler. For debugging the python code, the most simple way is to use the print function, or you should use the python debugger.
Deleteexcuse me can you record a short video of python code running?
ReplyDeleteand send your code to my email: maziar111@gmail.com i try so but nothing i can read degree in lcd 16*2 and usart but python nothing
Hello. I'm sorry but i can not do this. I'm actually envolved full time in other project, the point collection running in python is something like the one you see in the video of this post, which is running on processing.org. If you can not run the python script, my suggestion is to run the processing script. Or find another script online to collect your points from the magnetometer.
DeleteThis comment has been removed by the author.
ReplyDeleteHello in magn_docalibration.h file i found code line:
ReplyDelete//wait for the input request
while(cgetc() != 0x22);
what this mean?
It means, wait until a 0x22 it is read by the uart library of your micro.
Deletehello excuse me again i'm totally cunfused what's problem. in python I open magn_docalibration.py and in RUN menu Run Moudle and i get first this massege:
ReplyDelete"" Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:38:48) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>>
RESTART: C:\Users\mazir\Desktop\Elctronic Project\campass calibration software\magn_docalibration.py
Magnetometer Calibration functions 01
Usage: magn_docalibration.py [options]
Options:
-h, --help show this help message and exit
-d, --debug debug output
-g, --get collect data from chip
-p, --plot plot raw values collected
-t, --testcalib compute estimation of collected data and do plot, need
calibration points to be setup with other script""
After that when I TYPE:""magn_docalibration.py -g"" I get this massage:
""Traceback (most recent call last):
File "", line 1, in
magn_docalibration.py -g
NameError: name 'magn_docalibration' is not defined
>>>
""
and I totaly confused what should I do"" PLEASE HELP ME ""
Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:38:48)
Deletethis is whole PYTHON:
[MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>>
RESTART: C:\Users\mazir\Desktop\Elctronic Project\campass calibration software\magn_docalibration.py
Magnetometer Calibration functions 01
Usage: magn_docalibration.py [options]
Options:
-h, --help show this help message and exit
-d, --debug debug output
-g, --get collect data from chip
-p, --plot plot raw values collected
-t, --testcalib compute estimation of collected data and do plot, need
calibration points to be setup with other script
>>> magn_docalibration.py -g
Traceback (most recent call last):
File "", line 1, in
magn_docalibration.py -g
NameError: name 'magn_docalibration' is not defined
>>>
hello again I programmed my avr and connect to com1 by usart when I run processing.org i get this massage
ReplyDelete"Display -1 does not exist, using the default display instead.
WARNING: RXTX Version mismatch
Jar version = RXTX-2.2pre1
native lib Version = RXTX-2.2pre2
OpenGL error 1280 at after bind: invalid enumerant
"
Hello, this is a processing.org error on the RXTX port, you can find usefull information to recover this error on the processing.org forum. You can start checking if your Java Runtime edition fits the processing.org version. Also try to start some processing.org sample, to see if event the samples sketch does not works.
DeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHey Davide !
ReplyDeleteYour work is awesome !
I would like to use the matlab function to calibrate my magnetometer.
I run it and it works perfectly. However, I need to calculate the calibrated data right ?
You said that we have to use the scale factor and offset value to get the new data but I don't see those variables in the matlab function.
Could you help me ?
Thank you very much!
Yann
Hello, and thank you for your feedback. Look at minute 2:18 of my youtube video, the matlab output you have to use is the one i'm selecting.
DeleteOk thank you for answering.
DeleteTell me if I am write :
e_center are the x,y,z offset and comp (line 1) = scalefactor_x and comp (line2) and comp(line3) are y and z respectively ?
Actually I calculate that and I don't get a perfect circle for the calibrated data, I think I should, should I ?
Moreover, if I calculate the module of the x,y and z (u = sqrt(x.^2 + y.^2 + z.^2) I should find the same one, right ?
Thank you for your time.
I also don't use Ellipsoid radii and Ellipsoid evecs, is it normal ?
DeleteHello, take a look at the "MorganMay 15, 2015 at 1:28 PM" comment and reply.
DeleteThank you for taking the time to answer.
DeleteActually I read his comments and replies but it does not seem to work correctly. So I probably make a mistake somewhere.
Fisrt when I run the matlab code I get a ellipse at the end.. I should get a circle right ?
A good calibration leads to a circle, isn't it ?
Second I used Magneto 1.2, and I don't succeed by this way also.
To be sure in Norm of Magnetic I put the one I would like to reach or I put the one I calculate from the raw data (if it's points 2, the norm is different at every point since it's not calibrated yet).
Thank you for your help. It's been a while I am working on this magnetometer calibration and it seems strange that it still does not work properly...
The green image should be a the fitted ellipsoid. Should be something next to a circle.
DeleteAt first, what calibration does not works for you? soft, or hard iron distortion calibration?
Hello Davide! Sorry I have not seen you reply. Thank you.
DeleteI don't exactly know (how can I know this ?)
After the calibration, I plot the 3 angles (using atan2 on matlab).
And when I move the device only around one axis, I should find a angle of zero (around zero) for one of the three angles, and I don't.
So I suppose that the calibration process is wrong.
I don't know if you see what I mean.
If you put a magnet next to you magnetometer it will procude hard-iron distorsion. It is identified on the graph by an offset of the original of the collected point to the graph origin (0,0). Indeed the soft-iron distorsion is visibile by a non perfect circle, collected points will look like an ellipse.
DeleteWhat angles are you talking about?
Ok thank you for the answer.
DeleteSo I did not solve both distorsion. I have an offset (this is pretty easy to correct I think) and I also get a kind of an ellispe, so this is soft_iron distorsion.
I would like to get the angle of my device related to the north. So forward/backwar axis is x, medio-lateral is y and vertical is z. So I need the angle between z and y.
Thank you for helping me.
I'm sorry but I don't get it. Usually, if your z-axis is parallel to ground, you get y and x axis value, then you measure the heading of your device by arctan2 those values. Then you transform this value to degree, and you add the magnetic declination for your location.
DeleteOk thank you for your help. I will keep going to find my needs.
DeleteThis comment has been removed by the author.
ReplyDeletehello processing running without any error and avr(main.c programmed to avr) send code to com1 but no point shown in processing 3d plot. is there any code manipulation needed? or i'm programmed wrong code on avr?
ReplyDeleteWhat do you get in processing reading routine? Debug there.
DeleteHello thank you for your great work.I'm using Arduino2560mega.my code is:
ReplyDelete#include "Wire.h"
#include "HMC5883L.h"
HMC5883L compass; //Copy the folder "HMC5883L" in the folder "C:\Program Files\Arduino\libraries" and restart the arduino IDE.
int16_t xv, yv, zv;
void setup()
{
Serial.begin(9600);
Wire.begin();
compass = HMC5883L();
setupHMC5883L();
}
void loop()
{
getHeading();
Serial.flush();
Serial.print(xv);
Serial.print(",");
Serial.print(yv);
Serial.print(",");
Serial.print(zv);
Serial.println();
//Serial.write(xv);
//Serial.write(xv>>8);
//Serial.write(yv);
//Serial.write(yv>>8);
//Serial.write(zv);
//Serial.write(zv>>8);
//Serial.write('\n');
// delay(100);
}
void setupHMC5883L()
{
compass.SetScale(0.88);
compass.SetMeasurementMode(Measurement_Continuous);
}
void getHeading()
{
MagnetometerRaw raw = compass.ReadRawAxis();
xv = (float)raw.XAxis;
yv = (float)raw.YAxis;
zv = (float)raw.ZAxis;
}
in hyperterminal can see:
29,476,455
29,476,455
29,476,455
28,479,456
28,479,456
28,479,456
28,479,456
28,479,456
30,475,461
30,475,461
30,475,461
30,475,461
30,475,461
28,479,455
28,479,455
28,479,455
28,479,455
28,479,455
27,473,455
27,473,455
27,473,455
27,473,455
27,473,455
27,477,461
31,477,461
31,477,461
31,477,461
31,477,461
hyperterminal show x,y,z. I want to use your processing sketch.
what changes in my code is needed?
Hello. You have to use the commented part of "//Serial.write". Please do not flood with data comments.
DeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeletehello again.I use commented codes:
ReplyDeleteSerial.write(xv);
Serial.write(xv>>8);
Serial.write(yv);
Serial.write(yv>>8);
Serial.write(zv);
Serial.write(zv>>8);
Serial.write('\n');
and programmed arduino
and changes processing codes line to:
static String serialport = "COM4";
static int serialbaud = 9600;
processing is running but no point shown 0/1000. it's like processing sketch don't get the serial numbers .but when I use HyperTerminal instead of processing , I can see Numbers changes in HyperTerminal of windows7.
So, it seems something related to you processing engine. You have to debug the serialEvent. At first, write a new sketch and a new simple rom for your micro, and test if it works. It should be simpler this way.
Deletehello I found the processing code problem by do //port.write(0x22); the processing plot points. i think there is problem with port.write command. thank you so much your work is so great.
ReplyDeleteGood job!
Deletehello thank you Davide thank you ariyan.I comment //while(cgetc() != 0x22); in magn_docalibration.h and also commend //port.write(0x22); in processing . and everything work good thank you so much.
ReplyDeleteHappy to hear this!
DeleteHello David i think that this is not a reel time calibration am i right ?
ReplyDeleteHello, not this one. But you can implement it insiede the microcontroller logic.
DeleteThis comment has been removed by the author.
ReplyDeleteHi Davide Gironi,
ReplyDeleteThank you for a great post.
I am calibrating the magnetometer follow your post.
I read to your second reference [ https://sites.google.com/site/sailboatinstruments1/proof ]
On step 2 of [ E. Geometric interpretation ]
would you mind explain for me why it need to multiple inverse rotation?
Thank you,
Dear Minh, unluckily this post here was from 2013, I've forgot the math behind this, I've to read it and study this again, but I've not time to do this now.
DeleteThank you for your reply,
DeleteI have tried calibrate the magnetometer (BMX055 from BOSCH)
But it didnot work well.
The ellipsoid fitting function as already mention in your guideline was not work well. It just draw a 1/4 mesh of ellipsoid shape in the result. Have you seen this situation before?
Thank you.
Sorry for my English.
Never happened. I've used this calibration routine 6 month ago. And it works. You can check if the scripts that collect the points works well. Then try the "magneto" tools also.
DeleteWould you mind have a look on my Matlab code. I have checked my code and I can not figure out what happend. It recieves the data of magnetometer (x,y,z order):
ReplyDelete///////////
%% Connect to arduino
clc;
delete(instrfindall);
Port = 'COM3';
BaudRate = 9600;
DataBits = 8;
Parity = 'None';
s = serial(Port);
set(s, 'BaudRate', BaudRate);
set(s, 'DataBits', DataBits);
set(s, 'Parity', Parity);
set(s, 'StopBits', 1);
fopen(s);
%% Take sample for arduino
sample = 4000;
x = [];
y = [];
z = [];
fprintf( 'Taking sample now ');
for element_th = 1:1:sample
temp = fgets(s);
k = strsplit(temp);
x(element_th) = str2double(k(1));
y(element_th) = str2double(k(2));
z(element_th) = str2double(k(3));
display(temp);
display(element_th);
plot3(x,y,z,'.');
drawnow;
end
x(1) = x(2);
%% Plot
%plot3(x,y,z,'o');
%% Fitting
x = transpose(x);
y = transpose(y);
z = transpose(z);
%%
% [center, radii, evecs, pars ] = ellipsoid_fit([x y z]);
% plot3(x,y,z,'.');
% display(center)
% display(radii)
% display(evecs)
% display(pars)
% do ellipsoid fitting
[e_center, e_radii, e_eigenvecs, e_algebraic] = ellipsoid_fit([x, y, z]);
% compensate distorted magnetometer data
% e_eigenvecs is an orthogonal matrix, so ' can be used instead of inv()
S = [x - e_center(1), y - e_center(2), z - e_center(3)]'; % translate and make array
scale = inv([e_radii(1) 0 0; 0 e_radii(2) 0; 0 0 e_radii(3)]) * min(e_radii); % scaling matrix
map = e_eigenvecs'; % transformation matrix to map ellipsoid axes to coordinate system axes
invmap = e_eigenvecs; % inverse of above
comp = invmap * scale * map;
S = comp * S; % do compensation
% output info
fprintf( 'Ellipsoid center :\n %.3g %.3g %.3g\n', e_center );
fprintf( 'Ellipsoid radii :\n %.3g %.3g %.3g\n', e_radii );
fprintf( 'Ellipsoid evecs :\n %.6g %.6g %.6g\n %.6g %.6g %.6g\n %.6g %.6g %.6g\n', e_eigenvecs );
fprintf( 'Ellpisoid comp evecs :\n %.6g %.6g %.6g\n %.6g %.6g %.6g\n %.6g %.6g %.6g\n', comp);
% draw data
figure;
hold on;
plot3( x, y, z, '.r' ); % original magnetometer data
plot3(S(1,:), S(2,:), S(3,:), 'b.'); % compensated data
view( -70, 40 );
axis vis3d;
axis equal;
% draw ellipsoid fit
figure;
hold on;
plot3( x, y, z, '.r' );
maxd = max(e_radii);
step = maxd / 30;
[xp, yp, zp] = meshgrid(-maxd:step:maxd + e_center(1), -maxd:step:maxd + e_center(2), -maxd:step:maxd + e_center(3));
Ellipsoid = e_algebraic(1) *xp.*xp + e_algebraic(2) * yp.*yp + e_algebraic(3) * zp.*zp + ...
2*e_algebraic(4) *xp.*yp + 2*e_algebraic(5) * xp.*zp + 2*e_algebraic(6) * yp.*zp + ...
2*e_algebraic(7) *xp + 2*e_algebraic(8) * yp + 2*e_algebraic(9) * zp;
p = patch(isosurface(xp, yp, zp, Ellipsoid, 1));
set(p, 'FaceColor', 'g', 'EdgeColor', 'none');
alpha(0.5);
view( -70, 40 );
axis vis3d;
axis equal;
camlight;
lighting phong;
%%
fclose(s);
/////////
Thank you.
Dear Minh, to get data first start with the python script provided or with the processing one. Then, if all goes ok with that scripts, you can rewrite it in Matlab.
Deletei cant find
ReplyDeletemagn_collectandviewpoints.pde
oh okay it was in avr_helper_magn_docalibration_01.zip
DeleteHello omeranar, great! You find it :) Hope is working, cause it's a bit outdated project.
DeleteThere is a small challenge in this , let's say i dont want to get into any hassle of the python script of anything i want the calibration to be a part of my main application code in the arduino , then how do i execute this ?
ReplyDeleteHello, you can build your own script to retrive data points, then use "ellipsoid fit" matlab script or "magneto" software.
DeleteHi
ReplyDeleteCould you tell me some features of using the Magwick filter? I am currently developing a spatial adjustment device based on the MPU6050 and HMC5883, but the device does not work correctly. I would appreciate any help.
Hello, you can find a Mahony filter implemented there in my driver http://davidegironi.blogspot.com/2013/02/avr-atmega-mpu6050-gyroscope-and.html. That's nothing more than the matematical model proposed by Mahony and Magwick. Honestly I've done this back in the 2013 so I have to recall my memories. What I can tell you is that although the MPU6050 DMP processor save your microcontroller resources, the Mahony filter in my opinion works a little better. You have to pay attention to the calibration of course.
Delete