cancel
Showing results for 
Search instead for 
Did you mean: 

LSM303AGR Tilt-Compensated Compass

Gohil
Visitor

 

Hello STM32 Community,

I'm working with the LSM303AGR magnetometer/accelerometer sensor on an STM32L4 microcontroller. I'm trying to compute a tilt-compensated heading, based on the method described in ST's application note DT0058.

However, I'm running into a problem: the heading value changes significantly when the sensor is tilted, even when the actual orientation toward magnetic north doesn't change. I expect the heading to stay consistent regardless of tilt, thanks to tilt compensation — but this is not happening.

Below is the code I'm currently using to compute the heading:

 

 

uint8_t lsm303agr_heading_read(float* heading) {
float magx_out, magy_out, magz_out;
float accx_out, accy_out, accz_out;

// Read sensor data
if (lsm303agr_acc_data_read(&accx_out, &accy_out, &accz_out, 10) != 0)
return 1;
if (lsm303agr_m_data_read(&magx_out, &magy_out, &magz_out, 10) != 0)
return 1;

// Normalize accelerometer readings
float acc_norm = sqrt(accx_out * accx_out + accy_out * accy_out + accz_out * accz_out);
if (acc_norm == 0) return 1;
accx_out /= acc_norm;
accy_out /= acc_norm;
accz_out /= acc_norm;

// Normalize magnetometer readings
float mag_norm = sqrt(magx_out * magx_out + magy_out * magy_out + magz_out * magz_out);
if (mag_norm == 0) return 1;
magx_out /= mag_norm;
magy_out /= mag_norm;
magz_out /= mag_norm;

// Compute roll and pitch
double roll = atan2(accy_out, accz_out);
double acc_z2 = accy_out * sin(roll) + accz_out * cos(roll);
double theta = atan(-accx_out / acc_z2);

// Tilt-compensated magnetometer
double mag_y2 = magz_out * sin(roll) - magy_out * cos(roll);
double mag_z2 = magy_out * sin(roll) + magz_out * cos(roll);
double mag_x3 = magx_out * cos(theta) + mag_z2 * sin(theta);

// Compute heading
double heading_rad = atan2(mag_y2, mag_x3);
double heading_deg = heading_rad * (180.0 / 3.14159);

if (heading_deg < 0)
heading_deg += 360.0;

*heading = (float)heading_deg;
return 0;
}

Problem:

  • The heading value is correct when the sensor is flat (horizontal).

  • When the sensor is tilted (e.g., rotated along X or Y), the heading becomes inaccurate.

  • I am following the tilt-compensation steps from ST’s DT0058, but they don’t seem to work as expected.

My Questions:

  1. Is there any mistake in my tilt-compensation math?

  2. Is DT0058 accurate for the LSM303AGR, or are there better alternatives?

  3. Do I need to apply any additional corrections (like hard-iron or soft-iron calibration)?

  4. Can anyone please provide a working example code that gives consistent heading regardless of tilt?

Any help or guidance would be highly appreciated.

Thank you!

0 REPLIES 0