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

Increase data transfer rate for nRF52840 for queued write

Hi

I am using the provided example ble_app_queued_writes to send 256 bytes in each call.

It is taking around 13 seconds to transfer 3136 bytes:

12 calls of 256 and one for 64. Around 1 second per transfer. This seems very slow to me.

I checked many posts on this site and refered the throughput and long range demo to make the data transfer faster.

I got slight improvement of a second overall when i made following changes:

1) Updated BLE_GAP_DATA_LENGTH_DEFAULT to 128 from 27 (Successful)

2) Updated 

MIN_CONN_INTERVAL to MSEC_TO_UNITS(10, UNIT_1_25_MS) (Successful)

MAX_CONN_INTERVAL to MSEC_TO_UNITS(20, UNIT_1_25_MS) (Successful)

Other useful changes sugested gives error once the hex is uploaded:

1) ATT MTU :  NRF_SDH_BLE_GATT_MAX_MTU_SIZE more than 23 results in error:

<warning> app: System reset
<info> app_timer: RTC: initialized.
<warning> nrf_sdh_ble: Insufficient RAM allocated for the SoftDevice.
<warning> nrf_sdh_ble: Change the RAM start location from 0x20002300 to 0x20002C80.
<warning> nrf_sdh_ble: Maximum RAM size for application is 0x3D380.
<error> nrf_sdh_ble: sd_ble_enable() returned NRF_ERROR_NO_MEM.
<error> app: Fatal error

2) When updating to BLE_GAP_PHY_2MBPS getting again System reset

I am using Iphone 8 Plus to transfer data: on printing character maximumWriteValueLength i get value as 512

SDK: nRF5_SDK_16.0.0_98a08e2

Kit: nRF52840-DK

Am i correct thinking using queued write will be the fasted way to transfer data in volume? Is updating MTU, DLE not possible with it?

Please advice how i can make the data transfer faster?

  • 1) ATT MTU :  NRF_SDH_BLE_GATT_MAX_MTU_SIZE more than 23 results in error:

     You need to actually do these ram adjustments in your IDE settings. What do you use? Segger Embedded Studio?

     

    2) When updating to BLE_GAP_PHY_2MBPS getting again System reset

     What does the log say? Try to define DEBUG in your preprocessor definitions to see what the error handler points to.

    I just answered a very similar question. Check out the answer, and the project I attached in that ticket:

    https://devzone.nordicsemi.com/f/nordic-q-a/62363/nrf52832-throughput-test-with-nordic-uart-service

    Best regards,

    Edvin

  • I see currently this is the RAM settings in segger:

    FLASH_PH_START=0x0

    FLASH_PH_SIZE=0x100000

    RAM_PH_START=0x20000000

    RAM_PH_SIZE=0x40000

    FLASH_START=0x27000

    FLASH_SIZE=0xd9000

    RAM_START=0x20002300

    RAM_SIZE=0x3dd00

    From the link above attached project  \examples\nus_throughput\ble_app_uart\pca10056\s140\ses

    I get RAM settings as:

    FLASH_PH_START=0x0

    FLASH_PH_SIZE=0x100000

    RAM_PH_START=0x20000000

    RAM_PH_SIZE=0x40000

    FLASH_START=0x27000

    FLASH_SIZE=0xd9000

    RAM_START=0x20002bf0

    RAM_SIZE=0x3d410

    When i changed to this i get this error:


    <warning> app: System reset
    <info> app_timer: RTC: initialized.
    <warning> nrf_sdh_ble: Insufficient RAM allocated for the SoftDevice.
    <warning> nrf_sdh_ble: Change the RAM start location from 0x20002BF0 to 0x20002C80.
    <warning> nrf_sdh_ble: Maximum RAM size for application is 0x3D380.
    <error> nrf_sdh_ble: sd_ble_enable() returned NRF_ERROR_NO_MEM.
    <error> app: Fatal error

    Do you have a similar project for queued write?

    Please advice

  • You need to change the settings to what your log says:

    RAM_START=20002c80
    RAM_SIZE=0x3d380

    Use those values. And if you change something else later in your project, and you see that log message again, you must change the values in the log again.

    Just to let you know. Queued write is not intended for higher throughput. I would not recommend using it for your use case.

    If you are interested, queued write is intended if you want to change several characteristics at the same time. E.g. if you have a service containing characteristics that contains a heart rate and a time stamp, and these belong together, you can use queued write to update them simultaneously. It has nothing to do with throughput speed.

  • Thanks Edvin,

    It is working now i can transfer the data bit faster, but still it is taking 2.5 mins to pass 19KB of data. I was hoping to get at least 20-40 KBPS.

    I have been going through different posts and  have found following steps to increase the data transfer speed. Unfortunately there is no clear post which mentions code steps most of them are only describing the theory.

    Please see below the steps i have done to increase the the updated the code as follows:

    1) Updated the connections interval as:

    #define MIN_CONN_INTERVAL                MSEC_TO_UNITS(7.5, UNIT_1_25_MS)
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(500, UNIT_1_25_MS)

    2) Updated the config file to increase MTU and set the Length as 100


    #define NRF_SDH_BLE_GAP_EVENT_LENGTH 100
    #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247

    3) Updated the main to increase the Data length to 251 before advertise:

    In main set the 

    data_len_set(251);
    advertising_start(erase_bonds);
    void data_len_set(uint8_t value)
    {
        ret_code_t err_code;
        err_code = nrf_ble_gatt_data_length_set(&m_gatt, BLE_CONN_HANDLE_INVALID, value);
        APP_ERROR_CHECK(err_code);
    }


    4) In ble_evt_handler updated to use 2 MBPS

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



    Please point me in the right direction, Thanks
  • Ok, you are half the way there. What are you sending to/from? nRF in both ends?

    How do you actually send the 19kB of data? Can you show me a snippet of where the data is being sent? And what do you get in the callback gatt_evt_handler()? (or whatever you set as the callback function in nrf_ble_gatt_init().

    /**@brief Function for handling events from the GATT library. */
    void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
    {
        if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
        {
            m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
            NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
        }
        NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
                      p_gatt->att_mtu_desired_central,
                      p_gatt->att_mtu_desired_periph);
    }

    What is your m_ble_nus_max_data_len (or equivalent) after this callback?

    BR,

    Edvin

Related