Skip to content

IMU ODR setup discrepancy #354

Description

@sanrav2016

Describe the bug
The IMU ODR is 25 Hz as documented, but the setup achieved to reach this ODR is incorrect.

When calling this function in EmotiBit.cpp setup:

BMI160.setGyroRate(BMI160GyroRate::BMI160_GYRO_RATE_100HZ);

There is a problem because the function name setGyroRate is duplicated across two classes in the EmotiBit_BMI160 library.

BMI160.cpp

/** Set gyroscope output data rate.
 * @param rate New output data rate
 * @see getGyroRate()
 * @see BMI160_GYRO_RATE_25HZ
 * @see BMI160_RA_GYRO_CONF
 */
void BMI160Class::setGyroRate(uint8_t rate) {
    reg_write_bits(BMI160_RA_GYRO_CONF, rate,
                   BMI160_GYRO_RATE_SEL_BIT,
                   BMI160_GYRO_RATE_SEL_LEN);
}

CurieIMU.cpp

void CurieIMUClass::setGyroRate(int rate)
{
    BMI160GyroRate bmiRate;

    if (rate <= 25) {
        bmiRate = BMI160_GYRO_RATE_25HZ;
    } else if (rate <= 50) {
        bmiRate = BMI160_GYRO_RATE_50HZ;
    } else if (rate <= 100) {
        bmiRate = BMI160_GYRO_RATE_100HZ;
    } else if (rate <= 200) {
        bmiRate = BMI160_GYRO_RATE_200HZ;
    } else if (rate <= 400) {
        bmiRate = BMI160_GYRO_RATE_400HZ;
    } else if (rate <= 800) {
        bmiRate = BMI160_GYRO_RATE_800HZ;
    } else if (rate <= 1600) {
        bmiRate = BMI160_GYRO_RATE_1600HZ;
    } else {
        bmiRate = BMI160_GYRO_RATE_3200HZ;
    }

    BMI160Class::setGyroRate(bmiRate);
}

CurieIMUClass inherits from BMI160Class and redefines setGyroRate. This redefined function expects its parameter to be the ODR in Hz, not an enum. But the decimal value for BMI160_GYRO_RATE_100HZ is 8, defined here. So the setup call is setting the ODR to 25 Hz even when passing the 100 Hz enum. In fact, a 100 Hz enum is used for the accelerometer and magnetometer setup as well.

BMI160.setAccelRate(BMI160AccelRate::BMI160_ACCEL_RATE_100HZ);

BMI160.setMagRate(BMI160MagRate::BMI160_MAG_RATE_100HZ);

However, the ODR remains at 25 Hz on this channels (and there are no problems with accel/mag setup function redefinitions). Why don't these run at 100 Hz? The reason is that the IMU is set to headerless mode and the FIFO is enabled for all channels.

// Setup the FIFO
BMI160.setAccelFIFOEnabled(true);
_imuFifoFrameLen += 6;
BMI160.setGyroFIFOEnabled(true);
_imuFifoFrameLen += 6;
BMI160.setMagFIFOEnabled(true);
_imuFifoFrameLen += 8;
BMI160.setFIFOHeaderModeEnabled(false);

In this specific configuration, all IMU channels need to have the same ODR (page 24 of the BMI160 datasheet):

In headerless mode no header byte is used and the frames consist only of data bytes. The data bytes will always be sensor data. Only regular frames with the same ODR for all sensors are supported and no external interrupt flags are possible.

Because the gyro was being set to 25 Hz behind the scenes, it limited the frame output to that rate even though the accel and mag were set at 100 Hz.

Expected behavior
Looking at the setup functions, the IMU ODR should be 100 Hz as 100 Hz enums are being used. The code should be changed to use 25 Hz enums while preserving the 25 Hz ODR. This makes changing the ODR more straightforward if users wish to do so.

Additional details

  • EmotiBit firmware version: observed on v1.14.3, but stems from this PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions