Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Advertisement packet loss at device startup

Hello,

nRF5SDk16.0, Softdevice v.7.0.1, device nRF52840.

We using manufacturer specific information in the advertisement data. Here are the set values:

#define APP_ADV_INTERVAL                100     //62.5ms
#define APP_ADV_DURATION                0       //always advertise

The data is update through following code:

void send_adv_data(){
    ret_code_t err_code;
    ble_advertising_init_t init;
    uint8_t data_packet[5] = {0};
    
    // Get latest time
    rtc_get_time_local();
    // Copy data into data_packet
    for (int i=0; i<sizeof(4); i++)
        data_packet[i] = local_time[i];
    // Copy time stamp (+1) to last byte
    data_packet[4] = t_stamp;
    
    
    memset(&init, 0, sizeof(init));

    
    advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    advdata.include_appearance      = true;
    advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    clock_data.data.p_data               = &data_packet;
    clock_data.data.size                 = sizeof(data_packet);
    advdata.p_manuf_specific_data = &clock_data;
    err_code = ble_advertising_advdata_update(&m_advertising, &advdata, NULL);
    APP_ERROR_CHECK(err_code);

} 

The send_adv_data() function above is being called by an APP_TIMER with an interval of 50ms.

ISSUE:

We are receiving this advertisement data on an iPhone application. The problem is that when we power cycle the nRF52840 custom board, the received adv packets are sometimes more than 1 second apart. While we need these packets on a quick succession like after every 62.5ms. If the iPhone device is out-of-range and comes back into the range of nRF device, we can capture these packets quickly. But at the start of power cycle, we cannot get reliable packets for several minutes.

So my question is why can't the nRF device send reliable packets at the start of power cycle? What is the priority of advertisement over other tasks? Does the startup cycle have any affect of advertisement at all? 

The initialization code in my main.c file takes less than 500ms to complete.

Here is initialization code:

int main(void)

{
    bool erase_bonds;
    char * name_ptr;
    bool test_drives_result;
    int i=0;
    

    // Initialize.
    log_init();
    timers_init();
    read_module_type();
    //buttons_leds_init(&erase_bonds);
    NRF_LOG_INFO("Initializing RTC timer...");
    rtc_init();

    power_management_init();
    ble_stack_init();

    // Conventional passkey call here if required
    // TODO


    // Get device mac address and config its name accordingly
    get_device_mac_address();
    device_name_app = get_device_name(device_mac_address);


    gap_params_init();
    gatt_init();
   
    // Initialize flash memory &
    // Get values from Flash memory, Hotshot operation
    fdsm_init();

    services_init();
    advertising_init();
    conn_params_init();
    peer_manager_init();

    // Start execution.
    NRF_LOG_INFO("\r\n\r\n\r\nHotshot Firing System started...");
 
    NRF_LOG_INFO("Initializing adv timer...");
    adv_timer_init();
    adv_timer_start();

    
    NRF_LOG_INFO("Initializing script timer...");
    scr_timer_init();
       
    // Hotshot operations initialize (except fds_init())
    NRF_LOG_INFO("Initializing ADC...");
    saadc_init();
    saadc_sampling_event_init();
    saadc_sampling_event_enable();

    NRF_LOG_INFO("Initializing cue outputs...");
    cue_outputs_init();
    NRF_LOG_INFO("Initializing address (RGB colors)...");
    rgb_outputs_init();
    NRF_LOG_INFO("Initializing script data...");
    scr_data_init();
    NRF_LOG_INFO("Initializing scan delay timer...");
    s_delay_timer_init();
        
    if (modType == MOD_TYPE_BT840XE) {
#ifdef APP_PA_LAN	
      nrf_gpio_cfg_output(APP_CPS_PIN);
      nrf_gpio_cfg_output(APP_CHL_PIN);
      nrf_gpio_pin_set(APP_CHL_PIN);
      nrf_gpio_pin_clear(APP_CPS_PIN); //enable
      pa_lna_init(APP_PA_PIN,APP_LNA_PIN);
#endif
    }

    // Get the time stamp
    record_read_data(&t_stamp);
    t_stamp++;
    if (t_stamp>255)
        t_stamp=0;
    record_update_data(t_stamp);
    NRF_LOG_INFO("Time stamp value to adv: %d", t_stamp);
    //nrf_delay_ms(100);
    
    NRF_LOG_INFO("Initializing app timers...");
    application_timers_start();
    advertising_start(erase_bonds);				  
    // Extract password key from MAC address
    NRF_LOG_INFO("Setting passkey...");
    set_passkey();     
    
    // Run RGB sequence
    #ifdef RGB_INDICATOR
    rgb_sequence();
    #endif
    NRF_LOG_INFO("Running cue drive voltage tests...");
    // Perform the self test
    test_drives_result = test_drives(); 
    if (test_drives_result){
        NRF_LOG_INFO("Drive voltage tests passed.");
    }
    else{
        NRF_LOG_INFO("Drive voltage tests failed.");   
    }
    #ifdef RGB_INDICATOR
    rgb_self_test_indicator(test_drives_result);
    #endif

    // Get drive battery (18V) voltage
    drive_battery_voltage = get_drive_voltage();
    
    

    NRF_LOG_INFO("Device name = %s", device_name_app);
    NRF_LOG_INFO("Device total cues = %d", dev_total_cues);
    NRF_LOG_INFO("Device Hardware version = %d.%d", HARDWARE_VERSION/10, HARDWARE_VERSION%10);
    NRF_LOG_INFO("Device Firmware version = %d.%d", FIRMWARE_VERSION/10, FIRMWARE_VERSION%10);
      
    // Initialize log data, read log data from flash
    #ifdef INTERNAL_LOG_ENABLED
    init_log_data();
    #endif

    // Extract password key from MAC address
    NRF_LOG_INFO("Running main loop...");  
    // Enter main loop.


    for (;;)
    {
        idle_state_handle();
    }
}

  • Hi

    First off, do you see this on multiple of your custom boards or just the one? It could be that you have a faulty/poorly optimized crystal that takes some time to get up to speed after a power cycle. Can you upload the schematics of your board and/or the datasheet of the external crystal(s) you are using so we can take a look at that.

    Next, advertising won't be the most reliable way to capture data, as there is no way to ensure that an advertisement reaches its destination, so if you're looking for reliability I would suggest connecting the devices instead to ensure that all the necessary data is received in the central device.

    Best regards,

    Simon

  • We further tested this issue and found that if iPhone rescans the advertisement data, it starts getting good packets again. So, for now, restarting iPhone scanner after every 10s resolves the issue. I means that hardware sends correct packets but iPhone somehow cannot capture those packets unless it's BLE scanner is reset. Does this make any sense? Why it's happening?

  • This is just a guess but I think this feature changed and doesn't now continuous advertise in recent softdevices:

    #define APP_ADV_DURATION   0   //always advertise

    I can't check as too busy, but on advertising timeout - set to a large number like 18000 - simply restart the advertising if I recall correctly. Quick look in my code shows this, may be what you want:

    /**@brief Function for handling the Timeout event.
     *
     * @param[in] p_advertising Advertising module instance.
     * @param[in] p_ble_evt Event received from the BLE stack.
     */
    static void on_terminated(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt)
    {
        ret_code_t ret;
    
        if (p_ble_evt->header.evt_id != BLE_GAP_EVT_ADV_SET_TERMINATED)
        {
            // Nothing to do.
            return;
        }
    
        if (  p_ble_evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_TIMEOUT
            ||p_ble_evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_LIMIT_REACHED)
        {
            // Start advertising in the next mode.
            ret = ble_advertising_start(p_advertising, adv_mode_next_get(p_advertising->adv_mode_current));
    
            if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL))
            {
                p_advertising->error_handler(ret);
            }
        }
    }
    

  • @Sinmonr,

    Does the following code continuously advertise or not in the softdevice v7.0.1 (SDK v16.0)?

    #define APP_ADV_DURATION   0   //always advertise

    My testing shows that it does, and whenever I scan devices through nRFConnect, it shows updated adv data. But still I want to confirm as @hmolesworth suggested otherwise.

    Also my issue is not that it stops advertising, my issue is packet loss at the start of advertising. It may just be mobile app scanner issue, but I still want to confirm.

  • Hi

    setting the advertising duration (APP_ADV_DURATION) to 0 will disable the advertising timeout, and will let the device keep advertising "indefinitely". I'm not entirely sure what  is referring to I'm afraid.

    Best regards,

    Simon

Related