This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

BLE UART - ble_nus_string_send() connection interval & data transfer

Hey guys,

From what I understand, the minimum connection interval on say, an iPhone, is 20ms. Also, you can send up to 6 packets of 20 bytes within a connection interval. So that's 120 bytes every 20ms.

I've been playing around with the UART peripheral example in SDK 14. I notice that the function ble_nus_string_send() sends a max length of 20 bytes.

What I want to know is how exactly are the data packets and connection interval handled? For example, if I call ble_nus_string_send() once with 20 bytes, will it just go ahead and send the 20 bytes and take up the entire 20ms connection interval?

Consequently, if I call ble_nus_string_send() 6 times with 20 bytes, will all that data transfer within the one connection interval?

Just trying to wrap my head around how this all works. I'll search for some explanations on the SDK and tutorials, but thought it might be more time effective to ask on here.

Thanks!

Parents
    • I understand the connection interval is controlled by the central. I have it currently set up so that the peripheral demands a min/max of 20ms connection interval. When using the nRF Sniffer and the UART app on Android I can see that it goes through several connection updates to eventually agree upon the 20ms connection interval (from what I've read online, iOS minimum is 20ms)

    • I understand what you're saying about unexpected timing of packets going out because of all the stuff the stack handles in the background. I'll try just queueing as many packet transfers as possible. I'm sampling data at 100Hz and want to make sure the BLE buffer can be sent in time before the double buffer gets full

    • I'll look into the GAAT MTU stuff...I don't really know what you're referring to at the moment

    • What I am a little confused about though is that when using the nRF sniffer and sending 6 successive 20 byte packets using ble_nus_string_send(), it looks like the time stamps between each packets works out to around 20ms between each packet. I thought that you are able to send up to 6 packets within one connection interval, but it seems to be only sending one packet per interval. Any suggestions?

    --------------- UPDATE ------------------

    See attached images. When the GAP_EVENT_LENGTH is set to 3 (default UART example), each packet is sent out every 20ms+. When I set it to 16, it seems to send out all 6 packets within the 20ms connection interval which is within spec...

    --------------- UPDATE 2 ------------------

    I tried again with GAP EVENT set to 3 and a 20ms connection interval. All other times I do see that each packet transmits at 20ms and not 40-45 like the last image...so I don't really know what happened there. See attached images. I've also included images for the last LL_CONNECTION_UPDATE message before it gets accepted to show that the connection interval is set to 20ms. So it does seem like this parameter in the config file is solving the issue. Will have to do further reading to fully understand why though.

    Also, for reference, here are the Wireshark data dump files.

Reply
    • I understand the connection interval is controlled by the central. I have it currently set up so that the peripheral demands a min/max of 20ms connection interval. When using the nRF Sniffer and the UART app on Android I can see that it goes through several connection updates to eventually agree upon the 20ms connection interval (from what I've read online, iOS minimum is 20ms)

    • I understand what you're saying about unexpected timing of packets going out because of all the stuff the stack handles in the background. I'll try just queueing as many packet transfers as possible. I'm sampling data at 100Hz and want to make sure the BLE buffer can be sent in time before the double buffer gets full

    • I'll look into the GAAT MTU stuff...I don't really know what you're referring to at the moment

    • What I am a little confused about though is that when using the nRF sniffer and sending 6 successive 20 byte packets using ble_nus_string_send(), it looks like the time stamps between each packets works out to around 20ms between each packet. I thought that you are able to send up to 6 packets within one connection interval, but it seems to be only sending one packet per interval. Any suggestions?

    --------------- UPDATE ------------------

    See attached images. When the GAP_EVENT_LENGTH is set to 3 (default UART example), each packet is sent out every 20ms+. When I set it to 16, it seems to send out all 6 packets within the 20ms connection interval which is within spec...

    --------------- UPDATE 2 ------------------

    I tried again with GAP EVENT set to 3 and a 20ms connection interval. All other times I do see that each packet transmits at 20ms and not 40-45 like the last image...so I don't really know what happened there. See attached images. I've also included images for the last LL_CONNECTION_UPDATE message before it gets accepted to show that the connection interval is set to 20ms. So it does seem like this parameter in the config file is solving the issue. Will have to do further reading to fully understand why though.

    Also, for reference, here are the Wireshark data dump files.

Children
  • Probably just last bullet point opens new question, here is my humble answer: are you sure that you called ble_nus_string_send function as far as it was returning NRF_SUCCESS? When you receive BLE_GATTS_EVT_HVN_TX_COMPLETE event and what you do when stack call-back gives you this event value? Are you sure that you'r connection bandwidth setting on Nordic side is HIGH so you could see multiple PDUs per interval?

  • To be honest, I just copied and pasted ble_nus_string_send() 6 times to see what it would do. I'm just working off the ble_app_uart example. Nothing is handling the TX_COMPLETE event as far as I can see.

    Basically in my nus handler, I call ble_nus_string_send() six times trying to send over some constant data packets of 20 bytes.

    Not sure about the connection bandwidth...I will look into it further...

  • In case of such test simply just push some consecutive sequence of bytes (like 0x00 01 02 03...) split into 20-byte blocks through that NUS function and paste sniffer trace here for analysis. It should really give multiple packets per interval and if not then at least we can see More Data (to send) bit in PDU header so it will indicate if it's phone's stack which blocks more packets or if simply Nordic stack doesn't have more things to send (which would indicate either problem in bandwidth settings or in queuing of NUS function calls in your FW).

  • Yup, that's exactly what I was trying. I'll upload some images in a bit. It seems like in the SDK config, there is a parameter "NRF_SDH_BLE_GAP_EVENT_LENGTH" that is used to set the connection time for every connection interval. By default the UART example set this to 3 (3*1.25ms). If I change it to 16 (20ms), then the data in the sniffer seems to make more sense. See related thread below:

    devzone.nordicsemi.com/.../

    Again I wish there was some better documentation on this stuff...

  • I do agree that bandwidth settings in the latest Nordic SoftDevice API is little bit cryptic, but have you looked to API and SD specifications? Also timing in your both JPG screenshots looks pretty similar to me (always ~40ms between two Notifications) - could you show unfiltered trace to see where are empty PDUs and also some view of PDU headers to check MD bit value? Note that Nordic sniffer isn't accurate in timing on this scale and it can go off because of different delays and caching along the way through USB to Wireshark (I've seen inaccuracy larger then 10ms).

Related