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

alternate advertising packets with nRF52832, sdk15.0.0 , sd132 v6.0.0

I need to change, on a time basis, the advertising packet :

Let's say for X seconds it has to work as a "iBeacon"

  • BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED
  • Advertising interval 100ms

, while for other X seconds as a scannable and connecteble advertising (standard) packet:

  • Advertising interval 190 ms

i'm developing starting from the template example with  BLE_ADVERTISING_DEF(m_advertising)  structure and I'm trying to "integrate"

with the "nRF5_SDK_15.0.0_a53641a\examples\ble_peripheral\ble_app_beacon"  example but I'm getting an :

"..<error> app: Fatal error
<warning> app: System reset"

when trying with this piece of code:


static void timer_timeout_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    ret_code_t err_code;
    static int flag=1;
    timerCounter++;

    
    if( timerCounter % 3 == 0 )
    {
      if (flag ){
        //stop "standard" adv
        NRF_LOG_INFO(" stopping standard ADV");
        err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);      
        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }
  
        // change advertising message
        NRF_LOG_INFO(" init iBeacon ");
        iBeacon_init();              
        NRF_LOG_INFO(" starting ibeacon");
        iBeacon_start();
  
        flag = 0;

      }

      else  
      {
        
        NRF_LOG_INFO(" restart standard ADV");
        err_code = sd_ble_gap_adv_stop(m_adv_handle);
        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }
        err_code = ble_advertising_restart_without_whitelist(&m_advertising);
        if (err_code != NRF_ERROR_INVALID_STATE)
        {
            APP_ERROR_CHECK(err_code);
        }

        flag =1;
      }
      
    }

}


static void iBeacon_init(void)
{
    uint32_t      err_code;
    ble_advdata_t advdata;
    uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;

    ble_advdata_manuf_data_t manuf_specific_data;

    manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;

#if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
    // UICR instead of using the default values. The major and minor values obtained from the UICR
    // are encoded into advertising data in big endian order (MSB First).
    // To set the UICR used by this example to a desired value, write to the address 0x10001080
    // using the nrfjprog tool. The command to be used is as follows.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
    // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
    // the following command should be used.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
    uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
    uint16_t minor_value = ((*(uint32_t *)UICR_ADDRESS) & 0x0000FFFF);

    uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;

    m_beacon_info[index++] = MSB_16(major_value);
    m_beacon_info[index++] = LSB_16(major_value);

    m_beacon_info[index++] = MSB_16(minor_value);
    m_beacon_info[index++] = LSB_16(minor_value);
#endif

    manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
    manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;

    // Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));

    advdata.name_type             = BLE_ADVDATA_NO_NAME;
    advdata.flags                 = flags;
    advdata.p_manuf_specific_data = &manuf_specific_data;

    // Initialize advertising parameters (used when starting advertising).
    memset(&m_adv_params, 0, sizeof(m_adv_params));

    m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
    m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
    m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
    m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
    m_adv_params.duration        = APP_IBCN_DURATION;       // Never time out.

    err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
    APP_ERROR_CHECK(err_code);
}


static void iBeacon_start(void)
{
    ret_code_t err_code;

    err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
    APP_ERROR_CHECK(err_code);
}


 

the application resets on iBeacon_init() in the timer handler.

is it a problem of configuring the right parametrs to the SD API , or something else?

Thx

bye

  • I know they added a snazzy way to timeslice two completely different BLE personalities together in recent SD but haven't had need to learn about it.

    But, for what your needs appear to be, yes you can just run a timer and update the struct for the advertisement info and re-init advertisements. You don't have to stop advertising as you have shown.  Doing that only will increase the power consumption. You only need to stop adverts if you change the advertising interval.

    Just remember iBeacon adverts won't show up in iOS CoreBluetooth they will only show in CoreLocation.  But I suspect you already knew that. And, Android doesn't care what you call it so no concerns there.

    If you use radio notifications you can easily make it synchronous with the advertisements.

  • Hi,

    The SoftDevice V6.0.0 can only configure one advertising set. Therefore, when starting the non-connectable advertising(iBeacon), the advertising handle should be the same as for the connectable advertising. (i.e. use m_advertising.adv_handle for both).

    In your function, IBeacon_init() should configure the adv set like this:

        err_code = sd_ble_gap_adv_set_configure(&m_advertising.adv_handle, &m_adv_data, &m_adv_params);
        APP_ERROR_CHECK(err_code);

    The function iBeacon_start() should look like this:

    static void iBeacon_start(void)
    {
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_start(m_advertising.adv_handle, APP_BLE_CONN_CFG_TAG);
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
        APP_ERROR_CHECK(err_code);
    }

    And in timer_timeout_handler(), restart standard ADV like this:

          else  
          {
            
            NRF_LOG_INFO(" restart standard ADV");
            err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
            err_code = ble_advertising_restart_without_whitelist(&m_advertising);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }
    
            flag =1;
          }

    PS: I don't see that you set your timerCounter back to 0 anywhere, so it might overflow after awhile. You can also just adjust the timeout value for how often timer_timeout_handler is called, so you could consider removing the timerCounter.

    Best regards,

    Sigurd

  • still I get the error:

    <info> app: FW_VER= nRF52DK_00.02.01
    <info> app: log_init
    <info> app: timers_init
    <info> app: buttons_leds_init
    <info> app: power_management_init
    <info> app: ble_stack_init
    <info> app: services_init
    <info> app: advertising_init
    <info> app: XX Demo started.
    <info> app: Fast advertising.

    ...after 3 sec...

    <info> app: stopping standard ADV
    <info> app: init iBeacon
    <error> app: Fatal error
    <warning> app: System reset

    ...

    i'm wondering if the two different configurations are "compatible" :

    the custom advertisement is  this:

    static void advertising_init(void)
    {
        ret_code_t             err_code;
        ble_advertising_init_t init;
        ble_advdata_manuf_data_t  manuf_data_res; // Variable to hold manufacturer specific data
    
    
        //manuf_data.company_identifier         = 0x0059; // Nordics company ID
        manuf_data_res.company_identifier       = 0xffff; //interoperability default value; not to be used in shipping end product
        manuf_data_res.data.p_data              = (uint8_t *)SerialNumber;
        manuf_data_res.data.size                = sizeof(SerialNumber)-1;
    
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
        //init.advdata.name_type               = BLE_ADVDATA_SHORT_NAME;
        //init.advdata.short_name_len          = 8;
        //init.advdata.include_appearance      = true;
        init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;   
        init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
    
    
        init.srdata.name_type               = BLE_ADVDATA_NO_NAME;    
        init.srdata.include_appearance      = true;  
        init.srdata.p_manuf_specific_data   = &manuf_data_res;
        //init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);//more_adv_uuids
        //init.srdata.uuids_complete.p_uuids = m_adv_uuids;
           
    
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
    
        init.evt_handler = on_adv_evt;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    

    while the beacon struct is written above in the first code snippet.

    any comment?

  • What is the value of your "APP_IBCN_DURATION" ? Could you try setting it to 0 ?

  • SOLVED.

    issue was a wrong initialization in the data structures passed in the

     err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);

    when changing from iBeacon to custom advertising and vice versa.

    (the m_adv_data.adv_data.p_data  and m_adv_data.adv_data.len are static, retaining a wrong data size when toggling from one another kind of packets) 

    in the end it worked, on a time slice base, alternating the 2 packets (using just the same handler).

    the only thing is that I have to call every time sd_ble_gap_adv_stop() before the ble_advdata_encode-sd_ble_gap_adv_set_configure  and sd_ble_gap_adv_start() calls.

Related