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

(nRF52832 / SDK 14.0 / s132 5.0.0) Optimizing BLE throughput between nRF52 (peripheral) and Android device (central)

I'm using the nRF52382 with SDK 14.0 and softdevice s132 5.0.0, and I need to send up to hundreds or thousands of kilobytes to an Android phone over BLE. I need to optimize throughput, and I've read all the forum and blog posts I could find, and so I knew generally that I need to send data to the phone using notifications. And I knew that I need to support higher MTU and data length values. Most discussions say to look at the ble_app_att_mtu_throughput example, but that example uses an nRF52 in both roles, so it was hard to know which of that example's approaches still apply when using an Android device in the central role.

I primarily test with a Samsung Galaxy S7 running Android 7.0 and Bluetooth 4.2, so all of my throughput numbers here were recorded with that phone running nRFConnect version 4.17.0.

My baseline functionality left maximum MTU at 23 and used a connection interval of 15ms, and I typically got throughput speeds of about 20kbit/s. To optimize throughput, I've done the following:

  • Increase NRF_SDH_BLE_GATT_MAX_MTU_SIZE in sdk_config.h to 247. This requires updating the linker file to allocate more RAM to the softdevice. This also results in data length extension being used, which apparently requires the NRF_SDH_BLE_GAP_EVENT_LENGTH setting in sdk_config.h to be increased from 3 (3.75ms) to 5 (6.25ms).
  • Use as low a connection interval as possible. In the last few major Android releases (since Android 6.0 maybe?), this appears to be 11.25ms. But nRFConnect and some Android Bluetooth libraries appear to only allow setting connection interval as low as 15ms, so that's what I currently use.
  • Increase NRF_SDH_BLE_GAP_EVENT_LENGTH. I actually don't fully understand this parameter, but trial and error showed that setting this to match my connection interval at 15ms seemed to maximize throughput.
  • Disable wifi on the Android device. I believe the antenna is time-multiplexed between wifi and Bluetooth, so disabling wifi apparently allows more time for Bluetooth. Limited testing shows this might've bumped my throughput up by 50kbit/s or more.

With all these, I'm seeing data rates up to about 375kbit/s with my phone right next to my nRF52 board. (I also briefly tested my old Samsung Galaxy S5 with Android 5.1.1 and Bluetooth 4.0 and got throughput of about 100kbit/s.)

And so here are some questions:

  1. What exactly does the NRF_SDH_BLE_GAP_EVENT_LENGTH setting do? Why does increasing it require more RAM? Is setting it to match my connection interval the right approach? Are there any other connection interval/event length combinations that would increase throughput? I tried setting both to 30ms and 45ms, but it didn't seem to help.
  2. What sorts of throughput numbers can we expect with an Android device in the central role? The throughput example claims numbers about 2x as fast as I'm seeing with Bluetooth 4.2. Is this expected? What are the limitations?
  3. Are there any optimizations that I haven't mentioned that I may not already be using? I'm not in a position to test the 2M PHY yet. The throughput example uses the connection event extension feature with longer connection intervals, but I read somewhere that that is actually a Nordic feature rather than a Bluetooth spec feature, so my understanding is that I can't use that feature with an Android device.
  4. With these settings (MTU of 247, data length of 251, connection interval of 15ms, event length of 15ms), throughput is actually _very_ erratic and _heavily_ dependent on signal strength. Is it my imagination, or is it possible for throughput to actually drop below throughput of some lower performance configurations in some poor signal strength scenarios? If it's possible to sacrifice some throughput for better stability, what would be the best approach?
Parents
  • 1. the NRF_SDH_BLE_GAP_EVENT_LENGTH  in the length of the connection event. The bigger you set this variable, the more packets (or longer packets) you can send in one connection event because the connection event is longer. This means the buffer to store packets that can be sent has to be bigger, which increases your RAM usage. 

    You can send more than one packet in a connection event. If you set your MTU to 247 and you have a NRF_SDH_BLE_GAP_EVENT_LENGTH  that allows to send 6 packets per connection event, you maybe need a higher connection interval to be able to send 6 packets of 247B. So increasing your connection interval can optimize your throughput.

    Have a look here on how to optimize throughput: www.novelbits.io/.../

Reply
  • 1. the NRF_SDH_BLE_GAP_EVENT_LENGTH  in the length of the connection event. The bigger you set this variable, the more packets (or longer packets) you can send in one connection event because the connection event is longer. This means the buffer to store packets that can be sent has to be bigger, which increases your RAM usage. 

    You can send more than one packet in a connection event. If you set your MTU to 247 and you have a NRF_SDH_BLE_GAP_EVENT_LENGTH  that allows to send 6 packets per connection event, you maybe need a higher connection interval to be able to send 6 packets of 247B. So increasing your connection interval can optimize your throughput.

    Have a look here on how to optimize throughput: www.novelbits.io/.../

Children
  • Interesting- I currently have event length set to 15ms since that's what I typically use for connection interval, but it didn't appear that setting event length any higher (say, to 30ms or 45ms) in case I wanted to use longer connection intervals required any additional RAM.

    The 6 packets per connection interval is a limitation of Android, right? Not Bluetooth?

    And thanks, yeah, I'd seen that article about optimizing throughput, but the numbers they measure are for nRF52-to-nRF52, so I'm curious about how much slower we should expect to see a connection with an Android phone to be, where the bottlenecks are when transferring to an Android phone, and whether I'm already hitting those bottlenecks or if there are further improvements I can make.

Related