Hi all,
I'm facing a challenge with efficiently transmitting high-frequency sensor data over BLE.
I’m sampling sensor data via SPI from a sensor capable of outputting data at up to 1 kHz. My goal is to transmit this sampled data with low latency and as close to real-time as possible. However, I’m aware of the BLE limitations, particularly the 7.5 ms minimum connection interval, which, in practice, often turns out to be 11.25 ms on Android and 15 ms on iOS.
Given these constraints, it's clear that I can't send individual sensor values in real-time. Therefore, my current approach is to package multiple values into each notification. This introduces a slight delay, but it’s an acceptable trade-off.
To achieve stable notifications, I plan to use the BLE radio callback function, allowing me to queue one packet per connection interval as the callback is called right before the conn event. This setup creates a classic producer-consumer problem:
- Producer: The sensor, sampling data at 1 kHz.
- Consumer: The BLE radio callback, transmitting data at the connection interval.
Assuming a constant 15 ms connection interval (to accommodate iOS), I need to send 15 sensor values per notification. However, I’m struggling with how best to handle the mismatch between the producer and consumer rates. Specifically:
- Buffer Overflow: If the producer outpaces the consumer, the buffer fills up, increasing latency.
- Buffer Underflow: If the consumer outpaces the producer, some connection events will have no data to send, disrupting the desired transmission pattern.
Key Question:
How can I better synchronize the producer and consumer? What would be the best data structure and data-handling strategy to achieve stable, consistent data transfer in this scenario?
In theory i dont care if gathered sensor data gets lost if i just can always send out the latest 15 values. Could this maybe be handled by some sort of LIFO Ring buffer? But this would create the issue of not mixing stale data with new data.
Any insights or suggestions about to how best go about this issue would be greatly appreciated.
Maybe I'm also going completely wrong about the solution
Here is some of the relevant code:
Producer:
static void amr_work_handler(struct k_work *work) { // Some spi stuff to read out 4 sensors simulationsly amr_xfer_all(xfer_desc_all_bandwidth); amr_xfer_all(xfers_all); amr_xfer_all(init_m); amr_xfer_all(read_status_xfer); if (((r_status1[1] & 0x01) & (r_status2[1] & 0x01) & (r_status3[1] & 0x01) & (r_status4[1] & 0x01))) { set_spi1_error(true); set_spi2_error(true); } k_work_reschedule(&amr_work, K_MSEC(1000/current_MODR)); }
Consumer:
static void radio_notification_conn_prepare_cb(struct bt_conn *conn) { // ble callback // send the gathered sensor data out here by calling bt_gatt_notify(data) }
Im on ncs 2.9.0
Thanks in advance!