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

central and peripheral mode connection disconnecting in nrf52840

hai ,

   in my apllication i am using nrf52840 , i merged a code code of peripheral and central (app_blinky example)

i need to connect a peripheral to central (with esp32 ), i can able to connect.

i should with connect with another nrf ( which acts as peripheral) for this ,i need to switch mode from peripheral to central .

and now question is ,

in my merged code , it should connected with esp32 and when i send a message it sholud connect with another nrf at that time it should not lose connection with esp32 .

how to connect without disconnecting from another mode ??

Parents
  • Hi.

    I suggest that you take a look at the BLE Multi-link Example.

    The BLE Multi-link Central example application shows how one central can be connected to several peripherals simultaneously.

    Br,
    Joakim

  • actually my application is  with esp32(A) , relay_NRF(B) , nrf(C)

    relay(B) - merged code (with central and peripheral)

    STEP 1 : A and B DEVICE should be always in connected mode 

    1. in this ESP32- A(acts as central ) and relay _NRF- B(in peripheral mode )

    STEP 2 :  a data should send from A TO B , then B (relay_NRF )should connect with NRF - C(peripheral) from central mode in relay(B) without disconnecting from ESP32 (A).

    Is it possible to always connect with ESP32(A) as well relay_NRF should connect with another NRF - C(which is peripheral)??

    if you have any code kindly share the code ..

    Thank you

  • Yes, it is possible to do this.

    The S140 softdevice supports up to 20 concurrent connections.
    We already have sample code for this in our nRF5 SDK. You can take a look at the Multi-link example is referred to in my last reply or the relay example.
    Relay example:
    "The application combines a collector part on one end and a sensor part on the other to show how the SoftDevice can be used to make a device simultaneously function as central and peripheral device. "

  • hello,

    i tried with ble app-blinky example merged with central and peripheral.

    at first i can able to connect with ESP32(A - acts as central) and RELAY (B - acts as peripheral role)

    then i send a message from ESP32(A) TO RELAY(B) 

    When its get the message from esp32(A) then RELAY (B - already in peripheral role now after getting message i need to switch over the role to central ) to connect with another NRF(C -acts as peripheral)

    after this message should pass to NRF(C) then when C gives a acknowledgment to RELAY(B - again switch to Peripheral mode ) to connect with ESP32(A)

    for this , every time i am disconnect the role using 

    err_code = sd_ble_gap_disconnect(m_conn_handle,
    BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION);

    but sometimes its not getting disconnecting gives me a fatal error.

    i am searching to connecting the modes without disconnecting the roles every time.

    can you please explain me how to work on this???

    int main(void)
    {
     ret_code_t err_code;
        // Initialize.
         log_init();
         leds_init();
          timers_init();
     power_management_init();
        ble_stack_init();
     
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
       conn_params_init();
     
         db_discovery_init();
         lbs_c_init();
    
        // Start execution.
        NRF_LOG_INFO("Blinky example started pheriperal.");
        advertising_start();
    
        // Enter main loop.
        for (;;)
        {
       idle_state_handle();
    
        }
    }
    

    //ble stack initiate
    
    static void ble_stack_init(void)
    {
    //printf("ble_stack_init\n");
        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);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
    
         // Register handlers for BLE and SoC events.
         NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
        NRF_SDH_BLE_OBSERVER(m_ble_observer_re, APP_BLE_OBSERVER_PRIO, ble_evt_handler_relay, NULL);
       
    }
    
    

    event handler  for peripheral using flag to  play each role

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
          if(periperal_central_role == false)
          { 
    
            // printf("inside peripheral role----\n");
               on_ble_peripheral_evt(p_ble_evt);
    
           }
    
          else if(periperal_central_role == true)
           {
            // printf("inside Central role----\n");
               on_ble_central_evt(p_ble_evt);
    
           }
           
    
    

    at first it should go to on_ble_peripheral_evt() to connect with esp32

     void on_ble_peripheral_evt(ble_evt_t const * p_ble_evt)
    {
        ret_code_t err_code;
      //  printf("peripheral event handler\n");
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
               NRF_LOG_INFO("Connected with peripheral--------");
               scan_start();
              
          //   NRF_LOG_INFO("BLE peroi %d", p_gap_evt->params.connected.role);  
               // bsp_board_led_on(CONNECTED_LED);
               // bsp_board_led_off(ADVERTISING_LED);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                 data_ret_fun();
                err_code = app_button_enable();
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected peri-------");
                bsp_board_led_off(CONNECTED_LED);
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                err_code = app_button_disable();
                APP_ERROR_CHECK(err_code);
                advertising_start();
                break;
    
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                       BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
                                                       NULL,
                                                       NULL);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                // No system attributes have been stored.
                err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
           case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
    
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;  
    
            default:
             
      
                // No implementation needed.
                break;
        }
    }
    

    once connect getting message from esp32 and then switch over to central role to connect with another device - NRF(C - acts as peripheral) here i have shown how i disconnected and connecting to device (c)  , i tried without disconnecting from peripheral role used  ble_gap_connect fun to connect with device (c) but its not worked , when disconnect using ble_gap_disconnect.

    after i scan_init AND on_ble_central_evt - its connected with DEVICE NRF(C)

    static void led_write_handler(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t *data_ptr,ble_evt_t const * p_ble_evt)
    {
                chk_flag = true;
       
               ret_code_t err_code;
    
              printf("DATA:%s\n",data_ptr);
    
                  process_msg(data_ptr) ;     
    
     if(periperal_central_role == false && chk_flag == true) 
     {
      periperal_central_role = true;
             printf("inside fun call of central\n");
    /* err_code = sd_ble_gap_connect(p_addr,
                                      p_scan_params,
                                      p_conn_params,
                                      con_cfg_tag); */
    
    
             ret_code_t err_code;
              err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    
     if(err_code  ==  NRF_SUCCESS)
      {
     printf("sucess\n");
    
    
     scan_init();  
      
     on_ble_central_evt(p_ble_evt);
    
     }
    i am geting a mac id of devcie(C) from the message got from esp32 , then with the mac id i have to connect with device (C), for this connection i used the below fun

     void scan_init(void)
    {
        ret_code_t          err_code;
        nrf_ble_scan_init_t init_scan;
    
        memset(&init_scan, 0, sizeof(init_scan));
    if(periperal_central_role == true)
    {
    printf("inside central scan\n");
        init_scan.connect_if_match = true;
        init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
    
    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler_central);
        APP_ERROR_CHECK(err_code);
       
    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_ADDR_FILTER, m_addr);
        APP_ERROR_CHECK(err_code);
             if(err_code == NRF_SUCCESS)
        {
         printf("nrf_ble_scan_filter_set\n");
        }
        else
        {
         printf("nrf_ble_scan_filter_notttttt ok-----\n");
        }  
    
         err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_ADDR_FILTER, false);
        APP_ERROR_CHECK(err_code);
          if(err_code == NRF_SUCCESS)
        {
         printf("nrf_ble_scan_filters_enable\n");
        }
        else
        {
         printf("nrf_ble_scan_not ok-----\n");
        }
    }
    else if(periperal_central_role == false)
    {
     printf("inside periperal scan\n");
          init_scan.connect_if_match = false;
        init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
        init_scan.p_scan_param     = &m_scan_param;
        err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler_peri);
        APP_ERROR_CHECK(err_code);
    
    }
       
    }
    

    when getting the ack from DEVICE (C) I switching over the role to peripheral in RELAY(B)

    void central_msg_handler(void * p_context)
    {
    ret_code_t err_code;
    printf("handle -------centrl---\n");
    err_code = ble_lbs_led_status_send(&m_ble_lbs_c, button_action);
    if (err_code != NRF_SUCCESS &&
    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
    err_code != NRF_ERROR_INVALID_STATE)
    {

    sprintf(collect_data, "{\"MSTS\":\"%s\",\"MAC\":\"%02X%02X%02X%02X%02X%02X\"}","0", m_addr_c[0], m_addr_c[1],
    m_addr_c[2], m_addr_c[3],
    m_addr_c[4], m_addr_c[5]);
    coaster_msg_suc = true ;
    APP_ERROR_CHECK(err_code);
    printf("data ret %s\n",collect_data);
    }
    if (err_code == NRF_SUCCESS)
    {
    coaster_msg_suc = true ;
    sprintf(collect_data, "{\"MSTS\":\"%s\",\"MAC\":\"%02X%02X%02X%02X%02X%02X\"}","1", m_addr_c[0], m_addr_c[1],
    m_addr_c[2], m_addr_c[3],
    m_addr_c[4], m_addr_c[5]);
    printf("data ret %s\n",collect_data);
    printf("sucess return------------\n");

    }
    mode_chnage_peripheral();
    }

    void mode_chnage_peripheral()
    {


    ret_code_t err_code;
    err_code = sd_ble_gap_disconnect(m_conn_handle,
    BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION);err_code = sd_ble_gap_adv_stop(m_adv_handle);

    }

Reply
  • hello,

    i tried with ble app-blinky example merged with central and peripheral.

    at first i can able to connect with ESP32(A - acts as central) and RELAY (B - acts as peripheral role)

    then i send a message from ESP32(A) TO RELAY(B) 

    When its get the message from esp32(A) then RELAY (B - already in peripheral role now after getting message i need to switch over the role to central ) to connect with another NRF(C -acts as peripheral)

    after this message should pass to NRF(C) then when C gives a acknowledgment to RELAY(B - again switch to Peripheral mode ) to connect with ESP32(A)

    for this , every time i am disconnect the role using 

    err_code = sd_ble_gap_disconnect(m_conn_handle,
    BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION);

    but sometimes its not getting disconnecting gives me a fatal error.

    i am searching to connecting the modes without disconnecting the roles every time.

    can you please explain me how to work on this???

    int main(void)
    {
     ret_code_t err_code;
        // Initialize.
         log_init();
         leds_init();
          timers_init();
     power_management_init();
        ble_stack_init();
     
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
       conn_params_init();
     
         db_discovery_init();
         lbs_c_init();
    
        // Start execution.
        NRF_LOG_INFO("Blinky example started pheriperal.");
        advertising_start();
    
        // Enter main loop.
        for (;;)
        {
       idle_state_handle();
    
        }
    }
    

    //ble stack initiate
    
    static void ble_stack_init(void)
    {
    //printf("ble_stack_init\n");
        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);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
    
         // Register handlers for BLE and SoC events.
         NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
        NRF_SDH_BLE_OBSERVER(m_ble_observer_re, APP_BLE_OBSERVER_PRIO, ble_evt_handler_relay, NULL);
       
    }
    
    

    event handler  for peripheral using flag to  play each role

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
          if(periperal_central_role == false)
          { 
    
            // printf("inside peripheral role----\n");
               on_ble_peripheral_evt(p_ble_evt);
    
           }
    
          else if(periperal_central_role == true)
           {
            // printf("inside Central role----\n");
               on_ble_central_evt(p_ble_evt);
    
           }
           
    
    

    at first it should go to on_ble_peripheral_evt() to connect with esp32

     void on_ble_peripheral_evt(ble_evt_t const * p_ble_evt)
    {
        ret_code_t err_code;
      //  printf("peripheral event handler\n");
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
               NRF_LOG_INFO("Connected with peripheral--------");
               scan_start();
              
          //   NRF_LOG_INFO("BLE peroi %d", p_gap_evt->params.connected.role);  
               // bsp_board_led_on(CONNECTED_LED);
               // bsp_board_led_off(ADVERTISING_LED);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                 data_ret_fun();
                err_code = app_button_enable();
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected peri-------");
                bsp_board_led_off(CONNECTED_LED);
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                err_code = app_button_disable();
                APP_ERROR_CHECK(err_code);
                advertising_start();
                break;
    
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
                                                       BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
                                                       NULL,
                                                       NULL);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                // No system attributes have been stored.
                err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
           case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
    
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;  
    
            default:
             
      
                // No implementation needed.
                break;
        }
    }
    

    once connect getting message from esp32 and then switch over to central role to connect with another device - NRF(C - acts as peripheral) here i have shown how i disconnected and connecting to device (c)  , i tried without disconnecting from peripheral role used  ble_gap_connect fun to connect with device (c) but its not worked , when disconnect using ble_gap_disconnect.

    after i scan_init AND on_ble_central_evt - its connected with DEVICE NRF(C)

    static void led_write_handler(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t *data_ptr,ble_evt_t const * p_ble_evt)
    {
                chk_flag = true;
       
               ret_code_t err_code;
    
              printf("DATA:%s\n",data_ptr);
    
                  process_msg(data_ptr) ;     
    
     if(periperal_central_role == false && chk_flag == true) 
     {
      periperal_central_role = true;
             printf("inside fun call of central\n");
    /* err_code = sd_ble_gap_connect(p_addr,
                                      p_scan_params,
                                      p_conn_params,
                                      con_cfg_tag); */
    
    
             ret_code_t err_code;
              err_code = sd_ble_gap_disconnect(m_conn_handle,
                                                BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    
     if(err_code  ==  NRF_SUCCESS)
      {
     printf("sucess\n");
    
    
     scan_init();  
      
     on_ble_central_evt(p_ble_evt);
    
     }
    i am geting a mac id of devcie(C) from the message got from esp32 , then with the mac id i have to connect with device (C), for this connection i used the below fun

     void scan_init(void)
    {
        ret_code_t          err_code;
        nrf_ble_scan_init_t init_scan;
    
        memset(&init_scan, 0, sizeof(init_scan));
    if(periperal_central_role == true)
    {
    printf("inside central scan\n");
        init_scan.connect_if_match = true;
        init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
    
    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler_central);
        APP_ERROR_CHECK(err_code);
       
    err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_ADDR_FILTER, m_addr);
        APP_ERROR_CHECK(err_code);
             if(err_code == NRF_SUCCESS)
        {
         printf("nrf_ble_scan_filter_set\n");
        }
        else
        {
         printf("nrf_ble_scan_filter_notttttt ok-----\n");
        }  
    
         err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_ADDR_FILTER, false);
        APP_ERROR_CHECK(err_code);
          if(err_code == NRF_SUCCESS)
        {
         printf("nrf_ble_scan_filters_enable\n");
        }
        else
        {
         printf("nrf_ble_scan_not ok-----\n");
        }
    }
    else if(periperal_central_role == false)
    {
     printf("inside periperal scan\n");
          init_scan.connect_if_match = false;
        init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
        init_scan.p_scan_param     = &m_scan_param;
        err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler_peri);
        APP_ERROR_CHECK(err_code);
    
    }
       
    }
    

    when getting the ack from DEVICE (C) I switching over the role to peripheral in RELAY(B)

    void central_msg_handler(void * p_context)
    {
    ret_code_t err_code;
    printf("handle -------centrl---\n");
    err_code = ble_lbs_led_status_send(&m_ble_lbs_c, button_action);
    if (err_code != NRF_SUCCESS &&
    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
    err_code != NRF_ERROR_INVALID_STATE)
    {

    sprintf(collect_data, "{\"MSTS\":\"%s\",\"MAC\":\"%02X%02X%02X%02X%02X%02X\"}","0", m_addr_c[0], m_addr_c[1],
    m_addr_c[2], m_addr_c[3],
    m_addr_c[4], m_addr_c[5]);
    coaster_msg_suc = true ;
    APP_ERROR_CHECK(err_code);
    printf("data ret %s\n",collect_data);
    }
    if (err_code == NRF_SUCCESS)
    {
    coaster_msg_suc = true ;
    sprintf(collect_data, "{\"MSTS\":\"%s\",\"MAC\":\"%02X%02X%02X%02X%02X%02X\"}","1", m_addr_c[0], m_addr_c[1],
    m_addr_c[2], m_addr_c[3],
    m_addr_c[4], m_addr_c[5]);
    printf("data ret %s\n",collect_data);
    printf("sucess return------------\n");

    }
    mode_chnage_peripheral();
    }

    void mode_chnage_peripheral()
    {


    ret_code_t err_code;
    err_code = sd_ble_gap_disconnect(m_conn_handle,
    BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION);err_code = sd_ble_gap_adv_stop(m_adv_handle);

    }

Children
Related