NRF52840 BLE NUS data transmission is too slow

Dear all,
my project consists of 6 nRF52840 custom boards, one acting as central device and the other five acting as peripherals (star connection).


The central device receives USB serial commands from PC and transmits them via BLE to the five peripherals and the peripherals respond by sending sensors data back to the central.
Everything works like a charm except from the fact that the throughput is really slow.

The basis for the central and peripherals firmware have been the following SDK examples

  • nrf52-ble-app-uart-c-multilink ( Central)
  • ble_app_uart (peripherals)

To make things a little more simple, I decided to split the problem by creating a simple connection between the central device and only one peripheral and perform transfer speed tests.

For both central and peripheral I placed the same settings. The settings are the following

1a. Connection interval setting in main.c (Peripheral)

#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(9, UNIT_1_25_MS)          
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(10, UNIT_1_25_MS)            

1b. Connection Interval setting in sdk_config.h (Central)

// <o> NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL - Determines minimum connection interval in milliseconds. 
#ifndef NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL
#define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 9
#endif

// <o> NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL - Determines maximum connection interval in milliseconds. 
#ifndef NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL
#define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 10
#endif

2. GAP Data Length in sdk_config.h (Peripheral & Central)

#ifndef NRF_SDH_BLE_GAP_DATA_LENGTH
#define NRF_SDH_BLE_GAP_DATA_LENGTH 251
#endif

3. MAX MTU size in sdk_config.h(Peripheral & Central)

#ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE
#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247
#endif

4. Event length in sdk_config.h (peripheral & Central)

#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH
#define NRF_SDH_BLE_GAP_EVENT_LENGTH 7
#endif

5a. Link Count Settings in sdk_config.h (Peripheral)

#ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT
#define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1
#endif
 
#ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT
#define NRF_SDH_BLE_CENTRAL_LINK_COUNT 0
#endif

#ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT
#define NRF_SDH_BLE_TOTAL_LINK_COUNT 1
#endif

5b. Link Count Settings in sdk_config.h (Central)

#ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT
#define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 0
#endif

#ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT
#define NRF_SDH_BLE_CENTRAL_LINK_COUNT 1 
#endif

#ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT
#define NRF_SDH_BLE_TOTAL_LINK_COUNT 1
#endif

6a. Physical layer setting in main.c (Peripheral)

        case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
        {
            NRF_LOG_DEBUG("PHY update request.");
            ble_gap_phys_t const phys =
            {
                .rx_phys = BLE_GAP_PHY_1MBPS, 
                .tx_phys = BLE_GAP_PHY_1MBPS, 
            };
            err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
            APP_ERROR_CHECK(err_code);
        } break;

6b. Physical layer setting in sdk_config.h (Central)

// <0=> BLE_GAP_PHY_AUTO 
// <1=> BLE_GAP_PHY_1MBPS 
// <2=> BLE_GAP_PHY_2MBPS 
// <4=> BLE_GAP_PHY_CODED 
// <255=> BLE_GAP_PHY_NOT_SET 

#ifndef NRF_BLE_SCAN_SCAN_PHY
#define NRF_BLE_SCAN_SCAN_PHY 1
#endif

Last but not least, since the maximum transmittable data size for NUS is: 247B - 3B (NUS header) = 244 bytes, I send 244 B every time I execute command ble_nus_data_send()
to send data (in the peripheral code).

In the peripheral code I created a dummy bytes array of 4096 bytes and I send it to the central every time I send a get_data command from the central to the peripheral device.

The code part that corresponds to the 4096 bytes transmission from the peripheral to the central is the following

       size = 243;
       for(uint8_t i = 0; i<16; i++)    //send the cache buffer to tablet in chunks of 128 bytes
       {  
          nrf_gpio_pin_clear(TestPin); 
          err_code = ble_nus_data_send(m_nus_gen, &localBuffer.convPacket[i*size], &size, *m_conn_handle_gen);
          if(err_code = NRF_ERROR_RESOURCES)
          {
             bleBuffer_is_full = true; 
             while(bleBuffer_is_full); 
          }
          nrf_gpio_pin_set(UART_RX_PIN); // TODO TEST OUTPUT
       }
       size = 191;
       err_code = ble_nus_data_send(m_nus_gen, &localBuffer.convPacket[16*size], &size, *m_conn_handle_gen);
       if(err_code = NRF_ERROR_RESOURCES)
       {
          bleBuffer_is_full = true; 
          while(bleBuffer_is_full); 
       }     
       nrf_gpio_pin_set(TestPin); 

What I do is:

  • 16 transmissions of  244 bytes of the dummy array = 3904 kBytes and 
  • one last transmission of 192 bytes
  • After each transmission I check the BLE_GATTS_EVT_HVN_TX_COMPLETE event to be sure that transfer is complete

With those settings for peripheral and central (in 1 to 1 connection) the maximum transfer speed I can get from the peripheral is around 17kB/sec and the time for one BLE packet transmission of 244 bytes is about 25msec.

While in theory, after calculations, for PHY_1M,  throughput should be: about 100kB/sec and the Data packet time: about 2.5msec

When I connect the central to the debugger and once the connection to the peripheral has been established,
I get the following feedback information in the debug terminal which seem correct...  maxTx/Rx Time: 2.120msec and max Tx/Rx Octets: 251

<debug> ble_scan: Connecting
<debug> ble_scan: Connection status: 0
<debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
<debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
<debug> nrf_ble_gq: Registering connection handle: 0x0000
<debug> ble_db_disc: Starting discovery of service with UUID 0x1U of 247 bytes.
<debug> nrf_ble_gatt: Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
<debug> nrf_ble_gq: Processing the request queue...
<debug> nrf_ble_gq: GATTC Primary Service Discovery Request
<debug> nrf_ble_gq: SD is currently busy. The GATT request procedure will be attempted                           again later.
<debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
<info> app: ATT MTU exchange completed.
<info> app: Ble NUS max data length set to 0xF4(244)
<debug> nrf_ble_gq: Processing the request queue...
<debug> nrf_ble_gq: GATTC Primary Service Discovery Request
<debug> nrf_ble_gq: SD GATT procedure (2) succeeded on connection handle: 0.
<debug> nrf_ble_gatt: Data length updated to 251 on connection 0x0.
<debug> nrf_ble_gatt: max_rx_octets: 251
<debug> nrf_ble_gatt: max_tx_octets: 251
<debug> nrf_ble_gatt: max_rx_time: 2120
<debug> nrf_ble_gatt: max_tx_time: 2120
<debug> ble_db_disc: Found service UUID 0x1.
<debug> nrf_ble_gq: Adding item to the request queue
<debug> nrf_ble_gq: GATTC Characteristic Discovery Request
<debug> nrf_ble_gq: SD GATT procedure (3) succeeded on connection handle: 0.
<debug> nrf_ble_gq: Processing the request queue...
<debug> nrf_ble_gq: Adding item to the request queue
<debug> nrf_ble_gq: GATTC Characteristic Discovery Request
<debug> nrf_ble_gq: SD GATT procedure (3) succeeded on connection handle: 0.
<debug> nrf_ble_gq: Processing the request queue...
<debug> nrf_ble_gq: Adding item to the request queue
<debug> nrf_ble_gq: GATTC Characteristic Descriptor Request
<debug> nrf_ble_gq: SD GATT procedure (4) succeeded on connection handle: 0.
<debug> nrf_ble_gq: Processing the request queue...
<debug> ble_db_disc: Discovery of service with UUID 0x1 completed with success on connection handle 0x0.
<info> app: Discovery complete.
<debug> nrf_ble_gq: Adding item to the request queue
<debug> nrf_ble_gq: GATTC Write Request
<debug> nrf_ble_gq: SD GATT procedure (1) succeeded on connection handle: 0.
<info> app: Connected to device with Nordic UART Service.


I tried several event length and connection Interval variations (with event length always less or equal to the connection interval) but nothing increased the transfer speed.

I believe that I forget something or I do something wrong in my code but I cannot find what it is...

Any ideas?

Thank you for your time

Parents Reply Children
Related