Thursday 13 February 2020

Custom Flight Controller Part 2.2.2: Get Data from MPU9250 Using STM32

This post documents how to get data from MPU9250 using STM32. The detailed code can be found in my Github


In this project, I2C is selected to be the communication protocol to communicate with MPU9250. Therefore, reading sensor measurement data is done by calling I2C related APIs exposed by STM32 HAL library.

For example, the following functions reads the most recent accelerometer measurement data. 

void MPU9250::getAcceleration(int16_t* x, int16_t* y, int16_t* z) {
    uint16_t dataSizeToRead = 6;
    if (!I2C_Read(devAddr, MPU9250_RA_ACCEL_XOUT_H, I2C_MEMADD_SIZE_8BIT, buffer, dataSizeToRead)) {
        return;
    }
    //I2Cdev::readBytes(devAddr, MPU9250_RA_ACCEL_XOUT_H, 6, buffer);
    *x = (((int16_t)buffer[0]) << 8) | buffer[1];
    *y = (((int16_t)buffer[2]) << 8) | buffer[3];
    *z = (((int16_t)buffer[4]) << 8) | buffer[5];
}
MPU9250_RA_ACCEL_XOUT_H is a macro definition of value 0x3B, the address of MPU9250's register which stores the most recent accelerometer measurement.

The devAddr variable has the value of 0xD0. At first sight, this contradicts to I2C slave address of MPU9250 which is 0x68 as indicated in datasheet. However, STM32 HAL library requires the device address parameter to include the read/write bit as well. Therefore, the correct device address is 0x68 shifted to left by 1 bit, which is 0xD0.

MPU9250 can be configured to output data in different mode and frequencies to suit different purposes. In my project, I configured MPU9250 in the following settings.

void MPU9250::Init()
{
    //set clock source
    setClockSource(MPU9250_CLOCK_PLL_XGYRO);
    //set gyro output data rate to 1000hz. Low pass filter bandwidth 184Hz
    setGyroDLPFMode(1);
    //set gyro range to 2000dps.
    setFullScaleGyroRange(MPU9250_GYRO_FS_2000);
    //set accel output data rate to 1000hz. Low pass filter bandwidth 21.2Hz
    setAccDLPFMode(4);
    //set accel range to 2g
    setFullScaleAccelRange(MPU9250_ACCEL_FS_2);
    //setSleepEnabled(false); // thanks to Jack Elston for pointing this one out!
    //set i2c bypass enable pin to true to access magnetometer and configure interrupt
    setBypassEnable(MPU9250_BYPASS_ENABLE);
    // get mag sensitivity adjust data
    GetMagSensitivityAdjData(mMagSensAdjData);
    // set mag to 16 bit
    setMagMeasOutputBit(MPU9250_MAG_16BIT_OUTPUT);
    //set mag to continuous measurement mode
    setMagContMeasMode(MPU9250_MAG_CONTINUOUS_MODE_200HZ);
}
Digital low pass filter of accelerometer is set to have a low bandwidth to reduce noise in its measurements.

No comments:

Post a Comment