Unreliable BLE connection for continuos high bandwidth data stream

I want to send a continuos stream of sensor data over BLE, currently using the NUS GATT profile, connecting directly to a third-party device e.g. computer or phone.

The bandwidth required is about ~256kbit/s so in theory more than enough bandwidth available than the practical limit of around 1.4Mbit/s with 2M PHY that I so far observed with the throughput sample.

So far I have only been able to get a reliable stream going when heavily reducing the sensor sampling rate to 128-180Kbit/s but even then only in very specific combinations of MTU size and connection interval do I get a reliable transfer and without any clear reason as to why as both a larger and small MTU as well as longer and shorter connection intervals can cause the connection to get better or worse. I seem to sometimes hit magic numbers by trial and error that yield stable results.

So this has been very unintuitive so far as to how to tune these connection variables to get to a stable result and reasonable latency (<100ms).
Right now battery consumption is not the highest priority so it would be okay to use the most wasteful configuration as long as the bandwidth can be reached.

What is currently happening code wise is the sensor (dmic) reads into a memory slab. I pass the block pointer to the ble write thread and let the dmic continue to sample and grab the next block in the memory slab. For debugging I currently log the memory slabs block utilization.
The ble write thread then sends out the data in one or more messages depending on MTU size and memory block size.

Sometimes things go badly immediately and the memory blocks get used up immediately but sometimes its stable for a little bit and then suddenly goes sideways and the connection can't keep up with the sensor stream and fills up the slab.

How do I go about debugging this and are there deeper guides for this scenario in terms of PHY settings available to me.
I only found this on the topic so far: Building a Bluetooth application on nRF Connect SDK - Part 3 Optimizing the connection 

I have looked at what comes through the air with the BLE sniffer but could not spot anything obvious like too many retries.
Would a custom GATT profile be better suited? The NUS service seemed like a useful basis for this application but maybe I am overlooking a constraint here.

Parents
  • Hi Timon

    It is odd that you would get such low rates. Are you running Nordic devices on both sides of the link, or are you communicating with something else, like a smart phone? 

    Are you using custom hardware or standard devkits? 

    Did you confirm from the sniffer trace that data length and large MTU is probably utilized? 
    Could you see many packets sent back to back within a connection event, or only a single packet pr connection event? 

    For testing purposes I would recommend starting with dummy data just to rule out an issue in the handover between the DMIC reading and the Bluetooth transmission. 

    Best regards
    Torbjørn

  • I'm mostly testing with my Windows machine as the central. It has a Mediatek chipset for Bluetooth.
    I had also tried out the NUS Central sample but similar behaviour occurred though I have not dug deeper there other than upping the UART baud rate.
    In the end the application would have to work at least with your average Windows or Mac for now, later on also with phones so it would have to be somewhat reliable enough with third party chipsets too in any case.
    For bandwidth testing I stuck to the nRF5340DK instead of the custom hardware.

    Good call with testing dummy data, I don't think I have done that so far. From the profiling so far it didn't seem too much of a data handling issue as it was usually hanging at nus_send but good to double check.
    Below is a short block of what I captured with a 16hz sampling rate being transmitted.

    Both MTU size and 2M PHY were ack'ed by the central during connection handshake.
    But there are multiple L2CAP fragments between each event. I'm not knowledgable enough on the BLE PHY end to know if that is how a transmission works or if that should show up as a single packet equal to MTU size.

  • oh maybe I misunderstood something about the L2CAP layer. I thought the packet length was 265 and with overhead its 251 data bytes
    Was going by interrupt.memfault.com/.../ble-throughput-primer

  • Hi 

    It's a bit of semantics I guess, what you define as the payload or not. 

    The total packet length is higher, that is correct. You get either 10 or 14 bytes in addition to the payload I mentioned, depending on whether or not encryption is enabled.

    The total packet looks like this:

    1 byte preamble + 4 byte access address + 2 byte packet header + 0-251 byte data payload + 3 byte CRC (+ 4 byte MIC)

    This totals 265 bytes when using 251 byte payload and encryption. 

    Best regards
    Torbjørn

  • I wrote this to include in the code, as an aide memoire, hopefully it's about right :-)

    // +-----------------------------------------------------------------------------------------------------------------+
    // |                                             BLE Data Packet Min/Max                                             |
    // +-----------------------------------------------------------------------------------------------------------------+
    // |                                             1MHz: 10/265 octets, 2MHz: 11/266 octets                            |
    // +----------+--------+--------------------------------------------------------------------------------------+------+
    // |          | Access |                                                                                      |      |
    // | Preamble | Address|         Protocol Data Unit PDU                                                       | CRCC |
    // +----------+--------+--------------------------------------------------------------------------------------+------+
    // |   1 (2)  |    4   |                                                   2-257                              |  3   |
    // |          |        +-----------+------------------------------------------------------------------+-------+      |
    // |          |        | LL Header |  Payload                                                         |  MIC  |      |
    // |          |        +-----------+------------------------------------------------------------------+ (opt) |      |
    // |          |        |   2       |                                       0-251                      |   4   |      |
    // |          |        |           +--------+---------------------------------------------------------+       |      |
    // |          |        |           | L2CAP  |                                                         |       |      |
    // |          |        |           | Header |  ATT Data                                               |       |      |
    // |          |        |           +--------+---------------------------------------------------------+       |      |
    // |          |        |           |   4    |                              0-247                      |       |      |
    // |          |        |           |        +-----+-------+-------------------------------------------+       |      |
    // |          |        |           |        | ATT | ATT   |                                           |       |      |
    // |          |        |           |        | Op  | Attrib|  ATT Payload                              |       |      |
    // |          |        |           |        +-----+-------+-------------------------------------------+       |      |
    // |  1 (2)   |   4    |  2        |   4    |  1  |  2    |                0-244                      |  (4)  |  3   |
    // +----------+--------+-----------+--------+-----+-------+-------------------------------------------+-------+------+

Reply Children
No Data
Related