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

Configured advertising duration and interval dont match up observed values for ble_app_eddystone example. Is this a bug?

I am using sdk15.2.0 with PCA10040 dev board.

In ble_app_eddystone example, the configured advertising interval and duration dont match the observed values.

I think I have found the reason why they dont match... Just want a confirmation from Nordic engineers weather I am correct or not.

Below code snippet is from es_app_config.h file 

#define APP_CFG_NON_CONN_ADV_TIMEOUT                        0                           //!< Time for which the device must be advertising in non-connectable mode (in seconds). 0 disables the time-out.
#define APP_CFG_NON_CONN_ADV_INTERVAL_MS                    1000                        //!< The advertising interval for non-connectable advertisement (in milliseconds). This value can vary between 100 ms and 10.24 s.
#define APP_CFG_CONNECTABLE_ADV_TIMEOUT                     6000                        //!< Time for which the device must be advertising in connectable mode (in milliseconds). 0 disables the time-out.
#define APP_CFG_CONNECTABLE_ADV_INTERVAL_MS                 100                         //!< The advertising interval for connectable advertisement (in milliseconds). This value can vary between 20 ms and 10.24 s.

As per the comment in the code, the values are in milli seconds.

In es_adv.c in get_adv_params() values from es_app_config.h are assigned to ble_gap_adv_params_t structure. Below code is from es_adv.c

/**@brief  Given state of Eddystone beacon, get advertisement parameters. */
static void get_adv_params(ble_gap_adv_params_t * p_adv_params,
                           bool                   non_connectable,
                           bool                   remain_connectable)
{
    // Initialize advertising parameters (used when starting advertising).
    memset(p_adv_params, 0, sizeof(ble_gap_adv_params_t));

    // Non-connectable
    p_adv_params->properties.type = non_connectable
                                  ? BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED
                                  : BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
    p_adv_params->p_peer_addr     = NULL; // Undirected advertisement.
    p_adv_params->filter_policy   = BLE_GAP_ADV_FP_ANY;
    p_adv_params->interval        = non_connectable ? m_adv_interval : APP_CFG_CONNECTABLE_ADV_INTERVAL_MS;
    p_adv_params->duration        = non_connectable
                                  ? APP_CFG_NON_CONN_ADV_TIMEOUT
                                  : (remain_connectable ? 0 : APP_CFG_CONNECTABLE_ADV_TIMEOUT);
    p_adv_params->primary_phy     = BLE_GAP_PHY_1MBPS;
}

Now if you check ble_gap_adv_params_t structure definition in ble_gap.h, the interval and duration values are not in milli seconds(read the comments).

  uint32_t                 interval;                /**< Advertising interval in 625 us units. @sa BLE_GAP_ADV_INTERVALS.
                                                         @note If @ref ble_gap_adv_properties_t::type is set to
                                                               @ref BLE_GAP_ADV_TYPE_CONNECTABLE_NONSCANNABLE_DIRECTED_HIGH_DUTY_CYCLE
                                                               advertising, this parameter is ignored. */
  uint16_t                 duration;                /**< Advertising duration in 10 ms units. When timeout is reached,
                                                         an event of type @ref BLE_GAP_EVT_ADV_SET_TERMINATED is raised.
                                                         @sa BLE_GAP_ADV_TIMEOUT_VALUES.
                                                         @note The SoftDevice will always complete at least one advertising

Milli second macros from es_config.h should have been converted to respective count before use. This is the reason why configured and observed values don't match up.

Please confirm my understanding...

Parents
  • Hi,

    Yes, I can confirm that this is a bug.

    A fix could be to convert the interval from ms units to 625 us units in adv_start() in es_adv.c 

    Snippet:

    static void adv_start(ble_gap_adv_params_t * p_adv_params)
    {
        ret_code_t err_code = NRF_SUCCESS;
    
        es_tlm_adv_cnt_inc();
    
        uint32_t interval_0625 = MSEC_TO_UNITS(p_adv_params->interval,UNIT_0_625_MS);
    
        p_adv_params->interval = interval_0625;
    
        err_code = sd_ble_gap_adv_set_configure(mp_adv_handle, &m_adv_data, p_adv_params);
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gap_adv_start(*mp_adv_handle, BLE_CONN_CFG_TAG_DEFAULT);
    
        if (err_code != NRF_ERROR_BUSY && err_code != NRF_SUCCESS)
        {
            APP_ERROR_CHECK(err_code);
        }
    }

    OR maybe better, in the get_adv_params() function.

    Snippet:

    /**@brief  Given state of Eddystone beacon, get advertisement parameters. */
    static void get_adv_params(ble_gap_adv_params_t * p_adv_params,
                               bool                   non_connectable,
                               bool                   remain_connectable)
    {
        // Initialize advertising parameters (used when starting advertising).
        memset(p_adv_params, 0, sizeof(ble_gap_adv_params_t));
    
        // Non-connectable
        p_adv_params->type =
            non_connectable ? BLE_GAP_ADV_TYPE_ADV_NONCONN_IND : BLE_GAP_ADV_TYPE_ADV_IND;
        p_adv_params->p_peer_addr = NULL; // Undirected advertisement.
        p_adv_params->fp          = BLE_GAP_ADV_FP_ANY;
    
        p_adv_params->interval    = non_connectable ? BLE_GAP_ADV_INTERVAL_MAX : 1000;
    
        uint32_t interval_0625 = MSEC_TO_UNITS(p_adv_params->interval,UNIT_0_625_MS);
        p_adv_params->interval = interval_0625;
    
    
        p_adv_params->timeout     = non_connectable
                                    ? APP_CFG_NON_CONN_ADV_TIMEOUT
                                    : (remain_connectable ? 0 : APP_CFG_CONNECTABLE_ADV_TIMEOUT);
    }

  • Hi

    There are too many timing related issues in ble_app_eddystone. Looks like the developer completely forgot about converting milli second values. es_app_config.h is confusing, the developer who wrote this should take a relook at this file. Here are a few that I can list...

    1. The macro APP_CONFIG_ADV_INTERVAL_MS_MAX has "_MS_" in it. I assumed this would be in milliseconds. But the value assigned to this macro is 16384. As per standard the max advertising interval is 10.24 sec. And all the while I was guessing if the standards have changed, it took me some time to realize that 16384 * 0.625 = 10240ms! 

    2. Apparently there is one more macro, MAX_ADV_INTERVAL, in the same file for the same purpose but not used anywhere! Again there is contradiction between the comment and macro name.

    #define MAX_ADV_INTERVAL                                    (10240)                     //!< Maximum connection interval (in ms).

    3. If you change advertising interval from nRF Beacon for Eddystone app then again the advertising intervals go haywire. Looks like the milli sec values are not converted to interval counts.

    There are many such issue in this example, I may not be able to list them all. Can you request for a proper fix from the developer? Because if I do it I would need to spend more time and efforts in understanding the sdk code rather than writing my application.

    Usually your sdk code and examples are pretty awesome and rarely I find such issues with it but I wonder how this work got approved to be included in the release!

Reply
  • Hi

    There are too many timing related issues in ble_app_eddystone. Looks like the developer completely forgot about converting milli second values. es_app_config.h is confusing, the developer who wrote this should take a relook at this file. Here are a few that I can list...

    1. The macro APP_CONFIG_ADV_INTERVAL_MS_MAX has "_MS_" in it. I assumed this would be in milliseconds. But the value assigned to this macro is 16384. As per standard the max advertising interval is 10.24 sec. And all the while I was guessing if the standards have changed, it took me some time to realize that 16384 * 0.625 = 10240ms! 

    2. Apparently there is one more macro, MAX_ADV_INTERVAL, in the same file for the same purpose but not used anywhere! Again there is contradiction between the comment and macro name.

    #define MAX_ADV_INTERVAL                                    (10240)                     //!< Maximum connection interval (in ms).

    3. If you change advertising interval from nRF Beacon for Eddystone app then again the advertising intervals go haywire. Looks like the milli sec values are not converted to interval counts.

    There are many such issue in this example, I may not be able to list them all. Can you request for a proper fix from the developer? Because if I do it I would need to spend more time and efforts in understanding the sdk code rather than writing my application.

    Usually your sdk code and examples are pretty awesome and rarely I find such issues with it but I wonder how this work got approved to be included in the release!

Children
  • Hi,

    Can you request for a proper fix from the developer?

    Thank you for the feedback. I have reported the issue to the responsible developers.

  • Hi ,

    Thanks for your excellent  support! I tried to fix issues that mattered to me... hope this would help.

    diff --git a/Tools/nRF5_SDK_15.2.0_9412b96/examples/ble_peripheral/ble_app_eddystone/es_app_config.h b/Tools/nRF5_SDK_15.2.0_9412b96/examples/ble_peripheral/ble_app_eddystone/es_app_config.h
    index c6c08f1..a6251a3 100644
    --- a/Tools/nRF5_SDK_15.2.0_9412b96/examples/ble_peripheral/ble_app_eddystone/es_app_config.h
    +++ b/Tools/nRF5_SDK_15.2.0_9412b96/examples/ble_peripheral/ble_app_eddystone/es_app_config.h
    @@ -74,7 +74,7 @@
     #define APP_CONFIG_TLM_ADV_INTERLEAVE_RATIO                 5                           //!< How often should the TLM frame be advertised.
     
     
    -#define APP_CONFIG_ADV_INTERVAL_MS_MAX                      16384                       //!< Maximum allowed advertisement interval. Can be undefined without int
    +#define APP_CONFIG_ADV_INTERVAL_MS_MAX                      MSEC_TO_UNITS(MAX_ADV_INTERVAL, UNIT_0_625_MS) //!< Maximum allowed advertisement interval. Can be undefined without int
     #define APP_CONFIG_ADV_FRAME_SPACING_MS_MIN                 500                         //!< Minimum time between advertisement frames. Imposes limit on minumum accepted advertisement interval.
     #ifdef NRF52_SERIES
     #define APP_CONFIG_ADV_FRAME_ETLM_SPACING_MS                300                         //!< The time that is reqired for preparing an eTLM slot. Imposes limit on minimum accepted advertisement interval.
    @@ -99,8 +99,8 @@
     // BLE CONFIGS
     #define APP_DEVICE_NAME                                     "nRF5x_Eddystone"           //!< Advertised device name in the scan response when in connectable mode.
     #define IS_SRVC_CHANGED_CHARACT_PRESENT                     0                           //!< Information whether the service changed characteristic is available. If it is not enabled, the server's database cannot be changed for the lifetime of the device.
    -#define MAX_ADV_INTERVAL                                    (10240)                     //!< Maximum connection interval (in ms).
    -#define MIN_CONN_ADV_INTERVAL                               (20)                        //!< Minimum connection interval (in ms).
    +#define MAX_ADV_INTERVAL                                    (10240)                     //!< Maximum advertising interval (in ms).
    +#define MIN_CONN_ADV_INTERVAL                               (20)                        //!< Minimum advertising interval for connection mode (in ms).
     #define MIN_NON_CONN_ADV_INTERVAL                           (100)                       //!< Minimum advertisement interval for non-connectable advertisements (in ms).
     
     #define CENTRAL_LINK_COUNT                                  0                           //!< Number of central links used by the application. When changing this number, remember to adjust the RAM settings.
    diff --git a/Tools/nRF5_SDK_15.2.0_9412b96/components/ble/ble_services/eddystone/es_adv.c b/Tools/nRF5_SDK_15.2.0_9412b96/components/ble/ble_services/eddystone/es_adv.c
    index 16bcf79..d633d35 100644
    --- a/Tools/nRF5_SDK_15.2.0_9412b96/components/ble/ble_services/eddystone/es_adv.c
    +++ b/Tools/nRF5_SDK_15.2.0_9412b96/components/ble/ble_services/eddystone/es_adv.c
    @@ -44,11 +44,19 @@
     #include "es_tlm.h"
     #include "es_slot.h"
     
    +/*Note: Ideally this macro should be in components/libraries/util/app_util.h*/
    +/**@brief Macro for converting ticks to milliseconds.
    + *
    + * @param[in] TICKS         Number of ticks to convert.
    + * @param[in] RESOLUTION    Unit to be converted to in [us/ticks].
    + */
    +#define UNITS_TO_MSEC(TICKS, RESOLUTION) (((TICKS) * (RESOLUTION)) / (1000))
    +
     static es_adv_evt_handler_t m_adv_evt_handler;                                       //!< Eddystone advertisement event handler.
     static bool                 m_is_connected       = false;                            //!< Is the Eddystone beacon in a connected state.
     static bool                 m_remain_connectable = false;                            //!< Should the Eddystone beacon remain connectable.
     static uint8_t              m_ecs_uuid_type      = 0;                                //!< UUID type of the Eddystone Configuration Service.
    -static uint16_t             m_adv_interval       = APP_CFG_NON_CONN_ADV_INTERVAL_MS; //!< Current advertisement interval.
    +static uint16_t             m_adv_interval       = MSEC_TO_UNITS(APP_CFG_NON_CONN_ADV_INTERVAL_MS, UNIT_0_625_MS); //!< Current advertisement interval.
     
     static uint8_t   m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];                    //!< Buffer for storing an encoded advertising set.
     static uint8_t   m_enc_scan_response_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];         //!< Buffer for storing an encoded scan data.
    @@ -117,10 +125,10 @@ static void get_adv_params(ble_gap_adv_params_t * p_adv_params,
                                       : BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
         p_adv_params->p_peer_addr     = NULL; // Undirected advertisement.
         p_adv_params->filter_policy   = BLE_GAP_ADV_FP_ANY;
    -    p_adv_params->interval        = non_connectable ? m_adv_interval : APP_CFG_CONNECTABLE_ADV_INTERVAL_MS;
    +    p_adv_params->interval        = non_connectable ? m_adv_interval : MSEC_TO_UNITS(APP_CFG_CONNECTABLE_ADV_INTERVAL_MS, UNIT_0_625_MS);
         p_adv_params->duration        = non_connectable
    -                                  ? APP_CFG_NON_CONN_ADV_TIMEOUT
    -                                  : (remain_connectable ? 0 : APP_CFG_CONNECTABLE_ADV_TIMEOUT);
    +                                  ? MSEC_TO_UNITS(APP_CFG_NON_CONN_ADV_TIMEOUT, UNIT_10_MS)
    +                                  : (remain_connectable ? 0 : MSEC_TO_UNITS(APP_CFG_CONNECTABLE_ADV_TIMEOUT, UNIT_10_MS));
         p_adv_params->primary_phy     = BLE_GAP_PHY_1MBPS;
     }
     
    @@ -288,18 +296,19 @@ void es_adv_on_ble_evt(ble_evt_t const * p_ble_evt)
     }
     
     
    -void es_adv_interval_set(nrf_ble_escs_adv_interval_t interval)
    +void es_adv_interval_set(nrf_ble_escs_adv_interval_t interval_ms)
     {
         const es_slot_reg_t * p_reg = es_slot_get_registry();
         uint16_t min_valid_adv_interval;
    +    nrf_ble_escs_adv_interval_t interval = MSEC_TO_UNITS(interval_ms, UNIT_0_625_MS);
     
         bool eTLM_required = (p_reg->num_configured_eid_slots > 0) && (p_reg->tlm_configured);
     
         min_valid_adv_interval = eTLM_required ?                                                               \
    -                                    p_reg->num_configured_slots * (APP_CONFIG_ADV_FRAME_SPACING_MS_MIN +   \
    -                                                                   APP_CONFIG_ADV_FRAME_ETLM_SPACING_MS)   \
    +                                    p_reg->num_configured_slots * (MSEC_TO_UNITS(APP_CONFIG_ADV_FRAME_SPACING_MS_MIN +   \
    +                                                                   APP_CONFIG_ADV_FRAME_ETLM_SPACING_MS, UNIT_0_625_MS))   \
                                                :                                                               \
    -                                    p_reg->num_configured_slots * APP_CONFIG_ADV_FRAME_SPACING_MS_MIN;
    +                                    p_reg->num_configured_slots * (MSEC_TO_UNITS(APP_CONFIG_ADV_FRAME_SPACING_MS_MIN, UNIT_0_625_MS));
     
         m_adv_interval = (interval > min_valid_adv_interval) ? interval : min_valid_adv_interval;
     
    @@ -311,10 +320,9 @@ void es_adv_interval_set(nrf_ble_escs_adv_interval_t interval)
     #endif // APP_CONFIG_ADV_INTERVAL_MS_MAX
     }
     
    -
     nrf_ble_escs_adv_interval_t es_adv_interval_get(void)
     {
    -    return m_adv_interval;
    +    return UNITS_TO_MSEC(m_adv_interval, UNIT_0_625_MS);
     }
     
     
    diff --git a/Tools/nRF5_SDK_15.2.0_9412b96/components/ble/ble_services/eddystone/nrf_ble_es.c b/Tools/nRF5_SDK_15.2.0_9412b96/components/ble/ble_services/eddystone/nrf_ble_es.c
    index bf203c2..ce762eb 100644
    --- a/Tools/nRF5_SDK_15.2.0_9412b96/components/ble/ble_services/eddystone/nrf_ble_es.c
    +++ b/Tools/nRF5_SDK_15.2.0_9412b96/components/ble/ble_services/eddystone/nrf_ble_es.c
    @@ -324,7 +324,7 @@ static void ble_escs_init(void)
                                                        & (ESCS_FRAME_TYPE_RFU_MASK);
         memcpy(init_params.broadcast_cap.supp_radio_tx_power, tx_powers, ESCS_NUM_OF_SUPPORTED_TX_POWER);
     
    -    init_params.adv_interval    = APP_CFG_NON_CONN_ADV_INTERVAL_MS;
    +    init_params.adv_interval    = MSEC_TO_UNITS(APP_CFG_NON_CONN_ADV_INTERVAL_MS, UNIT_0_625_MS);
         init_params.adv_tx_pwr      = APP_CFG_DEFAULT_RADIO_TX_POWER;
         init_params.radio_tx_pwr    = 0x00;
         init_params.factory_reset   = 0;
    @@ -351,7 +351,7 @@ static void adv_init(void)
     
         if (err_code == FDS_ERR_NOT_FOUND)
         {
    -        beacon_config.adv_interval       = APP_CFG_NON_CONN_ADV_INTERVAL_MS;
    +        beacon_config.adv_interval       = MSEC_TO_UNITS(APP_CFG_NON_CONN_ADV_INTERVAL_MS, UNIT_0_625_MS);
             beacon_config.remain_connectable = false;
         }
     
    
     

  • I programmed the following SDK 15.3.0 pre-compiled hex in my nRF-52 DK:

    \nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\ble_app_eddystone\hex\ble_app_eddystone_pca10040_s132.hex

    I used Android nRF Beacon for Eddystone app to configure:
    - Slot 0 = TLM
    - Adv. interval = 10000ms

    Afterwards Android app nRF Connect indicated frame interval as 6251ms, so it appears the above issue has not been addressed in SDK 15.3.0.  Nothing indicated in the release notes either...

    I observe strange results when I configure slot 0 as URL with interval 10000ms: nRF Connect shows short and long transmissions with interval 3741ms...

  • NordicHam said:
    so it appears the above issue has not been addressed in SDK 15.3.0.

     Yes, that is unfortunately correct.

  • I implemented Prasad's code on my nRF52-DK in SDK 15.3.0 and it is working as expected.  The maximum beacon interval I can configure is about 10 seconds.  How can I increase that to 30 seconds?

    Thank you.

Related