# Tilt-compensated compass - at my wits' end

I'm a bit at my wits' end here - I'm trying to build a tilt compensated compass for my autonomous sailboat (ardusailor!). I'm using an InvenSense MPU9150. Originally, I used the built-in fusion support on the sensor to get a quaternion, pull the yaw/pitch/roll angles from that, and then use this formula to do the tilt compensation:

float heading = atan2(-(mz * s_phi - my * c_phi), mx * c_theta + my * s_theta * s_phi + mz * s_theta * c_phi);


where the various s_angle is sin(angle) and c_angle is cos(angle). That didn't work. I tried using a vector-based approach stolen from here. That didn't work. Then, I took away the tilt compensation, and just did an uncompensated atan2(Yh,Xh), and that produced very strange result as well.

Basically, as I rotate the sensor about the z axis, the value rotates between 70 and -10 degrees, completing a full circle (i.e. as i make a 360 degree rotation, it starts at 70, gets to -10, and then back up to 70). 70 is at about 0* magnetic, 10 is at about 180, 0 is at about 70-80.

I see the same behavior from an HMC5883L magnetometer chip as well. The thing is, looking at raw values, I get magnetic values that seem fine, and hard and soft iron offsets are in place:

top row is corrected for offsets (using an ellipsoid fit method), bottom is raw. The numbers may look skewed, but they aren't - the scales aren't all the same. Graphs are, in order, x:y, y:z, x:z

What could this be?

• Are you sure you've correctly pulled the values from the quaternion? Also, can you draw a diagram of how you're applying the tilt angle to the compass?
– Ian
Jul 23, 2014 at 3:34
• Have you calibrated the compass by rotating it through all 3 axes several times? Oct 1, 2015 at 19:55

## 1 Answer

You may want to take a look at FreeIMU library that does 'data fusion' that combine raw data from multiple sensors and present user with a much reliable, stable and easy-to-use data in a roll, pitch and yaw (direction as you require) format.

FreeIMU http://www.varesano.net/projects/hardware/FreeIMU This version from the original author use MPU60X0 chip. It also has hard and soft iron offsets calibration. You may want to use this version by changing chip which is relatively low cost. Or, use below newer version by community authors uses the newer MPU9150.

(about 60% toward the end) Video showing roll, pitch and yaw as displayed on pc screen https://www.youtube.com/watch?v=4Dmbr4XDnSM

There are dozens of similar videos. like https://www.youtube.com/watch?v=jSUULyOchKY which explain a bit about the working principle, etc.

http://www.youtube.com/watch?v=kujLFiehwC4

You may want to consider using Arduino MCU board as it is low cost and has plenty examples. The library is in C and in-theory can be ported to other MCU.

Hope it helps