Increasing BLE Throughput

I've been following this blog post to increase BLE throughput for my application: Building a Bluetooth application on nRF Connect SDK - Part 3 Optimizing the connection - Software - nRF Connect SDK guides - Nordic DevZone (nordicsemi.com)

It's very helpful, but I need a little extra guidance. My setup is a Peripheral device with an nRF9160 as Host with a nRF52820 as Controller connecting to a Central device with a nRF52840 all using NCS v1.7.0. I'm attempting to send a large file to the Peripheral (500+ KB). I've gotten all projects configured to where the transfer takes about 5-6 minutes. I'm using a connection interval of around 7.5 ms, 0 latency, and 4 second timeout. Given RAM constraints on the 52820, the largest data length I can negotiate is 147 bytes. The MTU is 247 bytes. The PHY is 2M. These all seem decently optimal given my understanding of BLE. Based on the blog post, a conservative estimate of the throughput should be around 1000 kb/s for their configuration, and since my data length is decently shorter than the project in the blog post, let's just roughly estimate it's more like 700 kb/s. With that throughput, it works out to about 87,500 bytes per second. With a 500 KB file, the transfer would be about 5.7 seconds if all symbols being sent were the file; obviously, there's overhead, so let's be very conservative and triple that number to get around 17 seconds for the entire transfer. Correct me if my reasoning is wrong but given my explanation and how long it is currently taking to transfer the file, it seems that I am setting up something wrong. Are my connection parameters not optimized? I'm also using bt_gatt_write instead of bt_gatt_write_without_response or bt_gatt_notify which I do know is slowing the transfer down since the peripheral needs to respond, but it shouldn't be on the order of minutes right?

Edit: I figured out how to configure the 52820 project to increase the max data length to 251 bytes. I timed the transfer and it took 4 minutes. My goal is to still get the transfer down to under a minute since the Throughput example (Bluetooth: Throughput — nRF Connect SDK 1.7.0 documentation (nordicsemi.com)) shows that it transfers 598 KB in 3.8 seconds

  • Hey Simon,

    What is your current throughput? Have you managed to get close to the numbers in Bluetooth Low Energy data throughput?

    After performing write commands instead of write requests drastically improved the throughput. I've demonstrated sending the 500 KB file in about 1 min. That link is helpful for setting expectations on the speed.

    There are some useful blogs about BLE throughput you might want to check out:  

    I've read 2/3 of those blogs and they helped me get to where I am now. 

    The throughput also depends on how you store the file on the peer device, if you need to erase flash pages and write to flash. This will be a bottleneck.

    This paired with my first response regarding write commands and that link you sent me gives me some better context on my situation. My current setup is the file is stored on flash on another MCU (ESP32) that is the Internet link. That MCU downloads the file. The nRF52840 is scanning for peripherals that need to update. Once it finds one to update, the 840 connects to the peripheral and starts sending it the file. That whole process though consists of the 840 asking the ESP32 for a chunk of the file at a certain offset over UART, chunk gets sent over UART to 840 after it reads that chunk from flash at the specified offset, 840 sends chunk to peripheral via write command, and the whole process repeats itself.

    Based off the throughput link you sent me, it says that over 2M PHY, conn interval 7.5ms, and using write commands the throughput could reach up to 256 kbps with just straight data to peripheral, no other operations involved. That comes out to about 15 seconds for the transfer of a 500 KB file. Since I'm doing all these other transactions, the ~1 min transfer sounds right to me. Maybe it could be slightly improved.

    Could you provide a sniffer trace? Then it will be easier to spot where the issue is.

    I set it up on a dev kit that I have but once I had Wireshark open it was a little tough for me to discern how to sniff a connection based off of the instructions I found on Infocenter.

    Both write commands and write requests should be acked in the link layer, so both are reliable.

    That is good to know, I feel much better about using the commands instead of requests since they're both reliable. Just to clarify my understanding, what's the benefit of using the requests then? Is it just acked higher up in the BLE stack (GATT, application)?

    Thanks so much for all of your help so far

    Ethan

  • I'm happy you were able to increase the throughput to an acceptable level.

    esisk said:
    I set it up on a dev kit that I have but once I had Wireshark open it was a little tough for me to discern how to sniff a connection based off of the instructions I found on Infocenter.

    If you want to increase the throughput even more, a sniffer trace would be nice.

    Feel free to open a new ticket about the sniffer trace, and get back here as soon as you have gotten it working. Then I'll take a look at it.

    esisk said:
    Just to clarify my understanding, what's the benefit of using the requests then? Is it just acked higher up in the BLE stack (GATT, application)?

    Write requests can be useful in situations where you want to start some time consuming operation on the server side, and you want to restrict the ability to send more data or commands while the current operation is running. The server can send a response to the request once the operation is complete, and is guaranteed not to receive any new commands before this, since you can only have one indication pending at the time. 

    Indications/notifications are the equivalents of Write request/write command, just in the opposite direction. So the answer above was inspired by  RE: Use cases of indications - When is it better to use indications over notifications? 

    Best regards,

    Simon

  • Hey Simon, I'm replying here because the reply button won't show up on your most recent post. 

    Feel free to open a new ticket about the sniffer trace, and get back here as soon as you have gotten it working. Then I'll take a look at it.

    I'll do that sometime soon.

    Thanks for the clarification regarding requests vs commands. The last thing I need guidance on is scanning for other advertisements while sending this file. Is that even feasible given how much this file sending process is hogging the radio? If it's feasible, could you give me some advice as to how to go about setting that up or point me towards a good ticket regarding this? Currently haven't found anything.

  • Hi Ethan

    Simon is currently unavailable, and I will help you out instead. 

    Scanning while in a connection is possible, but it will affect the max throughput of your link, yes. What you can do to minimize the impact is to use a long scanning interval and a short scanning window, but this will obviously affect how fast you detect advertise packets so you have to do some testing to find a good compromise between scanning performance and the throughput of the connection. 

    Best regards
    Torbjørn

  • That's ok, thanks for stepping in Torbjørn. I actually found a decent compromise between scanning discovery and connection throughput, thanks for your suggestion. One more question I have: I noticed that with write commands, the length of the data I can send seems to be limited by the MTU whereas write requests can split a say 2KB packet into the necessary lengths and then some layer in the Bluetooth stack on the peripheral can assemble them all back together to 2KB before giving it to the peripheral's application layer. Is that possible with write commands as well? I'm trying to reduce the number of flash reads and UART transmissions I need to make in order to send this file

Related