Hello,
I got a custom board based on nRF52840. It uses extended BLE advertising to deliver a sensor data to the central hub with a frequency of 10 Hz. I've set the interval_max to 100ms/0.625 = 160, and interval_min to 159, as by the BT spec they cannot be equal (setting to 160 doesn't change the picture though).
In the test, conducted against Linux machine - I see that the distance between the received packets is ~103-105 ms (average over ~1000 packets). I can tweak it to become 100 by reducing the interval value by 5-7 0.625th - but the correction has to be found individually for each board instance.
The boards are factory-made and both oscillator circuits made according to a reference design. I use NRFConnect v. 2.5.1
My configuration:
CONFIG_DK_LIBRARY=y CONFIG_NEWLIB_LIBC=y CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y CONFIG_LOG=n CONFIG_ASSERT=n CONFIG_USE_SEGGER_RTT=n CONFIG_LOG_BACKEND_RTT=n CONFIG_LOG_MODE_IMMEDIATE=n CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CTLR_PHY_CODED=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=255 CONFIG_BT_EXT_ADV=y CONFIG_BT_USER_PHY_UPDATE=y CONFIG_BT_DEVICE_NAME_DYNAMIC=y CONFIG_BT_RX_STACK_SIZE=4096 CONFIG_BOOTLOADER_MCUBOOT=y CONFIG_NRF_APPROTECT_LOCK=y CONFIG_HWINFO=y CONFIG_BOARD_ENABLE_DCDC=n CONFIG_HEAP_MEM_POOL_SIZE=8192 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 CONFIG_MAIN_STACK_SIZE=4096
Code:
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/hwinfo.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/uuid.h>
#include <dk_buttons_and_leds.h>
#include <app_version.h>
#include <zephyr/logging/log.h>
//LOG_MODULE_REGISTER(MN, LOG_LEVEL_INF);
enum
{
UNIT_0_625_MS = 625, /**< Number of microseconds in 0.625 milliseconds. */
UNIT_1_25_MS = 1250, /**< Number of microseconds in 1.25 milliseconds. */
UNIT_10_MS = 10000 /**< Number of microseconds in 10 milliseconds. */
};
/**@brief Macro for converting milliseconds to ticks.
*
* @param[in] TIME Number of milliseconds to convert.
* @param[in] RESOLUTION Unit to be converted to in [us/ticks].
*/
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
#define ADV_INTERVAL_NORMAL 100
#define ADV_INTERVAL_HIGHSAMPLING 100
#define BLE_ADV_INTERVAL MSEC_TO_UNITS(ADV_INTERVAL_NORMAL, UNIT_0_625_MS)
#define INITIAL_DELAYSTART 3000
#define COMPANY_ID 0x1234
#define ADV_DATA_PROTOCOL_VER 0x02
static uint8_t _deviceName[21];
static struct bt_le_ext_adv *_advertiser;
static uint8_t _advMfgData[24];
static uint32_t _advInterval = BLE_ADV_INTERVAL;
static bool _advInit = false;
static uint16_t _delayToStartAdv = 0;
static struct bt_data _advData[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA(BT_DATA_NAME_COMPLETE, _deviceName, sizeof(_deviceName)-1),
BT_DATA(BT_DATA_MANUFACTURER_DATA, _advMfgData, sizeof(_advMfgData))
};
static struct bt_le_adv_param _advParam;
int main(void)
{
uint64_t hwinfo = 0;
int err;
err = dk_leds_init();
if (err) {
// LOG_ERR("LEDs init failed (err %d)", err);
}
err = bt_enable(NULL);
if (err) {
// LOG_ERR("Bluetooth init failed (err %d)", err);
return 0;
}
// LOG_INF("Bluetooth initialized");
/* Get hardware ID */
hwinfo_get_device_id((uint8_t*)&hwinfo, sizeof(hwinfo));
// LOG_INF("HWId: %016llx", hwinfo);
uint32_t hwIdMsb = 0, hwIdLsb = 0;
_delayToStartAdv = INITIAL_DELAYSTART + (hwinfo % INITIAL_DELAYSTART);
_advParam.id = BT_ID_DEFAULT;
_advParam.sid = 0;
_advParam.secondary_max_skip = 0;
_advParam.options = (BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_CODED);
_advParam.interval_max = _advInterval-7;
_advParam.interval_min = _advInterval-7;
_advParam.peer = NULL;
err = bt_le_ext_adv_create(&_advParam, NULL, &_advertiser);
if (err) {
// LOG_ERR("Failed to create advertiser set (err %d)", err);
return err;
}
_advInit = true;
/* Update device name */
memset(_deviceName, 0, sizeof(_deviceName));
hwIdMsb = (hwinfo >> 32);
hwIdLsb = (uint32_t)hwinfo;
sprintf((char*)_deviceName, "AAA_%08x%08x", hwIdMsb, hwIdLsb);
err = bt_set_name((const char*)_deviceName);
if (err) {
// LOG_ERR("Failed to set device name (err %d)", err);
}
/* Update manufacturing data */
_advMfgData[0] = (uint8_t)COMPANY_ID;
_advMfgData[1] = (uint8_t)(COMPANY_ID >> 8);
_advMfgData[2] = ADV_DATA_PROTOCOL_VER;
_advData[2].data = _advMfgData;
err = bt_le_ext_adv_set_data(_advertiser, _advData, ARRAY_SIZE(_advData), NULL, 0);
if (err) {
// LOG_ERR("Failed to set advertising data (err %d)", err);
return err;
}
err = bt_le_ext_adv_start(_advertiser, NULL);
if (err) {
// LOG_ERR("Failed to start advertising set (err %d)", err);
return;
}
}
Please advise