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

Slow Transfer - Calling ble_nus_string_send multiple times to send a large array

Hi all,

I am using PCA10040 with nRF5_SDK_14.2.0 and using the ble_app_uart example.

Basically I have a large array of size 18750 to send out and having read on the forum, I understand that I need to split up the data into smaller chunks and call ble_nus_string_send multiple times. Most people manage to get it to work by splitting into chuck of 20 bytes.

What I have tried so far is that I can provide a 150 byte array into the ble_nus_string_send function without any problem and its receiving well on a mobile phone. I also made a few changes:

#define MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */

Inside the gatt_init function, I also increase the max MUT size to 247:

err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, 247);

This is what I did in the main function:

Each call to ble_nus_string_send, I am sending out 150 bytes, and I go this in a for loop that iterates for 125 times, so essentially I will transfer all 18750 bytes. After each call to ble_nus_string send, I am checking a flag tx_complete , which is set to true when a BLE_GATTS_EVT_HVN_TX_COMPLETE event happens. 


This is working well except that the transfer seems to be still fairly slow about 19-20 seconds to send everything over. Is there anything I am doing wrong? How can I make this go much more faster?

Parents
  • Hi all,

    Looks like my problem isn't entirely solved. I just found another issue. Here is my RTT log:

    0> <warning> nrf_sdh_ble: RAM starts at 0x20002A68, can be adjusted to 0x200025D0.
    0> <warning> nrf_sdh_ble: RAM size can be adjusted to 0xDA30.
    0> <info> app: UART Start!
    0> <debug> ble_gatt: Requesting to update ATT MTU to 64 bytes on connection 0x0.
    0> <debug> ble_gatt: Requesting to update data length to 251 on connection 0x0.
    0> <error> ble_gatt: sd_ble_gap_data_length_update() (request) on connection 0x0 returned unexpected value 0x13.
    0> <info> app: Connected
    0> <debug> ble_gatt: ATT MTU updated to 64 bytes on connection 0x0 (response).
    0> <info> app: Data len is set to 0x3D(61)
    0> <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0x40
    0> <debug> ble_gatt: Peer on connection 0x0 requested a data length of 123 bytes.
    0> <debug> ble_gatt: Updating data length to 123 bytes on connection 0x0.
    0> <debug> ble_gatt: Data length updated to 123 on connection 0x0.
    0> <debug> ble_gatt: max_rx_octets: 123
    0> <debug> ble_gatt: max_tx_octets: 123

    I presume that my Data Length has been increased to 123 bytes from the RTT log. Hence I am calling ble_nus_string_send() with a length of 100.

    I have a buffer of size 1880 and I am transferring 100 bytes per call to ble_nus_string_send. On the receiving side I have an android phone running nrf ToolBox and connected using the UART app. Looking at the log on the mobile app, I see that I am only getting 61 bytes in each notification and the remaining 39 bytes is lost. 

    Eg.

    first notification: buffer1[0] to buffer1[60] is received, buffer1[61] to buffer1[99] is lost.

    second notification: buffer1[100] to buffer1[160] is received, buffer1[161] to buffer1[199] is lost.

    I also tried to set the MUT to 100: 

    err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, 100);

    This is the RTT log:

    0> <warning> nrf_sdh_ble: RAM starts at 0x20002A68, can be adjusted to 0x200025D0.
    0> <warning> nrf_sdh_ble: RAM size can be adjusted to 0xDA30.
    0> <info> app: UART Start!
    0> <debug> ble_gatt: Requesting to update ATT MTU to 100 bytes on connection 0x0.
    0> <debug> ble_gatt: Requesting to update data length to 251 on connection 0x0.
    0> <error> ble_gatt: sd_ble_gap_data_length_update() (request) on connection 0x0 returned unexpected value 0x13.
    0> <info> app: Connected
    0> <debug> ble_gatt: ATT MTU updated to 100 bytes on connection 0x0 (response).
    0> <info> app: Data len is set to 0x61(97)
    0> <debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0x64
    0> <debug> ble_gatt: Peer on connection 0x0 requested a data length of 123 bytes.
    0> <debug> ble_gatt: Updating data length to 123 bytes on connection 0x0.
    0> <debug> ble_gatt: Data length updated to 123 on connection 0x0.

    Now on the android app, I am receiving 97 bytes and losing 3 bytes for each notification call.

    I don't understand why. Can anyone help advise? And how can I solve this problem?

  • Looks suspiciously like the old bug (feature) in gatt_init(), as 61 = 64-3. I saw this a while back, perhaps there is similar code on the central end

Reply
  • Looks suspiciously like the old bug (feature) in gatt_init(), as 61 = 64-3. I saw this a while back, perhaps there is similar code on the central end

Children
  • Hi hmolesworth,

    I made the changes you suggested and it worked! Thanks a lot! I wonder why the default example had the MUT size set to 64 and not to NRF_SDH_BLE_GATT_MAX_MTU_SIZE. That would have not caused so much confusion. 

    Thanks a lot for the advise. Appreciate it!