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

Why UART client does not connect to multiple peripherals

I would like UART client in example

C:\NordicSdks\SDK_14.1.0\examples\ble_central\ble_app_uart_c\pca10040\s132\arm5_no_packs

to connect auotomatically to nearby devices broadcasting advertising packets with Nordic UART service UUID encoded data payloads. Example client code without modifications currently connects to single perihperal based on service UUID in payload but does not connect to mutiple devices as I want.

I looked at ble_evt_handler call-back and noticed two events, BLE_GAP_EVT_ADV_REPORT and BLE_GAP_EVT_CONNECTED.

BLE_GAP_EVT_ADV_REPORT

case BLE_GAP_EVT_ADV_REPORT:
{
    ble_gap_evt_adv_report_t const * p_adv_report = &p_gap_evt->params.adv_report;

    if (is_uuid_present(&m_nus_uuid, p_adv_report))
    {
                    
        log("Connecting to device...");
                      
        err_code = sd_ble_gap_connect(&p_adv_report->peer_addr, 
                                      &m_scan_params,           
                                      &m_connection_param,      
                                      APP_BLE_CONN_CFG_TAG);
        log("Stopping scan...");

        if (err_code == NRF_SUCCESS)
        {
            // scan is automatically stopped by the connect
            err_code = bsp_indication_set(BSP_INDICATE_IDLE);
            APP_ERROR_CHECK(err_code);
            NRF_LOG_INFO("Connecting to target %02x%02x%02x%02x%02x%02x",
                     p_adv_report->peer_addr.addr[0],
                     p_adv_report->peer_addr.addr[1],
                     p_adv_report->peer_addr.addr[2],
                     p_adv_report->peer_addr.addr[3],
                     p_adv_report->peer_addr.addr[4],
                     p_adv_report->peer_addr.addr[5]
                     );
        }
    }
}break; // BLE_GAP_EVT_ADV_REPORT

BLE_GAP_EVT_CONNECTED

case BLE_GAP_EVT_CONNECTED:
            
    log("Connected to device.");
        
    NRF_LOG_INFO("Connected to target");
    err_code = ble_nus_c_handles_assign(&m_ble_nus_c, p_ble_evt->evt.gap_evt.conn_handle, NULL);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
    APP_ERROR_CHECK(err_code);

    // start discovery of services. The NUS Client waits for a discovery result
    err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
    APP_ERROR_CHECK(err_code);

    log("Starting scan...");
    scan_start();
        
    break;

In BLE_GAP_EVT_ADV_REPORT I noticed that on API call sd_ble_gap_connect chip will stop scanning before attempting to connect so there is no conflict with radio; so what I did was add scan_start() method in BLE_GAP_EVT_CONNECTED case.

I logged in my RTT that the client will attempt to connect to a second client, but not a third or more because when the client tries to connect to a secondary device the client appears to freeze up because there is no call back from ble_evt_handler.

I do not undestand why client freezes up probably inside soft device, but this is my explanation.

I noticed in the API call sd_ble_gap_connect that a data structure called peer_addr is passed as an argument

err_code = sd_ble_gap_connect(&p_adv_report->peer_addr, 
                              &m_scan_params,           
                              &m_connection_param,      
                              APP_BLE_CONN_CFG_TAG);

I look at ble_gap_evt_adv_report_t

typedef struct
{
  ble_gap_addr_t peer_addr;                     /**< Bluetooth address of the peer device. If the peer_addr resolved: @ref ble_gap_addr_t::addr_id_peer is set to 1
                                                     and the address is the device's identity address. */
  ble_gap_addr_t direct_addr;                   /**< Set when the scanner is unable to resolve the private resolvable address of the initiator
                                                     field of a directed advertisement packet and the scanner has been enabled to report this in @ref ble_gap_scan_params_t::adv_dir_report. */
  int8_t         rssi;                          /**< Received Signal Strength Indication in dBm. */
  uint8_t        scan_rsp : 1;                  /**< If 1, the report corresponds to a scan response and the type field may be ignored. */
  uint8_t        type     : 2;                  /**< See @ref BLE_GAP_ADV_TYPES. Only valid if the scan_rsp field is 0. */
  uint8_t        dlen     : 5;                  /**< Advertising or scan response data length. */
  uint8_t        data[BLE_GAP_ADV_MAX_SIZE];    /**< Advertising or scan response data. */
} ble_gap_evt_adv_report_t;

And then I look at ble_gap_addr_t

typedef struct
{
  uint8_t addr_id_peer : 1;       /**< Only valid for peer addresses.
                                       Reference to peer in device identities list (as set with @ref sd_ble_gap_device_identities_set) when peer is using privacy. */
  uint8_t addr_type    : 7;       /**< See @ref BLE_GAP_ADDR_TYPES. */
  uint8_t addr[BLE_GAP_ADDR_LEN]; /**< 48-bit address, LSB format. */
} ble_gap_addr_t;

And I notice addr_id_peer is 1 which make me wonder if there is some address conflict? And what about addr_t? Does it change from one uart server to the next? Is there address conflict here which is why client cannot connect to multiple servers?

Long story short, why is client not connecting to multiple servers?

Parents
  • Because simply it's written as single GAP Central role FW. If you want to establish more links then you need to do few changes:

    • Provision BLE stack aka Soft Device with more links during the init.
    • Create some structures/global variables to store mutliple connection handles and GATT handles so the code will really handle parallel connections correctly (not mixing them up!).
    • Once one connection is established you need to init another scanning slot (until you hit you maximum which you hardcode at compile time).

    These are indeed just high-level tasks, there will be many smaller parts to modify in the code. There is multi-link central example in the nRF5 SDK so get more inspiration there.

Reply
  • Because simply it's written as single GAP Central role FW. If you want to establish more links then you need to do few changes:

    • Provision BLE stack aka Soft Device with more links during the init.
    • Create some structures/global variables to store mutliple connection handles and GATT handles so the code will really handle parallel connections correctly (not mixing them up!).
    • Once one connection is established you need to init another scanning slot (until you hit you maximum which you hardcode at compile time).

    These are indeed just high-level tasks, there will be many smaller parts to modify in the code. There is multi-link central example in the nRF5 SDK so get more inspiration there.

Children
No Data
Related