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