Skip to content

feat(sensors): modernize sensor drivers and streaming#212

Draft
DennisMoschina wants to merge 1 commit into
OpenEarable:mainfrom
DennisMoschina:codex/thandal-sensor-stack
Draft

feat(sensors): modernize sensor drivers and streaming#212
DennisMoschina wants to merge 1 commit into
OpenEarable:mainfrom
DennisMoschina:codex/thandal-sensor-stack

Conversation

@DennisMoschina

@DennisMoschina DennisMoschina commented May 18, 2026

Copy link
Copy Markdown
Collaborator

Draft PR extracted from thandal/open-earable-2 (see #183). Modernizes the sensor stack with Bosch BMI160 support, sensor sink plumbing, diagnostics, metadata cleanup, and polling/performance fixes.

@DennisMoschina DennisMoschina linked an issue May 18, 2026 that may be closed by this pull request
@habibialireza

Copy link
Copy Markdown
Collaborator

This PR is a sensor pipeline modernization. The main idea is to remove the old central zbus-based sensor data path and make sensors write directly to SD/BLE through a new layer (named: sensor_sink). It also updates several sensor drivers to use FIFO batching, improves power/shutdown behavior, removes some old/unused code, and adds a Zephyr shell interface for sensor testing.

Main change:
The old data path was:

Sensor -> sensor_queue -> SensorManager publisher thread -> sensor_chan -> SDLogger / Bluetooth

The new intended path is:

Sensor -> sensor_sink_put() -> SDLogger and/or Bluetooth GATT queue

This simplifies the path and removes the SensorManager publisher thread. SensorManager is now mostly responsible for starting/stopping sensors and managing SD/BLE config state, not forwarding every sensor sample.

However, there is a possible incomplete migration: SDLogger.cpp still declares/observes sensor_chan, but the PR removes the SensorManager definition of sensor_chan. This should be checked because it can cause build issues.

SensorManager:
SensorManager no longer owns sensor_queue or publishes sensor messages to zbus. It now processes all pending config messages in one work handler run, starts SDLogger before starting sensors, and calls sensor->init() (used to be sensor->init(&sensor_queue).

One possible issue: start_sensor_manager() clears sd_sensors and ble_sensors. Since SD sensor tracking is updated before start_sensor_manager() is called, the first SD sensor may get removed from tracking immediately.

sensor_service / BLE:
The BLE sensor service is no longer subscribes to sensor_chan for sensor data. Instead, sensor_sink pushes data into the BLE GATT queue.

A risk here is that the new notification logic appears to reuse shared/static sensor_data memory with a semaphore, instead of giving every BLE notification its own independent payload copy. This should be checked for possible overwrite/race problems when multiple notifications are sent.

sensor_sink:
A new sensor_sink API acts as the common output layer for sensor messages.

Several sensors ignore the return value from sensor_sink_put(), so SD/BLE failures may silently drop samples or only appear in debug counters.

Driver / sampling changes:
BMA580 / Bone Conduction:
The BMA580 path now disables some feature-engine behavior and uses the larger 1024-byte FIFO. The code no longer relies on the FIFO watermark interrupt/INT1 path. it uses scheduled polling and reads batches when enough samples should be ready. BoneConduction now powers the sensor more carefully, reads less frequently in batches, and logs performance/error stats.

BMX160 / IMU:
The old DFRobot BMX160 driver is replaced with a Bosch BMI160-based driver plus an OpenEarable wrapper. The IMU now reads batches from the chip FIFO instead of reading one live sample per timer tick. It still emits one old-format IMU message per sample and estimates timestamps for each sample in the batch. It also configures both accel and gyro ODRs, whereas the old code mainly changed accel ODR. Magnetometer is disabled by default.

BMP388 / Barometer:
The BMP388 driver now puts the sensor into continuous/normal measuring mode and reads the latest available values instead of reconfiguring/triggering a one-shot reading every time. Baro now uses sensor_sink, adds read-failure checks, cancels pending work on stop, logs timing stats, and puts the BMP388 to sleep before power-down. One thing to verify: the BMP388 driver appears to set ODR to 25 Hz in init, while Baro exposes many rates.

MAXM86161 / PPG:
Unused MAXM86161 methods were removed. There are also small correctness fixes, including interrupt-status read ordering and a register constant fix. PPG now uses sensor_sink, polls at batch intervals instead of every sample interval, logs timing/drop stats, and explicitly disables the external PPG LDO GPIO on stop. This should improve power behavior. The default PPG frequency also changed from index 1 to index 2, from 50 Hz to 84 Hz.

MLX90632 / Temperature:
The MLX90632 calculations were changed from double-heavy math to float/faster math, which is better for the Cortex-M FPU. EEPROM busy-wait loops were bounded. Temp now uses sensor_sink, polls at 2x the selected sensor rate to avoid missing data-ready windows, cancels pending work on stop, logs timing stats, and puts the sensor into sleep mode before powering down.

Microphone:
The microphone path was simplified to only expose 48 kHz recording. The old decimator/downsampling path was removed, so lower microphone sample rates are no longer supported. There may be a typo/incomplete rename.

sensor_shell:
A new Zephyr shell command was added for developer testing. It allows starting/stopping sensors, printing sensor info, running stress tests, and running nominal-rate tests without using the phone app/BLE UI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FYI: Fork with major improvements

2 participants