I am having troubles with tilt compensating my compass.

I am using the LSM303DLHC accelerometer/compass in combination together with the Adafruit_LSM303_U.h.

I was able to get my compass to the right direction withthis little snippet:

``````  float heading = (atan2(event.magnetic.y,event.magnetic.x) * 180) / Pi;
``````

I also was able to get my roll and tilt angle with converting my X and Y of my accelerometer to angles:

``````   headingNew = asin(eventA.acceleration.x/10);
``````

Now I need to compensate my angle to get a new x and y for inside my heading calculation but the problem is that I can't seem to get the right functions. Online I found the functions below from a large tutorial about the sensor but this gives me completely wrong values.

``````    //Xh = event.magnetic.x*cos(tilt)+event.magnetic.z*sin(tilt);
//Yh = event.magnetic.x*sin(roll)*sin(tilt)+event.magnetic.y*cos(roll)-event.magnetic.z*sin(roll)*cos(tilt);
``````

or in the code itself:

``````   Xh = event.magnetic.x*(eventA.acceleration.z/10)+event.magnetic.z*(eventA.acceleration.x/10);
Yh = event.magnetic.x*(eventA.acceleration.y/10)*(eventA.acceleration.x/10)+event.magnetic.y*(eventA.acceleration.z/10)-event.magnetic.z*(eventA.acceleration.y/10)*(eventA.acceleration.z/10);
``````

I actually get the right angle on a flat surface. But it is even more inaccurate at an angle as the normal heading. Does anybody have any experience with this sensor? Already a big thanks for the help.

The `sin()` and `cos()` functions expect their arguments to be in radians. If you feed them with anything else, be it degrees, percent slope, or whatever, expect the result to be just crap.

Edit: The OP changed the question, invalidating my answer. So here comes a new answer...

You have mistaken `eventA.acceleration.y` for `cos(tilt)`, `eventA.acceleration.x` for `sin(tilt)`, and so on. They are not the same. You may think they are the same up to some multiplicative factor, and that's right. However, the factor doesn't cancel out as soon as you do computations like `sin(roll)*sin(tilt)`. Don't rush your math: if you want to transform known-good formulas to more practical ones, check every step of the transformation carefully.

• Actually for the sinus of the tilt I use my Accelerometer.x, for the cosinus of tilt the accelerometer.y. Also for the sin of the roll I use the accelerometer.Y. These are values from 0 to 1 that are the same as the cos/sin of a unit circle – Roel Nov 21 '19 at 9:24
• @Roel: Re “for the cosinus of tilt [I use] the accelerometer.y”: I can't see that in the code you posted. If you are asking a question about a different piece of code, then please edit the question and make sure the code you show is the one that matches your question. – Edgar Bonet Nov 21 '19 at 9:39
• I edited the question to show you how the code really looks like in my project. – Roel Nov 21 '19 at 9:52
• I just want to know what Is wrong with the final function because I am not able to get the right result. – Roel Nov 21 '19 at 10:11
• @Roel: What's wrong: it uses `eventA.acceleration.y` instead of `cos(tilt)`, etc. Solution: use the formula as published, with the angles in radians. – Edgar Bonet Nov 21 '19 at 10:32

Via this Youtube movie I found a different library and made this code:

``````#include <SPI.h>
#include <Wire.h>
#include <LSM303.h>
const int centreX  = 160;
const int centreY  = 120;
const int diameter = 100;
#define STMPE_CS 8
#define TFT_CS 10
#define TFT_DC 9

int last_dx, last_dy, dx, dy;
LSM303 compass;
void setup(){
Serial.begin(9600);
Serial.println("meters Test"); Serial.println("");
Wire.begin();
compass.init();
compass.enableDefault();

compass.m_min = (LSM303::vector<int16_t>){-602, -704, -511}; //values from
cailbration.
compass.m_max = (LSM303::vector<int16_t>){+557, +436, +529}; //values from
cailbration.
last_dx = centreX;
last_dy = centreY;
}
void loop() {
double angle;