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:
- 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.
- 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.
- Added a counter directly around
pushData(DataType::ACCELEROMETER_X, ...) inside updateIMUData(). This consistently prints ~25 calls/sec, regardless of the above changes.
- 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.
_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.
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):
Also changed
IMU_SAMPLING_DIVfrom 2 to 1 in EmotiBit.h (readSensors() polling divider).Verification steps taken:
BMI160.getAccelRate()printed over Serial that the chip register genuinely reads back8(=100Hz) after setup — so the ODR write is succeeding at the register level.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.pushData(DataType::ACCELEROMETER_X, ...)insideupdateIMUData(). This consistently prints ~25 calls/sec, regardless of the above changes._info.jsondoes correctly reportnominal_srate: 100after the fix (since we recompute_samplingRatesfromimuSettings), 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.