Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Concurrents connections (2 identicals centrals try to connect to the same peripheral at the same time)

Hello,

I have a project (using NUS) that comes in 2 parts:

  1. NRF52840 (peripheral) which generate advertising when they have information to transmit.
  2. PCA10059 USB dongles that constantly scan for the above peripherals

I encounter a problem when several USB dongles (with same firmware) receive advertising from a device...
In this case, sometimes the dongles synchronize perfectly and simultaneously try to communicate with the peripheral which launched its advertising.

Each dongle then generates a BLE_NUS_C_EVT_DISCONNECTED event with which I relaunch a scan_start, and so on a few times for ten seconds !

I tried to modify NRF_BLE_SCAN_SCAN_INTERVAL and NRF_BLE_SCAN_SUPERVISION_TIMEOUT like this (but with some small result) :

// <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 100
#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 100
#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
#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 40
#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 4
#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 800
#endif

static ble_gap_scan_params_t m_scan_param = 
{
    .active        = 1,
    .interval      = NRF_BLE_SCAN_SCAN_INTERVAL,
    .window        = NRF_BLE_SCAN_SCAN_WINDOW,
    .timeout       = NRF_BLE_SCAN_SCAN_DURATION,
    .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL,
    .scan_phys     = BLE_GAP_PHY_1MBPS,
};
static ble_gap_conn_params_t m_conn_param = 
{
    .min_conn_interval  = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL, UNIT_1_25_MS),
    .max_conn_interval  = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL, UNIT_1_25_MS),
    .slave_latency      = (uint16_t)NRF_BLE_SCAN_SLAVE_LATENCY,
    .conn_sup_timeout   = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT, UNIT_10_MS),
};

static void scan_init(void)
{
    ret_code_t err_code;
    nrf_ble_scan_init_t init_scan;

    m_scan_param.interval = NRF_BLE_SCAN_SCAN_INTERVAL + (NRF_FICR->DEVICEADDR[0] & 0xFF);
    m_scan_param.window = m_scan_param.interval;

    m_conn_param.conn_sup_timeout = (uint16_t)MSEC_TO_UNITS(NRF_BLE_SCAN_SUPERVISION_TIMEOUT + (NRF_FICR->DEVICEADDR[0] & 0xFF)*10, UNIT_10_MS);

    memset(&init_scan, 0, sizeof(init_scan));

    init_scan.connect_if_match = true;
    init_scan.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
    init_scan.p_scan_param = &m_scan_param;
    init_scan.p_conn_param = &m_conn_param;

    err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);

In this page Connecting to advertisers performing extended advertising, I think I'm in the variant #4 but I never get the timeout event...

What's the best pratice for this case ?

Regards,

Gaétan

Related post: 

Parents Reply Children
  • Hi,

    1) Yes disconnect reason is BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED(0x3E)

    2) Actualy project use s140_nrf52_6.1.0_softdevice.hex, I need to change SDK version...

    3) Yes, I tried to add nrf_delay_us(NRF_FICR->DEVICEADDR[0] & 0xFF); in case BLE_NUS_C_EVT_DISCONNECTED  without change.

    Regards,

    Edit: I tried with SDK 17.1 and softdevice 7.3.0... It is the same: the dongles synchronize for a few seconds (about 3 seconds) and then the operation is OK

  • Gaétan said:
    I tried with SDK 17.1 and softdevice 7.3.0.

    For both central and peripheral?

    Gaétan said:
    tried to add nrf_delay_us

    Could you try a bit bigger delay? use e.g. nrf_delay_ms() instead?

  • For both central and peripheral?

    I think the peripheral program is not in question because when the centrals synchronize, the peripheral does not report any status, it looks like it does not receive a coherent frame. Probably because the 3 centrals transmit perfectly at the same time and the frame received is corrupted.

    Could you try a bit bigger delay? use e.g. nrf_delay_ms() instead?

    I tried putting the same delay in ms (but I was worried that softdevice wouldn't like too long a delay in interupt time). It didn't change anything because I have the feeling that the moment of the scan start is not very important, what is important is that the 3 centrals are listening on the same channel and simultaneously receive the advertising of the peripheral... Then the 3 centrals respond in a perfectly synchronized way!

  • Hi,

    Gaétan said:
    but I was worried that softdevice wouldn't like too long a delay in interupt time

    Yeah, better to use an app_timer for this. Start a one-shot timer that expires in random time < from 0 to x ms>, and in the callback, start the scanner.

    If it's started with some delay, then it reduces the probability for the scanners to be on the same channel.

  • Hello,

    I'm sorry, but I don't think that the start time of the SCAN function is important.
    Indeed, what matters is how many centrals are listening on the channel at the moment the peripheral is advertising.

    I really feel that the problem is that several centrals are TX their response to the advertising in a perfectly synchronized way.
    In this case, it would be necessary to integrate a random time in the central between the RX of the advertising and the TX of the connection request.

Related