Skip to content

IMU (Accel/Gyro) sampling rate stays at ~25Hz even after setting BMI160 ODR to 100Hz and disabling FIFO downsampling #353

Description

@AnusoenSaman

Hardware: EmotiBit MD (HW V05c) + Adafruit Feather HUZZAH32 (ESP32)
Firmware version: 1.14.3 (EmotiBit_stock_firmware, built from source via PlatformIO)

Goal: Increase the accelerometer/gyroscope sampling rate from the stock 25Hz to 100Hz.

Changes made so far (in EmotiBit.cpp, IMU setup block):

// Accelerometer
BMI160.setAccelRate(BMI160AccelRate::BMI160_ACCEL_RATE_100HZ);
imuSettings.acc_odr = BMI160AccelRate::BMI160_ACCEL_RATE_100HZ;

// Gyroscope
BMI160.setGyroRate(BMI160GyroRate::BMI160_GYRO_RATE_100HZ);
imuSettings.gyr_odr = BMI160GyroRate::BMI160_GYRO_RATE_100HZ;

// Recompute _samplingRates so info.json metadata reflects the new rate
_samplingRates.accelerometer = 25.f * pow(2.f, ((float)imuSettings.acc_odr - 6.f));
_samplingRates.gyroscope = 25.f * pow(2.f, ((float)imuSettings.gyr_odr - 6.f));

// Attempted fix: disable BMI160 FIFO_DOWNS register (0x45) which independently
// downsamples data going into the FIFO relative to ODR
BMI160.setRegister(0x45, 0x88);

Also changed IMU_SAMPLING_DIV from 2 to 1 in EmotiBit.h (readSensors() polling divider).

Verification steps taken:

  1. Confirmed via BMI160.getAccelRate() printed over Serial that the chip register genuinely reads back 8 (=100Hz) after setup — so the ODR write is succeeding at the register level.
  2. Confirmed updateIMUData() (which drains the BMI160 FIFO) is being called ~150 times/sec by the acquisition timer (verified with a Serial counter), so the polling loop itself is not the bottleneck.
  3. Added a counter directly around pushData(DataType::ACCELEROMETER_X, ...) inside updateIMUData(). This consistently prints ~25 calls/sec, regardless of the above changes.
  4. Confirmed via raw SD card CSV (summing the NUM_DATAPOINTS field per AX packet over a 5-6 second window) that the real, end-to-end recorded accelerometer rate is consistently ~25-26Hz, both before and after all the above changes.
  5. _info.json does correctly report nominal_srate: 100 after the fix (since we recompute _samplingRates from imuSettings), but this is just metadata — the actual data rate written to the CSV is unchanged at ~25Hz.

Question: Since the BMI160 ODR register is confirmed correct (100Hz) and the FIFO downsampling register is disabled, what else in the firmware/hardware pipeline could be limiting the actual number of IMU samples pulled from the FIFO to ~25/sec? Is there a known architectural reason the IMU has stayed at 25Hz even in the official 100Hz PPG variant (as referenced in the EmotiBit validation paper)? Any pointers to where else in the codebase (or BMI160 datasheet) I should look would be much appreciated.

Happy to share the full diff if useful.

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