Skip to main content
Visitor II
May 14, 2025
Question

LSM303AGR Magnetometer Self-Test Fails on Z-Axis

  • May 14, 2025
  • 2 replies
  • 372 views

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!

    This topic has been closed for replies.

    2 replies

    Super User
    May 14, 2025

    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

     

    GohilAuthor
    Visitor II
    May 14, 2025

    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