How do I convert raw xyz Magnetometer data to a heading?

Cypher236 picture Cypher236 · Feb 24, 2016 · Viewed 18k times · Source

I'm using an embedded device with a simple 3-axis Magnetometer on it. I have it currently displaying the X Y Z values in micro Teslas but how do I convert these into a compass heading? I have tried looking it up on Google but everything I find seems extremely complicated/poorly explained.

If possible I'd like to know how to do it both tilt-compensated and also without compensating for tilt.

The values I'm currently getting on a flat surface for X, Y, Z are 70,0.8 and 34.1 respectively in case that somehow helps.

P.S In case it helps here is a snippet of the code I'm using for the magnetometer:

mSensor.enable();

while(true){
    wait(1);
    mSensor.getAxis(mData);
    lcd.cls();
    lcd.locate(0,3);
    lcd.printf("X=%4.1f micro-Tesla\n\rY=%4.1f micro-Tesla\n\rZ=%4.1f micro-Tesla", mData.x, mData.y, mData.z);

Answer

alain picture alain · Feb 24, 2016

Without compensation for tilt it's not too complicated:

angle = atan2(Y, X);

That's actually the same as converting a vector in cartesian coordinates [X, Y] to a vector in polar coordinates [length, angle], without needing the length.

For the tilt-compensated version, you need to project the 3D-vector [X, Y, Z] onto a plane [X2, Y2] first and then use the same formula as before. But to do that you would need an accelerometer to know the amount of tilt.