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

Can not (How to) send more than one packet in one connection interval

Hi, Community!

My development environment is the following:

  • SDK52,
  • nRF52840,
  • s140 17.2.0
  • nRF Sniffer

My problem is that I can not seem to be able to send more than one packet per connection interval. I have two nRF52840 devices that negotiate a 7.5 ms connection interval and I set aside 6 units for the NRF_SDH_BLE_GAP_EVENT_LENGTH. I have enabled DLE 251 and ATT MTU 247. I have also enabled the 2 M PHY speed. According to calculations, these parameters should result in 2-5 packets per connection interval. After the negotiation, the peripheral starts to send 244-byte chunks of data to the master, in a continuous loop. The code in main() is the following:

// Enter main loop.
    for (;;)
    {
        //If everything is negotiated correctly, start sending the messages.
        if (phy_negotiated == true && conn_interval_negotiated == true )
        {
            //The length of a message
            uint16_t length = 244;
            
            for (int i=0; i<1000; i++)
            {
                //Change between two different arrays every other time
                if (i%2 == 0)
                {
                    //Array filled with the value 'A'
                    p_byte_array = byte_array_A;
                }
                else
                {
                    //Array filled with the value 'B'
                    p_byte_array = byte_array_B;
                }
                do
                {
                        //Send selected array
                      err_code = ble_nus_data_send(&m_nus, p_byte_array, &length, m_conn_handle);
  
                      if ((err_code != NRF_ERROR_INVALID_STATE) &&
                          (err_code != NRF_ERROR_RESOURCES) &&
                          (err_code != NRF_ERROR_NOT_FOUND))
                      {
                          APP_ERROR_CHECK(err_code);
                      }

                } while (err_code == NRF_ERROR_RESOURCES);
            }
        }

        idle_state_handle();
    }

When I observe the communication with the nRF Sniffer in Wireshark, I can see that only one packet is sent per connection interval. I tested to raise the interval to 300 ms and NRF_SDH_BLE_GAP_EVENT_LENGTH to 240 units (=300 ms), yet still there is only one packet sent. Here is a snippet:

One message per connection interval

As you can see in the picture, the master opens the connection interval with a 44 us (2 M PHY) packet at every ~300.000 us. This is because I had set the interval to 300 ms. There after, the slave answers with a 251-byte packet that takes 1048 us, which is expected. However, the "More Data" column shows "False" which results in the closing of the connection interval.

What could be the problem? Please help me find a solution!

Parents
  • Hi,

    Could you log how often ble_nus_data_send() returns NRF_SUCCESS ?

    Try to set the hvn_tx_queue_size directly as well, and see if it improves anything, snippet:

    /**@brief Function for the SoftDevice initialization.
     *
     * @details This function initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        ble_cfg_t ble_cfg;
        memset(&ble_cfg, 0, sizeof(ble_cfg));
        ble_cfg.conn_cfg.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
        ble_cfg.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = 10;
    
        err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_cfg, ram_start);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_CONN_CFG_GATTS.",
                          nrf_strerror_get(err_code));
        }
    
    
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }

    And also try to enable Connection Event Length Extension, snippet:

        ret_code_t err_code;
        ble_opt_t  opt;
    
        memset(&opt, 0x00, sizeof(opt));
        opt.common_opt.conn_evt_ext.enable = 1;
    
        err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
        APP_ERROR_CHECK(err_code);

  • Hi, I have added your suggestion to my code like so:

    static void ble_stack_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
        
        //ATTENTION code added:
        ble_cfg_t ble_cfg;
        memset(&ble_cfg, 0, sizeof(ble_cfg));
        ble_cfg.conn_cfg.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
        ble_cfg.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = 10;
    
        err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_cfg, ram_start);
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_CONN_CFG_GATTS.",
                          nrf_strerror_get(err_code));
        }//END
    
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        //Im enabling the connection event extension:
        ble_opt_t  opt;
        memset(&opt, 0x00, sizeof(opt));
        opt.common_opt.conn_evt_ext.enable = 1;
        err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
        APP_ERROR_CHECK(err_code); 
        //END
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    

    However, there is no difference in my sniffer log, unfortunately. 

    I have declared two counter variables in the message sending loop, success_cntr and fail_counter. I attempt to send 1000 messages and count number of successes and failures. After 1000 messages, I clear the counters and start over. Here is the log:

    sending fails vs successes

  • Did you change NRF_SDH_BLE_GAP_EVENT_LENGTH on the central as well?

    Can you save and upload the sniffer log here?

Reply Children
  • Did you change NRF_SDH_BLE_GAP_EVENT_LENGTH on the central as well?

    It is set to 6 units (=7.5 ms) on both sides, and the connection interval is also 7.5 ms.

    It is worth mentioning that it is the ble_app_uart examples for central and peripheral in the SDK that I am modifying, so in theory it shouldn't be difficult to describe step-by-step, what modifications should be done to achieve my goal.

    Some interesting revelations: I have run some test with different application message sizes. My ATT MTU is still 247 but my application is set to send 20 / 128 / 150 / 180 / 200-byte messages. The results show that multiple messages are sent within every connection interval, if the app message size were 20 / 128 / 150. Here is the Sniffer log when the application message contains 150 bytes:

    Sniffer log for 150 byte msg

    You can see that it sends 4-5 messages in every interval.

    When the application messages were 180 bytes or above, I get a sniffer log similar to what I reported earlier, i.e. one message per connection interval. Here is the Sniffer log for 180-byte application messages:

    Sniffer log for 180 byte msg

    Here it shows that mostly only one message gets sent per interval.

Related