Having problem with low message rate with BLE Nus Service, help please.

Hello everyone, i am developing a board based on the nRF52832 microcontroller SDK v16.0.0 and sd132 for sending data of a sensor over BLE to a mobile APP. For this i am using the Nordic Uart Service but i am getting bad performance for it. 

I started from the ble_peripheral_app and then added Nus service, i run a simple test to know the maximun message rate that i can have that work like this:

In main:

uint8_t message = 1;
uint16_t message_lenght = 1;
while(true){

    if(ble_nus_tx_is_ready()){}
        send_nus_data(&message, message_lenght);
        message++;
    }
    
}

In the ble file (i separate the ble module from main) i have this function:

void send_nus_data(uint8_t *buf, uint16_t size)
{
    tx_char_bussy = true;
    ble_nus_data_send(&m_nus, buf, &size, m_conn_handle);
}



And the next line on the nus event handler to update the bussy flag of the nus TX char:
static void nus_evt_handler(ble_nus_evt *p_evt)
{
    if(p_evt->type == BLE_NUS_EVT_TX_RDY){
        tx_char_bussy = false;
    }
}


Of course i have more code but i just show you the important parts so you can understand how the test work. So is run this test for 4 Seconds (I use an App timer of 4000 milliseconds to stop the test) and i only get in average 15 messages per second wich i think is very low, if i send messages of 20 bytes lenght i will get 300bps, i dont understand what is wrong because i was specting a lot more messages. Here are some important parameters that i am using for the BLE instance:

#define APP_ADV_INTERVAL                300                                     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */

#define APP_ADV_DURATION                18000                                   
#define APP_BLE_OBSERVER_PRIO           3                                       
#define APP_BLE_CONN_CFG_TAG            1                                       

#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(7.5, UNIT_1_25_MS)      
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(30, UNIT_1_25_MS)        
#define SLAVE_LATENCY                   0                                       
#define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)         

#define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                  
#define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                  
#define MAX_CONN_PARAMS_UPDATE_COUNT    3                                       

_____________________________________________________
/* SDK config related: */

#define NRF_SDH_BLE_GAP_DATA_LENGTH 27
#define NRF_SDH_BLE_GAP_EVENT_LENGTH 6
#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 23
_____________________________________________________
/* Clock: */
#define NRF_CLOCK_LFCLKSRC      {.source        = NRF_CLOCK_LF_SRC_XTAL,            \
                                 .rc_ctiv       = 0,                                \
                                 .rc_temp_ctiv  = 0,                                \
                                 .accuracy =    NRF_CLOCK_LF_ACCURACY_20_PPM}


I hope the information provided is enough to see the problem, if more information is needed please tell me.



  • Hi Yeyzz, 

    I assume the function ble_nus_tx_is_ready() will just return the value of tx_char_bussy ? 

    Please note that the softdevice have several buffer slots to queue multiple message. So you would need to call send_nus_data() multiple times until you receive NRF_ERROR_RESOURCE meaning the buffer is full. 
    Similarly, when you receive BLE_NUS_EVT_TX_RDY (BLE_GATTS_EVT_HVN_TX_COMPLETE event) you may want to check how many packets have been sent (check the count variable inside ble_gatts_evt_hvn_tx_complete_t) then you can queue the same number of packets to the softdevice. Or you can just call send_nus_data() multiple times until it's full again. 

    If you can capture a sniffer trace and send to us we would be able to point out what you need to do to improve the throughput. 

  • Update: I had a significant improvement changing the maximun connection interval to MSEC_TO_UNITS(10, UNIT_1_25_MS)and get an average of 40 messages per second,  it seems like the maximun connection interval is the dominant for the peripheral,  but i am still not sure if is a good thing having the maximun connection interval this low,  i was thinking that the nrf can send multiple messages every interval but it seems it only can send one or less than one. 

  • Yes, ble_nus_tx_is_ready() just return the tx_char_bussy bool. I was thinking in use the BLE_NUS_EVT_TX_RDY because the purpose of the board is stream data over long period of time, so if i constantly queue messages i can have a buffer overflow and loss data.

  • Hi again, 
    Yes the BLE stack can send multiple packets on every interval, as long as you can fully fill the buffer of the stack. And also the central need to support multiple packets per connection interval (most centrals support that)

  • Now i see what i am doing wrong, if i understand everything well, every interval the BLE stack send multiple packets and when a interval finish then a event with the BLE_NUS_EVT_TX_RDY occurs right? Right now i am sending one message and set a flag of Tx bussy, and dont send another message until BLE_NUS_EVT_TX_RDY occurs (where i reset the tx_bussy_flag), so basically i am sending 1 message per interval. I think the way to get the best performance is set the tx_bussy_flag when "ble_nus_data_send" return the error meaning the buffer is full.

Related