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

Low transfer rate between nRF52840-DK (BLE) and nRF Connect (android app)

Hi,

I'm trying to transfer data between an nRF52840-DK and an Android phone which has nRF Connect installed on it and I can only reach about 40kbps (that is kilo bytes per second) where I need about 68kbps.

Here is what I do:

1. on the Android phone (Android 8, Samsung Galaxy 10) I open "nRF Connect" and connect to my custom device. Then I request connection priority high and set preferred PHY to LE 2M for both TX and RX.
I get success for switching PHY TX & RX to LE 2M. and connection is updated to interval: 15ms, latency: 0, timeout: 20000ms.
Then I turn on notifications to my custom characteristic.

2. on the nRF52840-DK I have PDM driver running that collects data into a buffer of type: int16_t pdm_buffer[254]; // biggest buffer that doesnt return an error
When the PDM driver handler is called with p_evt->buffer_released != NULL I send this buffer as a notification over a custom service + characteristics I created that handles the size of this buffer + 1 byte at the beginning for a running packet index (to see if I lose packets).

Overall PDM produces 16kHz * 2 (2 microphones) * 2 (16 bit) = 64000 bytes per second of data which I try to pass to the nRF Connect app in packets of size 254*2 + 1 = 509 bytes (254 samples + 1 index byte at the beginning).

Now, my problem is that I lose about 1/3 of the packets somehow (I can tell by looking at the first byte of the packets I do get in the nRF Connect log) which means a transfer rate of about 40kbps.

My question is - how can I increase the transfer rate ? how can I make it reliable ?

Parents Reply
  • I've increased NRF_SDH_BLE_GAP_EVENT_LENGTH from 140 (hexadecimal) to 280 (twice the size, didnt know proper value to put there) and I've embedded the sd_ble_gatts_hvx() function inside a do { /* ... */ } while (err_code == NRF_ERROR_RESOURCES); loop.

    As a consequence I'm not losing packets over the BLE, however the while loop is stuck for enough time for me to lose buffer(s) passed to me from the PDM handler.

    In other words, we moved the problem a stage back in the chain.

    The "real" way to handle this is to somehow increase the BLE transfer rate. How do I do that ?

Children
  • You have to reorganize your code. Use state machines or the app scheduler or something. You need to be able to retry later in case of error, i.e. fail -> tend to other stuff -> retry again...

  • You can also use the TX done event to retry

  • I do that, however it wont fix the core issue that I have:

    PDM driver push data faster than I can sent it over BLE. I am bound to hit an overflow somewhere. The only thing I can play with is where the overflow will happen.
    In the soft device -> lost packets.
    In the PDM handler -> lost PDM buffers.

    Only real way to fix this issue is to make it possible for me to send in a transfer rate higher than ~66kbps (kilo bytes per second)

    I read a few posts here that people managed to send in much much higher rates, but it isnt clear to me how they did it or if it was ever between a developer board and an android device.

  • I assume that you also have these parameters configured like this:

    NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247

    NRF_SDH_BLE_GAP_DATA_LENGTH 251

    You might also want to enable extended BLE connection events, and see if that improves the throughput.

    Create a function like this:

    void conn_evt_len_ext_set(void)
    {
        ret_code_t err_code;
        ble_opt_t  opt;
    
        memset(&opt, 0x00, sizeof(opt));
        opt.common_opt.conn_evt_ext.enable = 1;
    
        err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
        APP_ERROR_CHECK(err_code);
    }

    and call it after ble_stack_init() in main().

  • my configuration is:

    #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 1024 // had to adjust RAM start and length for this
    #define NRF_SDH_BLE_GAP_EVENT_LENGTH 352 // was 247, changed to 351, cant see any effect
    #define MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(8, UNIT_1_25_MS)

    This is the MTU size I get (in the logs):
    <info> app: GATT ATT MTU on connection 0x0 changed to 517.

    I added the function and I call it, but the throughput stays the same.

    Has anyone ever got a higher transfer rate between an nRF52840-DK and an android device ? (higher than 40 kilo bytes per second)

Related