cancel
Showing results for 
Search instead for 
Did you mean: 

LSM303AGR Magnetometer Self-Test Fails – Help Diagnosing with STM32

Gohil
Associate

Hi everyone,

I'm working with the LSM303AGR magnetometer using an STM32 microcontroller and trying to run the built-in self-test as described in the datasheet. However, the self-test consistently fails — the delta values (normal vs self-test mode) fall outside the expected range.


Goal

Perform a successful magnetometer self-test and confirm the output is within the required limits (according to the datasheet).


Summary of the Issue

  • Self-test bit is enabled in CFG_REG_C_M (0x62) → value reads back as 0x12.

  • Data output seems valid and updates regularly.

  • Delta between self-test and normal readings is either too small or too large, so the test fails.

    Self-Test Code (Full Function)

    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;

     

    // Configure magnetometer: 50 Hz, continuous mode

    lsm303AGR_Write8b_res(addr, 0x60, 0x8C); // Temp disable, low power, ODR = 100 Hz, continuous mode

    lsm303AGR_Write8b_res(addr, 0x61, 0x02);

    lsm303AGR_Write8b_res(addr, 0x62, 0x10); // 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);

    }

    Questions for the Community

    1. Are the ST_MIN/ST_MAX values accurate?
      The datasheet (Rev 2, Table 15) gives these thresholds but doesn’t specify units clearly. Should these be adjusted for specific gain settings?

    2. Is the delay after enabling self-test (500 ms) sufficient, or is more time needed before sampling?

    3. Do I need to read all six output registers in a burst (multibyte read) to ensure synchronized axis data?

    4. Any known issues with self-test on LSM303AGR in continuous mode?


    Datasheet Link (Magnetometer Section):

    LSM303AGR Datasheet (STMicroelectronics)


    System Details

    • MCU: STM32F4 series (STM32Cube HAL)

    • Sensor: LSM303AGR via I2C

    • IDE: STM32CubeIDE

    • OS: Bare-metal (no RTOS)

    Thanks in advance for any insights, corrections, or working reference code.
    Best regards,

    Raj

     

     

0 REPLIES 0