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

No scan response using latest version of pc-ble-driver v6.1.1 on nrf52832

We are using the latest pc-ble-driver with SoftDevice v6.1.1 and latest connectivity firmware on an nrf52832 (s132) which is connected via usb-uart.

We were previously using v5, but had some issues with setting TX power and so have updated to v6.1.1 which resolved that issue. But we are now no longer receiving any scan responses.

From what I've read so far, this might have something to do with the change in the API requiring the scan to be triggered each time a BLE_GAP_EVT_ADV_REPORT event occurs, and the connection being too slow to catch the scan responses. 

The parameters used for starting the scan are:

#define BLE_SCAN_EXTENDED 1

#define SCAN_INTERVAL 0x00A0 
#define SCAN_WINDOW 0x0050

static ble_gap_scan_params_t ble_scan_params = {
    #if NRF_SD_BLE_API >= 6
    .extended = BLE_SCAN_EXTENDED,
    .report_incomplete_evts = 0,
    #endif
    
    .active = 1,

    #if NRF_SD_BLE_API >= 6
    .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL,
    .scan_phys = BLE_GAP_PHY_1MBPS,
    #else
    .use_whitelist = 0, // TODO see if we can use this to pre-filter on service-uuid.
    .adv_dir_report = 0,
    #endif

    .interval = SCAN_INTERVAL, /**< Scan interval between 0x0004 and 0x4000 in 0.625 ms units (2.5 ms to 10.24 s). */
    .window = SCAN_WINDOW, /**< Scan window between 0x0004 and 0x4000 in 0.625 ms units (2.5 ms to 10.24 s). */
    .timeout = BLE_GAP_SCAN_TIMEOUT_UNLIMITED, /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */

    #if NRF_SD_BLE_API >= 6
    .channel_mask = { 0, 0, 0, 0, 0 },
    #endif
};

#if BLE_SCAN_EXTENDED == 1
static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_EXTENDED_MAX];
#else
static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MAX];
#endif

static ble_data_t m_scan_buffer =
{
    m_scan_buffer_data,
#if BLE_SCAN_EXTENDED == 1
    BLE_GAP_SCAN_BUFFER_EXTENDED_MAX
#else
    BLE_GAP_SCAN_BUFFER_MAX
#endif
};

As you can see active is set to 1, which from my understanding should allow for scan requests to be sent automatically and scan responses coming in as BLE_GAP_EVT_ADV_REPORT events. (We've also tried with both extended being set to 1 and 0.) The scan is then started using:

uint32_t error_code = sd_ble_gap_scan_start(adapter, &ble_scan_params, &m_scan_buffer);

And continued in the callback when receiving

static void ble_evt_dispatch(adapter_t* adapter, ble_evt_t* p_ble_evt)
{
#if NRF_SD_BLE_API >= 6    
    if(p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT)
    {
        sd_ble_gap_scan_start(adapter, nullptr, &m_scan_buffer);
        LOG_DEBUG("Found beacon - (%d, %d).", p_ble_evt->evt.gap_evt.params.adv_report.type.scannable, p_ble_evt->evt.gap_evt.params.adv_report.type.scan_response);
    }
#endif

    ...
}

This pseudo-code only logs Found beacon - (1, 0) and sometimes Found beacon - (0, 0) - but I almost never see Found beacon - (1, 1). I haven't measured but let's say only once every 10000 detections.

Since I mostly see devices which are scannable, I would expect to see a lot more scan responses, I also have several devices running for which I know they are able to send scan responses (tested using iOS app). 

I came across this post: https://devzone.nordicsemi.com/f/nordic-q-a/50082/pc-ble-driver-no-scan-response which seems to be a similar issue. But since that post is from over a year ago I was hoping there might be a solution for this.

The scan responses are a vital part for an application we are developing, but I have not been able to find a solution to be able to get the scan responses.

Is there anything basic we are missing which is preventing the scan responses to come in through the callback? Is there any way to manually send a scan request and get the response for that?

  • Hello,

    I had to ask around, as I see there have been some discussions on this topic, both here on DevZone, and internally. 

    What I see is that due to an API change in SD API v6 you need to restart the scanning after every advertising report. In serialization, this means that the advertising report needs to be sent (over serial), and then the application core/computer needs to decide whether or not to resume scanning, send the command back over serial, before it can be resumed. Since this takes time, the scan response has already been sent, and will not be picked up by the softdevice. 

    From the internal ticket:

    "The scanning APIs were changed in SD API v6 so that the scanning needs to be restarted for every received advertising packet. Since ble-driver uses serialization, the event needs to travel from the connectivity firmware, over USB-UART, and up to the application on the pc-side. Then the application needs to send a command back to the connectivity to continue the scanning. This roundtrip time makes it a lot slower to receive advertising packets. "

    I don't know where you found your serialization application (the one running on the nRF device that is plugged in the computer), but if you have compiled it yourself, you can look into restarting the scan directly in the nRF application in the BLE_GAP_EVT_ADV_REPORT event, so that this decision doesn't have to take the round trip. 

    Do you ever connect to anything? If so, you may need to take this into concideration. If you only support one connection, and start scanning, the softdevice will return an error to the start_scan call. 

    Let me know what you think about this, and whether you can try to change the connectivity firmware, found in SDK\examples\connectivity\ble_connectivity.

    Best regards,

    Edvin

  • Hi,

    Thanks for the reply, the delay in the communication then is what I expected.

    We are using the connectivity application that is compiled by the compile_connectivity target in the pc-ble-driver repository. Which from what I understand is the application from examples\connectivity\ble_connectivity.

    There is no objection to modifying the connectivity application, I have tried to play around with it but couldn't find the proper things to change and where to add/change them. 

    We do also connect to devices (currently only one at a time), so we have to take that in to account.

    If you could guide us to what to add/change and where that would be great.

    Kind regards,

    Thys

  • Hello Thys,

    I have not tested this, but the events occur in ser_conn_ble_event_handle() in ser_conn_handlers.c.

    The advertising reports will trigger the following chain:

    ser_conn_ble_event_handle() -> app_sched_event_put() -> which will trigger:

    ser_conn_ble_event_encoder() -> ble_event_enc() -> case BLE_GAP_EVT_ADV_REPORT: -> ble_gap_evt_adv_report_enc()

    So the first thing I would check is whether adding the scan start call before ble_gap_evt_adv_report_enc() would be sufficient. You can check the return value of this softdevice call and see whether it ever returns anything other than NRF_SUCCESS;

    Does it work without connecting to anything? Does any errors occur when you try to connect to anything? You can expect the scan_start() call in your application to return != NRF_SUCCESS, so try to ignore that for the time being. You can take note of what it returns.

    I have not set up pc-ble-driver on my computer, so if you can give this a go, that would be great. If you are stuck somewhere, I can try to install it.

    Best regards,

    Edvin

  • Hi Edvin,

    We'll give that a try.

    The sd_ble_gap_scan_start call requires a buffer for the second argument, is there any easy place we can access the current scan buffer from for when calling it from the ser_conn_ble_event_encoder?

    Kind regards,

    Thys

  • Hello Thys,

    To be fair, I don't know whether this will work or not at all. Officially, this is not supported, so I am not sure what scan buffer you can use. I am trying to see how the scan buffer is set up when the scanning is normally started. 

    It is usually started using conn_mw_ble_gap_scan_start() in conn_mw_ble_gap.c, so perhaps it would be possible to call that from the advertising report. 

    believe that this is usually triggered from conn_mw_handler() in conn_mw.c -> conn_mw_handler_get(), which again is called from ser_conn_command_process() in ser_conn_cmd_decoder.c.

    How about trying to call ser_conn_command_process(SD_BLE_GAP_SCAN_START, packet_len); from the adv report?

    I can't tell what the packet_len is used for, other than being the length of the serial command itself. Try setting it to a random number and see what happens. It looks like the len needs to be > 0, so try with 1.

    BR,

    Edvin

Related