cancel
Showing results for 
Search instead for 
Did you mean: 

LSM303AGR Magnetometer Self-Test Fails on Z-Axis

Gohil
Associate

I'm using the LSM303AGR magnetometer with an STM32L4 via I2C + HAL. The built-in self-test works fine for X and Y, but Z-axis always fails — the delta (self-test vs. normal) is out of range.

   Set Up

  • STM32L4, I2C, HAL drivers

  • Magnetometer config: 50 Hz, continuous mode

  • Self-test enabled via CFG_REG_C_M (0x62) = 0x12

  • 50 samples averaged before/after self-test

  • Delays: 200ms (pre), 500ms (post self-test)

     Problem

  • X/Y deltas: within 100–1000 LSB range → pass

  • Z delta: often too low or too high → fail

    Question

  1. Are 100–1000 LSB valid self-test limits for Z?

  2. Is 500ms delay enough after enabling self-test?

  3. Do I need to read output registers in burst mode for sync?

  4. Any known Z-axis issues in continuous mode?

Any advice or working examples appreciated!

2 REPLIES 2
TDK
Guru

The self test procedure is outlined in AN4825. Follow that exactly and show the numerical results you get along with relevant code.

TDK_0-1747220932571.png

Ultra-compact high-performance eCompass module based on the LSM303AGR

 

If you feel a post has answered your question, please click "Accept as Solution".
Gohil
Associate

Hello ST Community,

I shared complete example of the LSM303AGR magnetometer self-test, based on AN4825. This was tested on an STM32 platform using HAL over I2C. Below is the implementation and test results.


void
LSM303AGR_Mag_selfTest(void)

{

uint8_t addr = LSM303_MAG_ADR, status;

int16_t x_nost = 0, y_nost = 0, z_nost = 0;

int16_t x_st = 0, y_st = 0, z_st = 0;

int i;

 

lsm303AGR_Write8b_res(addr, 0x60, 0x8C); // ODR = 100Hz, LP = 0, continuous mode, soft reset enabled

lsm303AGR_Write8b_res(addr, 0x61, 0x02); // Configures magnetometer for continuous mode

lsm303AGR_Write8b_res(addr, 0x62, 0x10); // Enable Block Data Update (BDU = 1)

 

HAL_Delay(200); // Wait for stabilization

 

// Collect baseline data (no self-test)

for (i = 0; i < 50; i++)

{

do {

status = lsm303AGR_Read8b_res(addr, 0x67);

HAL_Delay(5);

} while (!(status & 0x08)); // Wait for new ZYX data

x_nost += lsm303AGR_Read16b_res(addr, 0x68);

y_nost += lsm303AGR_Read16b_res(addr, 0x6A);

z_nost += lsm303AGR_Read16b_res(addr, 0x6C);

HAL_Delay(20);

}

x_nost /= 50;

y_nost /= 50;

z_nost /= 50;

 

// Enable self-test mode

lsm303AGR_Write8b_res(addr, 0x62, 0x12); // BDU = 1, Self-test = 1

 

HAL_Delay(500); // Wait for stabilization

 

uint8_t reg_val = lsm303AGR_Read8b_res(addr, 0x62);

if (reg_val & 0x02) {

printf("Self-test is ENABLED CTRL_REG4_A = 0x%02X\r\n", reg_val);

} else {

printf("Self-test is NOT enabled CTRL_REG4_A = 0x%02X\r\n", reg_val);

}

 

// Collect self-test data

for (i = 0; i < 50; i++)

{

do {

status = lsm303AGR_Read8b_res(addr, 0x67);

HAL_Delay(5);

} while (!(status & 0x08)); // Wait for new ZYX data

x_st += lsm303AGR_Read16b_res(addr, 0x68);

y_st += lsm303AGR_Read16b_res(addr, 0x6A);

z_st += lsm303AGR_Read16b_res(addr, 0x6C);

HAL_Delay(20);

}

x_st /= 50;

y_st /= 50;

z_st /= 50;

 

// Calculate deltas

int16_t deltaX = abs(x_st - x_nost);

int16_t deltaY = abs(y_st - y_nost);

int16_t deltaZ = abs(z_st - z_nost);

 

// Check against datasheet min/max (example range in LSB)

const int16_t ST_MIN = 100;

const int16_t ST_MAX = 1000;

 

// Check for pass/fail

bool x_pass = (deltaX >= ST_MIN && deltaX <= ST_MAX);

bool y_pass = (deltaY >= ST_MIN && deltaY <= ST_MAX);

bool z_pass = (deltaZ >= ST_MIN && deltaZ <= ST_MAX);

 

if (x_pass && y_pass && z_pass) {

printf(" LSM303AGR Magnetometer Self-Test PASSED\r\n");

} else {

printf(" LSM303AGR Magnetometer Self-Test FAILED\r\n");

}

 

// Disable self-test

lsm303AGR_Write8b_res(addr, 0x62, 0x10);

lsm303AGR_Write8b_res(addr, 0x60, 0x83);

}
Output:

Self-test ENABLED: CTRL_REG3_M = 0x12

Self-Test Results:
X: nost = -106, st = 35, Δ = 141 [PASS]
Y: nost = -186, st = -61, Δ = 122 [PASS]
Z: nost = 356, st = 412, Δ = 58 [FAIL]

LSM303AGR Magnetometer Self-Test FAILED
Thanks