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

How to achieve max throughput with NUS service?

Hi All.

I have a project where my peripheral (nRF52832) connects to my central (nRF52840), and then transmits 128 byte packets continuously one after the other. It works ok, but data rate is about 5,000 bytes per second max (40,000 bps). This seems a little low. I am using the following event to trigger the message, so this should be the quickest way to send one after the other?

case BLE_NUS_EVT_TX_RDY:

            send_data();

            break;

Send data;

void send_data(void)
{
    uint8_t testData[128];
    ret_code_t err_code;

    for (uint8_t i = 0; i < 128; i++) {
       testData[i] = i;
    }
    testData[0] = P0;
    testData[1] = P1;
    testData[2] = P2;
    testData[3] = page_count;


    //TODO - Add something here so if it fails X number of times, we stop download and disconnect 
    uint16_t length = (uint16_t)128;
    err_code = ble_nus_data_send(&m_nus, testData, &length, m_conn_handle);
    if(err_code == NRF_SUCCESS)
    {
      P1++;
      if(P1 == 0) P2++;
      page_count--;
    }
}

Also here are my settings for the radio times which seem to give the best results (same on both central and peripheral);

#define MIN_CONNECTION_INTERVAL   MSEC_TO_UNITS(7.5, UNIT_1_25_MS)      /**< Determines minimum connection interval in milliseconds. */
#define MAX_CONNECTION_INTERVAL   MSEC_TO_UNITS(10, UNIT_1_25_MS)       /**< Determines maximum connection interval in milliseconds. */
#define SLAVE_LATENCY             0                                     /**< Determines slave latency in terms of connection events. */
#define SUPERVISION_TIMEOUT       MSEC_TO_UNITS(4000, UNIT_10_MS)       /**< Determines supervision time-out in units of 10 milliseconds. */

#ifndef NRF_SDH_BLE_GAP_DATA_LENGTH
#define NRF_SDH_BLE_GAP_DATA_LENGTH 251
#endif

// <o> NRF_SDH_BLE_PERIPHERAL_LINK_COUNT - Maximum number of peripheral links. 
#ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT
#define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1
#endif

// <o> NRF_SDH_BLE_CENTRAL_LINK_COUNT - Maximum number of central links. 
#ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT
#define NRF_SDH_BLE_CENTRAL_LINK_COUNT 0
#endif

// <o> NRF_SDH_BLE_TOTAL_LINK_COUNT - Total link count. 
// <i> Maximum number of total concurrent connections using the default configuration.

#ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT
#define NRF_SDH_BLE_TOTAL_LINK_COUNT 1
#endif

// <o> NRF_SDH_BLE_GAP_EVENT_LENGTH - GAP event length. 
// <i> The time set aside for this connection on every connection interval in 1.25 ms units.

#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH
#define NRF_SDH_BLE_GAP_EVENT_LENGTH 6
#endif

// <o> NRF_SDH_BLE_GATT_MAX_MTU_SIZE - Static maximum MTU size. 
#ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE
#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247

I don't really understand the above settings to be honest, but from what I have read should give the best throughput. However 40kbps seems a bit slow considering both ends are nRF52 devices?

Thanks

Phil

Parents
  • Hi Phil

    The SoftDevice team wrote a nice guide on how to set connection parameters and stack configuration properly for good throughput, and I would suggest reading through that first. 

    The guide is available here

    If something is still unclear after reading through it just let me know, and I will do my best to help Slight smile

    Best regards
    Torbjørn

  • Thanks Torbjørn, I will take a look at that guide.

    I managed to boost the speed a fair bit by calling "ble_nus_data_send" in a while loop until its response doesn't equal NRF_SUCCESS rather than just once in the BLE_NUS_EVT_TX_RDY event.

    Ill try some other tweeks once I have read the guide.

    Thanks

    Phil

  • Hi Philip 

    You should definitely be able to get more than one packet pr connection interval. 

    Do you make sure to call ble_nus_data_send(..) in a loop (until it returns an error) every time the BLE_NUS_EVT_TX_RDY event occurs?

    Maybe you can share the code you implemented for doing this?

    Best regards
    Torbjørn

  • Hi, yes here is my send_data function, and also where it is called;

    void send_data(void)
    {
        uint8_t swimData[244];
    
        uint8_t test_counter = 0;
    
        ret_code_t err_code;
    
        //TODO - Add something here so if it fails X number of times, we stop download and disconnect 
        uint16_t length = (uint16_t)240;
    
        err_code = NRF_SUCCESS;
    
        test_counter = 0;
    
        while (err_code == NRF_SUCCESS & page_count != 0)
        {
            //TODO - Commented the read out to get throughput result without the delay of this.
            //Read_Data(240, P0, P1, P2, swimData); //start writing at byte 1 rather than 0. This means there are 5 bytes we can overwrite
    
            swimData[0] = test_counter;
            swimData[1] = P1;
            swimData[2] = P2;  //test_counter to see how many times this loops before failing
    
            //Have to send this so central knows when it has received the last packet of data i.e. page_count gets to zero
            swimData[3] = GET_HI_CHAR(page_count);
            swimData[4] = GET_LO_CHAR(page_count);
    
    test_counter++;
            err_code = ble_nus_data_send(&m_nus, swimData, &length, m_conn_handle);
            
            if(err_code == NRF_SUCCESS)
            {
              nrf_gpio_pin_toggle(TEST_PIN); //TODO - Test toggle this when sending so we can monitor with scope
    
              P1++;
              if(P1 == 0) P2++;
              page_count--;
            }
        }
    }

    And called from;

            case BLE_NUS_EVT_TX_RDY:
                //Try sending data here
    
                if(downloading == true & page_count != 0)
                {
                    send_data();
                }

    I thought maybe NRF_SDH_BLE_GAP_EVENT_LENGTH (which is 6) is not big enough to get another packet in the 10mS slot, so am trying to increase that also / experiment.

    Thanks

    Phil

  • Also, my central min a max connection interval is 7.5 and 10. My peripheral is 7.5 and 100.

    If I change my central intervals to 20 and 30 for example, no messages are sent.

    Seems like the setup I have can not be adjusted at all without it not working.

  • Update: Managed to get to 491Kbps which will be good enough for my application. Was able to update the min max connection times to 75 - 100, and the NRF_SDH_BLE_GAP_EVENT_LENGTH to 60. This seems to push a lot more packets through in each time slot.

    I think maybe with NRF_SDH_BLE_GAP_EVENT_LENGTH  = 6, the softdevice just did one packet per connection interval. 

  • Hi Philip

    An event length of 6 equals 7.5ms, which should be enough for a couple of packets, but there might be some overhead at the start and end of the event.

    You are sending packets of 240 bytes in length?

    Which phy are you using?

    Did you figure out the issue when setting the connection interval to 20 and 30?

    Best regards
    Torbjørn

Reply Children
Related