This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

MPU9250 TWI Data Retrieve Crashing

Hi

I'm have and NRF52840 with a MPU9250 connected via TWI. The connection to the MPU9250 is successful, I can find its address on the bus (0x68).

I've implemented a very simple couple of uint32_t structs to based upon other examples available:

Read from a TWI register:

uint32_t nrf_drv_mpu_read_registers(uint8_t reg, uint8_t * p_data, uint32_t length)
{
    uint32_t err_code;
    uint32_t timeout = MPU_TWI_TIMEOUT;

    err_code = nrf_drv_twi_tx(&m_twi, MPU9250_TWI_ADDR, &reg, 1, false);
    if(err_code != NRF_SUCCESS) return err_code;

    while((!twi_tx_done) && --timeout);
    if(!timeout) return NRF_ERROR_TIMEOUT;
    twi_tx_done = false;

    err_code = nrf_drv_twi_rx(&m_twi, MPU9250_TWI_ADDR, p_data, length);
    if(err_code != NRF_SUCCESS) return err_code;

    timeout = MPU_TWI_TIMEOUT;
    while((!twi_rx_done) && --timeout);
    if(!timeout) return NRF_ERROR_TIMEOUT;
    twi_rx_done = false;

    return err_code;
}
 

and read accelerometers values:

uint32_t app_mpu_read_accel(accel_values_t * accel_values)
{
    uint32_t err_code;
    uint8_t raw_values[6];
    err_code = nrf_drv_mpu_read_registers(MPU_REG_ACCEL_XOUT_H, raw_values, 6);
    if(err_code != NRF_SUCCESS) return err_code;

    // Reorganize read sensor values and put them into value struct
    uint8_t *data;
    data = (uint8_t*)accel_values;
    for(uint8_t i = 0; i<6; i++)
    {
        *data = raw_values[5-i];
        data++;
    }
    return NRF_SUCCESS;
}

I have the following definitions for the MPU:

#define MPU9250_TWI_ADDR 0x68

#define MPU_REG_ACCEL_XOUT_H       0x3B // ACCEL_XOUT[15:8]
#define MPU_REG_ACCEL_XOUT_L       0x3C // ACCEL_XOUT[7:0]
#define MPU_REG_ACCEL_YOUT_H       0x3D // ACCEL_YOUT[15:8]
#define MPU_REG_ACCEL_YOUT_L       0x3E // ACCEL_YOUT[7:0]
#define MPU_REG_ACCEL_ZOUT_H       0x3F // ACCEL_ZOUT[15:8]
#define MPU_REG_ACCEL_ZOUT_L       0x40 // ACCEL_ZOUT[7:0]

/**@brief Structure to hold acceleromter values. 
 * Sequence of z, y, and x is important to correspond with 
 * the sequence of which z, y, and x data are read from the sensor.
 * All values are unsigned 16 bit integers
*/
typedef struct
{
    int16_t z;
    int16_t y;
    int16_t x;
}accel_values_t;

I'm running a call once and writing to NRF_LOG to test within the main loop, as follows:

    // Read accelerometer sensor values
    uint32_t err_code;
    accel_values_t acc_values;
    err_code = app_mpu_read_accel(&acc_values);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_INFO("Accel %d\r\nX: %06d\r\nY: %06d\r\nZ: %06d", acc_values.x, acc_values.y, acc_values.z);
    NRF_LOG_FLUSH();

My NRF_LOG Output is:

<info> app: TWI started.

<info> app: TWI Scanner Started.

<info> app: SparkFun MPU-9250 detected at 0x68

<info> app: TWI Scanner Finished.

<info> app: MPU Sensor Connected

<error> app: Fatal error

<warning> app: System reset

Is anyone able to advise. Thanks in advance.

Parents Reply Children
  • Sorry. Are you using Makefiles from the SDK to compile? In that case, add this line "CFLAGS += -DDEBUG" together with the other C flags.

  • Great, set that an now I get a much better view of the issue (but still don't understand):

    New -DDEBUG Output:

    <info> app: Read accelerometer sensor values
    
    <error> app: ERROR 13 [NRF_ERROR_TIMEOUT] at ../../../main.c:741
    
    PC at: 0x0002B413

    In my code line 741 is line 31 in the code snippet below:

    int main(void)
    {
        // Initialize.
        log_init();
        leds_init();
        timers_init();
        buttons_init();
        power_management_init();
        twi_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
    
        // Start execution.
        twiScanning();
        advertising_start();
    
        NRF_LOG_INFO("StingRay Started.");
    
        NRF_LOG_FLUSH();
    
        if (MPU9250) {
            // Read accelerometer sensor values
            NRF_LOG_INFO("Read accelerometer sensor values");
            uint32_t err_code;
            accel_values_t acc_values;
            err_code = app_mpu_read_accel(&acc_values);
            APP_ERROR_CHECK(err_code);
            NRF_LOG_INFO("Accel %d\r\nX: %06d\r\nY: %06d\r\nZ: %06d", acc_values.x, acc_values.y, acc_values.z);
            NRF_LOG_FLUSH();
        }
    
        // Enter main loop.
        for (;;)
        {
            idle_state_handle();
        }
    }

  • Thanks, so it looks like you are getting the NRF_ERROR_TIMEOUT from nrf_drv_mpu_read_registers(). Maybe you can add some more logging in your TWI callback and see if you get the NRF_DRV_TWI_EVT_ADDRESS_NACK or NRF_DRV_TWI_EVT_DATA_NACK event instead of the expected NRF_DRV_TWI_EVT_DONE. 

  • Hi Vidar

    You are correct, I had ported a library which was using other legacy library's which was causing the issue. It has been a big learning curve, thanks for your excellent support.

Related