How does the peripherals reconnect to central board when the BLE connection lost

Hello everyone, I am developing a system with multiple peripherals to a central board. How many peripherals can keep connecting with central at one time? I made some peripherals connected to a central board but after several hours, the connection of some peripherals lost and cannot reconnect to the BLE network. How can the peripherals reconnected to the central board? I have enlarge the timeout to 20s but it doesn't work. Any help will be appreciated. 

Parents
  • Hi Jared, thanks for your information. The peripheral boards will not advertise after disconnection. I use S140 for nRF52840 and NUS (Nordic UART Service ) to transfer the data. I think 20 links will be great. Which function did you implement in the project? How to configure the parameter for the multi-link to the central, such as advertising interval? Thanks.

Reply
  • Hi Jared, thanks for your information. The peripheral boards will not advertise after disconnection. I use S140 for nRF52840 and NUS (Nordic UART Service ) to transfer the data. I think 20 links will be great. Which function did you implement in the project? How to configure the parameter for the multi-link to the central, such as advertising interval? Thanks.

Children
  • Hi,

    How would the peripherals re-connect to the central if they never restart the advertising? 

    See this section for suggested connection interval and window.

    regards

    Jared 

  • Hi Jared, thank you for your reply. I checked the post you mentioned. I also checked other sections related to it. My project is about multi peripherals to two central. The firmware of the peripherals is based on ble_app_uart. The peripherals have timers and send data periodically to the central. But they can't send data in a stable order like the figure shown in the document because the timer of the peripherals is running independently. 

    When some peripherals did not set up links with the central, they will lose connection with the central. 

    What should I do about that? Thanks.

  • Hi,

    laumung said:

    But they can't send data in a stable order like the figure shown in the document because the timer of the peripherals is running independently. 

    Either way, they should only send during the connection interval?! Have you made sure that all of the connection have a common factor for their connection interval as explained in the documentation? What connection parameters are you using?

    laumung said:
    When some peripherals did not set up links with the central, they will lose connection with the central. 

    So they stop advertising after a set time? Try restarting the advertising periodically after some time.

    regards

    Jared 

  • Hi Jared, the peripherals in my project send data at a 20ms interval. The data should be sent to central during the connection interval. Here is the detailed code below.

    For peripherals:

    #define SAADC_SAMPLE_RATE               20                                         /**< SAADC sample rate in ms. */     
    
    // BLE connection parameter.
    #define APP_BLE_OBSERVER_PRIO           3                                           /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    
    #define APP_ADV_INTERVAL                64  //3000  //64                                  /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
    
    #define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    
    #define MIN_CONN_INTERVAL               MSEC_TO_UNITS(20, UNIT_1_25_MS)             //10 /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */ // VersionINote1: Purpose: change MIN_CONN_INTERVAL to 10ms and MAX_CONN_INTERVAL to 250. change the timing of the BLE transmission.
    #define MAX_CONN_INTERVAL               MSEC_TO_UNITS(75, UNIT_1_25_MS)            //1900  /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
    #define SLAVE_LATENCY                   0                                           /**< Slave latency. */
    #define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(20000, UNIT_10_MS)             /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
    #define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                       /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                      /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT    16   //3                                           /**< Number of attempts before giving up the connection parameter negotiation. */
    
    // Initialize saadc
    void saadc_init(void)
    {
        ret_code_t err_code;
    	
        nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
        saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
    	
        nrf_saadc_channel_config_t channel_0_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
        channel_0_config.gain = NRF_SAADC_GAIN1_4;
        channel_0_config.reference = NRF_SAADC_REFERENCE_VDD4;
    	
        nrf_saadc_channel_config_t channel_1_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
        channel_1_config.gain = NRF_SAADC_GAIN1_4;
        channel_1_config.reference = NRF_SAADC_REFERENCE_VDD4;
    	
        nrf_saadc_channel_config_t channel_2_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
        channel_2_config.gain = NRF_SAADC_GAIN1_4;
        channel_2_config.reference = NRF_SAADC_REFERENCE_VDD4;
    	
        nrf_saadc_channel_config_t channel_3_config =
            NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
        channel_3_config.gain = NRF_SAADC_GAIN1_4;
        channel_3_config.reference = NRF_SAADC_REFERENCE_VDD4;				
    	
        err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_saadc_channel_init(1, &channel_1_config);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_saadc_channel_init(2, &channel_2_config);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_saadc_channel_init(3, &channel_3_config);
        APP_ERROR_CHECK(err_code);	
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAADC_SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);   
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAADC_SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    }
    
    // Transmit data in SAADC function
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            ret_code_t err_code;
            uint16_t adc_value;
            uint8_t value[SAADC_SAMPLES_IN_BUFFER*2];
            uint16_t bytes_to_send;
         
            // set buffers
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAADC_SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
            err_code = ble_nus_data_send(&m_nus, d_tx_buf_1, &nus_length, m_conn_handle);       // VersionFNote1: Purpose: decrease the transfer array by 2. Remove the checking sum.
            if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_NOT_FOUND))
            {
                APP_ERROR_CHECK(err_code);
            }
        }
    }
    
    

    For central:

    //BLE Timing in sdk_config.h
    
    // <o> NRF_BLE_SCAN_SCAN_INTERVAL - Scanning interval. Determines the scan interval in units of 0.625 millisecond. 
    #ifndef NRF_BLE_SCAN_SCAN_INTERVAL
    #define NRF_BLE_SCAN_SCAN_INTERVAL 400      //160
    #endif
    
    // <o> NRF_BLE_SCAN_SCAN_DURATION - Duration of a scanning session in units of 10 ms. Range: 0x0001 - 0xFFFF (10 ms to 10.9225 ms). If set to 0x0000, the scanning continues until it is explicitly disabled. 
    #ifndef NRF_BLE_SCAN_SCAN_DURATION
    #define NRF_BLE_SCAN_SCAN_DURATION 0
    #endif
    
    // <o> NRF_BLE_SCAN_SCAN_WINDOW - Scanning window. Determines the scanning window in units of 0.625 millisecond. 
    #ifndef NRF_BLE_SCAN_SCAN_WINDOW
    #define NRF_BLE_SCAN_SCAN_WINDOW 200      // 80
    #endif
    
    // <o> NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL - Determines minimum connection interval in milliseconds. 
    #ifndef NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL
    #define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 7.5       //7.5
    #endif
    
    // <o> NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL - Determines maximum connection interval in milliseconds. 
    #ifndef NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL
    #define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 180      //30
    #endif
    
    // <o> NRF_BLE_SCAN_SLAVE_LATENCY - Determines the slave latency in counts of connection events. 
    #ifndef NRF_BLE_SCAN_SLAVE_LATENCY
    #define NRF_BLE_SCAN_SLAVE_LATENCY 0
    #endif
    
    // <o> NRF_BLE_SCAN_SUPERVISION_TIMEOUT - Determines the supervision time-out in units of 10 millisecond. 
    #ifndef NRF_BLE_SCAN_SUPERVISION_TIMEOUT
    #define NRF_BLE_SCAN_SUPERVISION_TIMEOUT 4000
    #endif
    
    void uart_event_handle(app_uart_evt_t * p_event)
    {
        static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
        static uint16_t index = 0;
        uint32_t ret_val;
    
        switch (p_event->evt_type)
        {
            /**@snippet [Handling data from UART] */
            case APP_UART_DATA_READY:
                UNUSED_VARIABLE(app_uart_get(&data_array[index]));
                index++;
                /*
                if ((data_array[index - 1] == '\n') ||
                    (data_array[index - 1] == '\r') ||
                    (index >= (m_ble_nus_max_data_len)))
                */
                if (index >= (m_ble_nus_max_data_len))
                
                {
                    NRF_LOG_DEBUG("Ready to send data over BLE NUS");
                    NRF_LOG_HEXDUMP_DEBUG(data_array, index);
    
                    NRF_LOG_INFO("Ready to send data over BLE NUS");
                    for(int c = 0; c < NRF_SDH_BLE_CENTRAL_LINK_COUNT; c++)
                    {
                        do
                        {
                            ret_val = ble_nus_c_string_send(&m_ble_nus_c[c], data_array, index);
                            if ( (ret_val != NRF_ERROR_INVALID_STATE) && (ret_val != NRF_ERROR_RESOURCES) )
                            {
                                APP_ERROR_CHECK(ret_val);
                            }
                        } while (ret_val == NRF_ERROR_RESOURCES);
                    }
                    index = 0;
                }
                break;
    
            /**@snippet [Handling data from UART] */
            case APP_UART_COMMUNICATION_ERROR:
                NRF_LOG_ERROR("Communication error occurred while handling UART.");
                APP_ERROR_HANDLER(p_event->data.error_communication);
                break;
    
            case APP_UART_FIFO_ERROR:
                NRF_LOG_ERROR("Error occurred in FIFO module used by UART.");
                APP_ERROR_HANDLER(p_event->data.error_code);
                break;
    
            default:
                break;
        }
    }
    
    
    /**@brief Function for handling characters received by the Nordic UART Service (NUS).
     *
     * @details This function takes a list of characters of length data_len and prints the characters out on UART.
     *          If @ref ECHOBACK_BLE_UART_DATA is set, the data is sent back to sender.
     */
    static void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len)
    {
        for (uint32_t i = 0; i < packet; i++)
        {
            app_uart_put( 0xAA );
            for(uint32_t j = 0; j < 16; j++ )
            {
                app_uart_put(p_data[ i*16 + j ]);
            }
            // nrf_gpio_pin_toggle(13);
        }
    }
    

    Are the parameter of my BLE connection correct? 

    For the second question, when to reconnection to the BLE network, after the connection is timeout? Thanks.

  • Hi,

    It depends on the number of peripherals that are going to be connected to the central. Did you try the multi-link central example that I linked in a previous reply?

    laumung said:
    For the second question, when to reconnection to the BLE network, after the connection is timeout? Thanks.

    You can restart it after a disconnection event in the ble event handler

    best regards

    Jared 

Related