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

Multiple packets per connection interval - s132/IOS

Target - NRF52832 populated on a custom PCB using SDK 14.0.0 and s132 5.0

Background - end device will be used to send logged IMU data to the cloud via a smart device, 2-3mB expected to be sent at a time

Looking for a bit of help to increase the throughput using an IOS master (or really any device, but I'm currently using an iphoneSE). I'm running a lightly modified version of the peripheral ble_app_uart example - no UART functionality is now used, I am simply sending dummy data to evaluate throughput. Data length is successfully negotiated to 182 bytes. Connection interval is confirmed at 30ms. I am sending 182 byte packets (using ble_nus_string_send) upon every receipt of BLE_GATTS_EVT_HVN_TX_COMPLETE. Reviewing a log of packets received on the iphone (using lightBlue), I am predominately seeing a packet sent every ~30ms, with occasional packets separated by a few milliseconds. This results in a functional throughput of about 7kB/s.

I expected (hoped) that I would see multiple packets received within that 30ms window.

My questions:

  1. I've read that the connection interval can be dropped to 15ms with iOS devices - can you provide guidance with regards to the best way to complete this. I attempted to negotiate after a connection was made (using ble_conn_params_change_conn_params), but the 30ms interval was maintained. I understand that it may be better to stick with a longer connection interval given the bigger packet size (and assuming I can get to 6 or 7 packets per interval), but if I am limited to fewer packets per interval, a shorter connection interval would be better.

  2. What might be limiting me to 1, occasionally 2, packets per interval? Should I be attempting to send more frequently than waiting for BLE_GATTS_EVT_HVN_TX_COMPLETE?

Any help appreciated, I have searched, and turned up a number of good threads that have helped me get this far, but I think I've hit a bit of a wall.

-Chris

  • Hi Chris,

    Yes, that is the correct way of doing this. I don't know why you only get one packet.

    Please let us know the result of the test with your phones. What printed out on UART ? What is the connection interval.

    My test here with the unmodified example above, with an S6 showing 60kbps, 5 packets per interval , 15ms interval. Please use NRFConnect to test. On S8 it's 1200kbps.

    Please try capture a sniffer trace.

    You can also test between 2 nRF DK one as central one as peripheral to see the maximum through put it can achieve.

  • Hung- Apologies I did not send the actual output, I was too focused on the details. Using an iPhone SE, I hit, on average, 124kpbs with a 182B data length and an average buffer length of 90. Based on the log in either lightBlue explorer or nRF toolbox, packets are being sent at ~15ms intervals, with occasional multiple packets per interval. Based on a quick calc, this makes sense - 182Bytes8bits(1/15ms) = 97kbps, 2 packets per interval is of course double this, so occasional multiple packets per interval would yield a throughput between these two numbers.

    With a S7, a ~480kbps throughput is achieved with a 244B data length and an average buffer length around 250. The log file on this device always crashes, so I can't be sure of the interval, but assuming 15ms, then given the 244B data length, multiple packets must be sent during a given interval.

    With a iPhone X, I was still only able to hit a 182B data length, but an average transfer speed of ~500kbps was achieved. Again, obviously multiple packets were sent.

    So, it seems that multiple packets are being sent per interval, but it also seems that, based on my code testing, making calls to sd_ble_gatts_hvx before receiving BLE_GATTS_EVT_HVN_TX_COMPLETE is not the mechanism which enables multiple packets per interval to be sent and actually doesn't seem to do anything since, until BLE_GATTS_EVT_HVN_TX_COMPLETE is received, sd_ble_gatts_hvx returns NRF_ERROR_RESOURCES.

    Apologies that I kind of backed in to this as an answer, but based off of documentation/threads elsewhere, I was led to believe that the multiple calls to sd_ble_gatts_hvx before receiving BLE_GATTS_EVT_HVN_TX_COMPLETE was necessary to maximize throughput. I just want to be sure that I have a (somewhat) reasonable understanding about how the examples work before I start working on my own code.

    Please let me know if you disagree or find any issues with what I've stated above.

    -Chris

  • Hi Chris,

    Think of the buffer like this, you have 7 buffers. At the beginning they are all free, or at least you don't know how many are free. It's the buffer shared between a write command and a notification. You call sd_ble_gatts_hvx () as many as possible until it's full and you receive NRF_ERROR_RESOURCES.

    Calling sd_ble_gatts_hvx again before receiving BLE_GATTS_EVT_HVN_TX_COMPLETE usually won't help. Because the buffer was full before that and usually in one connection event, you can't get the buffer from full to empty (7 packets to be sent). So it's better to just wait for BLE_GATTS_EVT_HVN_TX_COMPLETE before calling sd_ble_gatts_hvx () again.

    To achieve 247 bytes MTU on iOS , as I suggested in the first answer, you let the phone request it instead of requesting it from the nRF5. To do that you need to comment out the call to sd_ble_gattc_exchange_mtu_request() inside on_connected_evt() in nrf_ble_gatt.c

  • Hung- Ah, thanks, that makes sense. On either IOS device, based on what is logged in RTT, the initial MTU exchange upon connection results in a 185 byte MTU, with or without the code commented out that you mention above. Leaving the code in simply results in another negotiation to a 185 byte MTU, Not really a huge deal right now, but it will be good to eventually get to 247 bytes on an IOS device.

    -Chris

  • Hi Chris,

    If you can provide a sniffer trace, it would be easier to check from whom the MTU request is sent. There is also a chance that an iOS update can change the behavior of the phone.

Related