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

Bidirectional throughput analysis with nrf52840 and Android

Hello Team,

Currently, we are evaluating nRF52 using nRF52840DK for one of our upcoming project. Basically, our typical application involves sending 32 Bytes of command data from Android to nRF52 and getting 256 bytes from nRF52 to Android. 

Considering this, we have taken the Android application “nRF UART Version 2.0” and the Firmware example “ble_app_att_mtu_throughput” as a reference and slightly modified them to perform sending the following sample commands from the Android application and handling the same from the nRF device FW.

100k

Instructs the nRF device to send 100KB data to the mobile device.

Used to test and simulate unidirectional throughput of the nRF device.

m100k

Instructs the Android tool to send 100KB data to the nRF device.

Used to test and simulate unidirectional througput of the mobile device.

10k 32

Instructs the nRF device to send 10KB data to the mobile device. During the transfer, the mobile device sends 32 bytes for every packet (244 bytes) that it receives.

Used to test and simulate bidirectional throughput.

10k 32 w30 w20

Instructs the nRF device to send 10KB data to the mobile device. During the transfer, the mobile device sends 32 bytes for every packet (244 bytes) that it receives; the nRF device performs a delay of 30 ms before sending every packet; the mobile device performs a delay of 20 ms before sending every 32 bytes.

Used to test and simulate bidirectional throughput with delays.

Command flow:

If we take the bidirectional transfer scenario of “10k 32” the overall application flow would be:

1 - The Android application writes 32 bytes to the write characteristic

2 - nRF FW gets a write callback on nrf_ble_amts_on_ble_evt() which is registered as NRF_SDH_BLE_OBSERVER

3 - Immediately the nRF52 FW calls char_notification_send(), to push 244 bytes as notification to the Android application

4- The Android application gets onCharacteristicChanged() from BluetoothGattCallback.

5 - Again the Android application performs Step-1. And this loop continues until 10k data is retrieved from the nRF device.

For information:

To send data from Android to nRF52, the system uses write without response and

To send data from nRF52 to Android, the system uses notification.

The Android application and the FW supports all transfer data lengths up to 1000K and delays up to 100ms.

While connecting to the “Nordic_ATT_MTU” from the Android application, we could see the connection parameters being updated in the nRF device by connecting the board to a putty/terminal window.

Observation:

By performing these test commands with a Samsung S10 running on Android 10, with BLE 5.0 parameters 2M PHY, 251 byte DLE, 247 bye MTU and connection interval 11.25 ms, here is our observation:

100k ==> 1201 kbps at 682 ms (nRF side) and 1168 kbps at 697 ms (App side)
m100k ==> 331 kbps at 2.473(nRF side) and 480 kbps at 1.707 s(App side)
10k 244 ==> 72.68 kbps at 1.128 sec (nRF side) and 64 kbps at 1.199 sec (App side)
10k 244 w30 w20 ==> 22 kbps at 3.627 sec (nRF side) and 16 kbps at 3.776 sec (App side)

Question:

From the above results, we observe that,

  • the unidirectional throughput from the nRF device (1201 kbps) is reaching the theoretical maximum (1400 kbps).
  • the unidirectional throughput from the Android device (480 kbps) is 65% slower than the theoretical maximum. We could not understand the reason for this drop.
  • the bidirectional throughput is more than 85% slower than the theoretical maximum. We could not understand the reason for this “drastic drop”.

Hereby we have attached our Android apk and the nRF FW binary for reference. Could you please guide us on the possible ways to improve the throughput for the bidirectional transfer case?

nRF uart v2.0.apkble_app_att_mtu_throughput_pca10056_s140.hex

Parents
  • Hi,

    The maximum throughput of Android devices varies with phone models and Android versions (as is the case with iOS). The phone may also adjust relevant parameters depending on the state of the phone and the application in question (foreground/background etc.). There are a few things you can do on the Android application to influence this. I do not have any recent documentation, but you can find a good (but slightly dated) overview here.

  • Hi Einar,

    we are using MTU 247 that's the maximum MTU size peripheral is supported and DLE 251 as well, we are using bidirectional data transfer, so by examining using NRF sniffer with Wireshark, for writing it's taking 1 connection interval and for the notification (response from peripheral) happens in the next connection interval.
    so if we calculate for 10k, 10*1024 =10240 / 244(maximum number of byte in a packet) = 42 packet for 10k.

    For each packet master will send a written request. 42*2(request 1 packet and response another 1 packet) = 84.

    84*11.25(connection interval) = 945ms, which is nearby value to our observation that is 1 second practically.

    I tested with Samsung S10, one plus 6 and Samsung M30 all the results are near to 950ms - 1.2 Second

    is there any possibility is there to improve the throughput further by fitting both writing and response in a single connection interval?

  • Hi,

    aslamz said:
    is there any possibility is there to improve the throughput further by fitting both writing and response in a single connection interval?

    The SoftDevice used to have API to specify the maximum number of packets per connection (up to version 2 if my memory is correct), but recent SoftDevice versions does not have that. Instead, you configure the event length. With a large maximum event length, more packets can fit into one event. This is described in this post. Note that the ble_app_att_mtu_throughput example already has this set to a high value (400 * 1.25 ms). Another point is that the event length can be limited by the connection interval. So you should not use a high connection interval if you try to get high throughput by having long event lengths.

Reply
  • Hi,

    aslamz said:
    is there any possibility is there to improve the throughput further by fitting both writing and response in a single connection interval?

    The SoftDevice used to have API to specify the maximum number of packets per connection (up to version 2 if my memory is correct), but recent SoftDevice versions does not have that. Instead, you configure the event length. With a large maximum event length, more packets can fit into one event. This is described in this post. Note that the ble_app_att_mtu_throughput example already has this set to a high value (400 * 1.25 ms). Another point is that the event length can be limited by the connection interval. So you should not use a high connection interval if you try to get high throughput by having long event lengths.

Children
  • Hi Einar,

    I cross-checked the NRF_SDH_BLE_GAP_EVENT_LENGTH value it's 400. When just sending data in unidirectional either by writing without a response from the client to server or Notification from server to client being able to send 7 packet's in a connection interval. But the bottleneck is coming up when we are doing this bidirectional transfer.

    Even I observe write with the response is taking 2 connectin intervals. 1 is for writing and another one for the response.

  • Hi,

    I do not have an explanation for this based on the nRF Configuration. There should be no problem sending multiple notifications in the same connection event. Note that if you used indications that would be different since an indication must be acked before another is sent. Can you double-check that you are using notifications (as you wrote initially), and not indications?

  • Hi Einar,

    we are able to send multiple notifications in a single connection interval. We are using notification only not indication.

    My question is when we are writing from android to NRF can we able to send a response back to android as a notification in the same connection interval(both write and notification)? 

  • Ah, sorry. This was filtered in my head.

    Write with the response (reliable write) will take two events since the application layer on the peer needs to accept the write, which then happens in the next event. This is not suitable if you want high throughput. Write without response also requires an ack before continuing, which may or may not occur in the same connection event depending on the implementation. You should use notifications instead if you need high throughput.

Related