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

nrf52832 notification limitations

I am unable to get 6 notifications per connection event. I am connecting two nrf32832's, one as a central, one as a peripheral. To make this as simple as possible, I limited the setup to just one peripheral though in reality I have many.

#########################################################

On my central side I have the following:

SDK 14.1.0

SD 132 v 5.0.1

#define NRF_SDH_BLE_TOTAL_LINK_COUNT        1

#define NRF_SDH_BLE_CENTRAL_LINK_COUNT        1

#define NRF_SDH_BLE_GAP_EVENT_LENGTH     50

#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE     23

#define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE   4096

connection interval is 60ms

##########################################################

On my peripheral side I have:

SDK 13.1.0

SD 132 

Min conn int 7.5 ms 

max conn int 300 ms

##########################################################

I am sending 12 byte packets as hvx notifications until its full. I am logging 2 things:
1. number of successfully queued packets before the gatts_hvx call fails to insert -> this returns 4

2. the number of successfully sent packets per second -> it should be near 100 / sec (1000 ms / 60 ms * 6 packets = 100 packets / second). I'm getting ~60 which confirms the queue is only 4 deep.

I have read every forum entry on the topic to no avail. any places to try?

  • Hi.

    Try to increase the NRF_SDH_BLE_GAP_EVENT_LENGTH, as explained in this question.

    Best regards,

    Andreas

  • I have read this question before posting. It does not answer my fundamental question. 

    according to this document, in section 15.10 I see the following 

    "When long Link Layer Data Channel PDUs are in use, it is recommended to increase the event length of a connection. For example, Link Layer Data Channel PDUs are by default 27 bytes in size. With an event length of 3.75 ms, it is possible to send three full sized packet pairs on LE 1M PHY in one connection event. "

    If its possible for a 3.75ms window to send 3 27 byte packets then a 62.5 ms window should be easily able to send 6 packets. 

    I tested earlier and confirmed. with my gap event length at 7.5 ms I can place 4 items in the queue and I see an effective bandwidth of ~60 packets per second. when I increase my gap event length to the aforementioned 62.5ms I see no difference in bandwidth. 

    So why am I maxed out a 4 packets in my queue? Are there any other levers I can pull in software?

  • Hi.

    Sorry for the late answer. Have you gotten any any returns when you "maxed" out the queue? If the queue is full you should get the return NRF_ERROR_RESOURCES.

    The application can keep track of the available queue element count for notifications by following the procedure below:

    - Store initial queue element count in a variable.
    - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns NRF_SUCCESS.
    - Increment the variable, which stores the current available queue element count, by the count variable in BLE_GATTS_EVT_HVN_TX_COMPLETE event.

    Best regards,

    Andreas

  • Hi Andreas - 

    yes, this is my approach. heres a snippet of my code.

    just to reiterate, my question is, why can i only put 4 elements into the HVX queue?

    thanks,

    Ryan

    struct test_data {                                                                 
        uint8_t data[18];                                                              
    };                                                                                 
                                                                                       
    void send_data(void)                                                               
    {                                                                                  
                                                                                       
        static uint32_t count = 0;                                                     
        struct test_data test_data;                                                    
        memset(&test_data, 0, sizeof(test_data));                                      
                                                                                       
        while(1)                                                                       
        {                                                                              
                                                                                       
            test_data.data[0] = count & 255;                                           
                                                                                       
            uint16_t len = sizeof(struct test_data);                                
            ble_gatts_hvx_params_t hvx_params =                                     
            {                                                                       
                .handle = get_value_handle(),                  
                .type = BLE_GATT_HVX_NOTIFICATION,                                  
                .p_len = &len,                                                      
                .p_data = (uint8_t *)&test_data,                                    
            };                                                                      
                                                                                    
                                                                                    
            uint32_t ret = sd_ble_gatts_hvx(conn_handle, &hvx_params);              
                                                                                    
            if (ret == NRF_SUCCESS)                                                 
            {   
                static uint32_t last_update_sec = 0;                                
                static uint32_t last_update_count = 0;                              
                                                   
                /* get ms since boot */                                                                    
                uint32_t time = ms_counter_get_ticks();                             
                                                                                    
                if ((time / 1000) != last_update_sec)                               
                {                                                                   
                    NRF_LOG_INFO("%d samples sent in last second\n",                
                                 count - last_update_count);                        
                                                                                    
                    last_update_sec = time / 1000;                                  
                    last_update_count = count;                                      
                }                                                                   
                                                                                    
                count++;                                                            
            }                                                                       
            else                                                                    
            {                                                                       
                //NRF_LOG_INFO("buffer full? [%d]\n", ret);                         
                break;                                                              
            }                                                                       
        }                                                                           
    }                                                    
                                                                
    void inertial_data_evt_handler(ble_evt_t *p_ble_evt)                            
    {                                                                               
        uint16_t evt_id = p_ble_evt->header.evt_id;                                 
                                                                                    
        switch (evt_id)                                                             
        {              
            // ...
            
            case BLE_GATTS_EVT_HVN_TX_COMPLETE:                                     
                if (notifications_enabled)                                          
                {                                                                   
                    send_data();   
                }
                break;
                
            // ...
        }
    }
            

  • Hi.

    Could you try to force the minimum guaranteed number of Handle Value Notifications that can be queued for transmission?

    And also set offset = 0 for hvx_params?

            ble_gatts_hvx_params_t hvx_params;
    		ble_gatts_conn_cfg_t 		queue_size;
            memset(&hvx_params, 0, sizeof(hvx_params));
    		memset(&queue_size, 0, sizeof(queue_size));
            len = sizeof(uint8_t);
    				
    		queue_size.hvn_tx_queue_size = 6;
            ble_gatts_hvx_params_t hvx_params =                                     
            {                                                                       
                .handle = get_value_handle(),                  
                .type = BLE_GATT_HVX_NOTIFICATION,
                .offset = 0,                                 
                .p_len = &len,                                                      
                .p_data = (uint8_t *)&test_data,                                    
            };                                                                      
                 

    Best regards,

    Andreas

Related