nRF52833で測距できるらしい、、、まずは理屈はそっちのけでやってみる
nRF52833のexampleをだらだら見てたら、Bluetooth: nRF Distance Measurement with Bluetooth LE discoveryってのを見つけたのでやってみる。
どういう原理で測距しているか、下の方からこちら(https://docs.nordicsemi.com/bundle/ncs-latest/page/nrfxlib/nrf_dm/README.html)に飛べば多少説明があるっぽいけど、まずは見ないことにする。で、exampleのページの下のほうにTestingって項があって、この通りにやるわけだけど、
1. ターミナルをつないだ状態のKitにこのsampleのソフトを書き込む
2. kitをリセットする
3. もう1個のkitに同じsampleソフトを書き込んでリセットする
4. kitたちが勝手に同期するのを待つ
5. ターミナルの出力を見る
ってことらしい。簡単やん。
まずは、普通に進めていく。
nRF Connectのアイコンをつつく
Create a new application
Copy a sample
nrf_dmって入力して出てくるDistance measurement sampleをつつく
ォルダを決めて(通常はそのまんまおすすめされた通りでもいい)、エンター
当然、Open
これ↓は無視
で、ここで欲が出てくるわけよ。printkをUSBに出したいって。ははーん。
が、どうやるのが正解なのかさっぱりわからない。MDBT50Q-DB-33(nRF52833)でUSBにprintkでできたもので反映しといたほうがよさそうなものを全部やってみる。たぶんこの後のAdd build configurationで必要なものを自動的に集めてくれるはずなので、このタイミングでやっとかんといかんと思う。
app.overlay
- /*
- * Copyright (c) 2023 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
- */
- / {
- /* The timer instance to use. */
- chosen {
- ncs,dm-timer = &timer2;
- zephyr,console = &cdc_acm_uart0;/*2024.10.20 Sunday Engineer */
- };
- /* The selected pins will be used by Distance Measurement module for debug purposes. */
- dm_gpio {
- compatible = "gpio-leds";
- dm_ranging: dm-ranging {
- gpios = <&gpio0 27 GPIO_ACTIVE_LOW>;
- label = "DM Ranging Pin";
- };
- dm_add_request: dm-add-request {
- gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
- label = "DM Add request Pin";
- };
- };
- };
- /*2024.10.20 Sunday Engineer from here*/
- &zephyr_udc0 {
- cdc_acm_uart0: cdc_acm_uart0 {
- compatible = "zephyr,cdc-acm-uart";
- };
- };
- /*2024.10.20 Sunday Engineer to here*/
CMakeLists.txt
- #
- # Copyright (c) 2021 Nordic Semiconductor
- #
- # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
- #
- cmake_minimum_required(VERSION 3.20)
- find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
- project(nrf_dm)
- # NORDIC SDK APP START
- target_sources(app PRIVATE
- src/main.c
- src/pwm_led.c
- src/peer.c
- src/service.c
- )
- # NORDIC SDK APP END
- zephyr_library_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
- #2024.10.20 Sunday Engineer from here
- include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
- FILE(GLOB app_sources src/*.c)
- #2024.10.20 Sunday Engineer to here
prj.conf
- #
- # Copyright (c) 2021 Nordic Semiconductor ASA
- #
- # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
- #
- # BT
- CONFIG_BT=y
- CONFIG_BT_CENTRAL=y
- CONFIG_BT_PERIPHERAL=y
- CONFIG_BT_SCAN=y
- CONFIG_BT_SCAN_FILTER_ENABLE=y
- CONFIG_BT_SCAN_NAME_CNT=1
- CONFIG_BT_SCAN_MANUFACTURER_DATA_CNT=1
- CONFIG_BT_SCAN_WITH_IDENTITY=y
- CONFIG_BT_ID_MAX=1
- CONFIG_BT_EXT_ADV=y
- CONFIG_BT_DEVICE_NAME="nRF_DM"
- CONFIG_BT_DDFS=y
- # Distance Measurement
- CONFIG_DM_MODULE=y
- CONFIG_MPSL=y
- CONFIG_MPSL_TIMESLOT_SESSION_COUNT=1
- CONFIG_DM_MODULE_LOG_LEVEL_DBG=n
- CONFIG_DM_GPIO_DEBUG=y
- CONFIG_PWM=y
- CONFIG_NCS_SAMPLES_DEFAULTS=y
- CONFIG_DK_LIBRARY=y
- CONFIG_DM_HIGH_PRECISION_CALC=y
- #2024.10.20 Sunday Engineer from here
- CONFIG_USB_DEVICE_STACK=y
- CONFIG_USB_DEVICE_PRODUCT="Zephyr USB console sample"
- CONFIG_USB_DEVICE_PID=0x0004
- CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
- CONFIG_SERIAL=y
- CONFIG_CONSOLE=y
- CONFIG_UART_CONSOLE=y
- CONFIG_UART_LINE_CTRL=y
- #2024.10.20 Sunday Engineer to here
sample.yaml
- sample:
- description: nRF Distance Measurement sample
- name: Distance measurement sample
- tests:
- sample.bluetooth.nrf_dm.timeslot:
- sysbuild: true
- build_only: true
- extra_configs:
- - CONFIG_DM_HIGH_PRECISION_CALC=n
- integration_platforms:
- - nrf52dk/nrf52832
- - nrf52833dk/nrf52833
- - nrf52840dk/nrf52840
- - nrf5340dk/nrf5340/cpuapp
- platform_allow: >
- nrf52dk/nrf52832 nrf52833dk/nrf52833 nrf52840dk/nrf52840 nrf5340dk/nrf5340/cpuapp
- tags: bluetooth ci_build sysbuild
- sample.bluetooth.nrf_dm.timeslot.high_precision:
- sysbuild: true
- build_only: true
- extra_configs:
- - CONFIG_DM_HIGH_PRECISION_CALC=y
- integration_platforms:
- - nrf52833dk/nrf52833
- - nrf52840dk/nrf52840
- - nrf5340dk/nrf5340/cpuapp
- platform_allow: nrf52833dk/nrf52833 nrf52840dk/nrf52840 nrf5340dk/nrf5340/cpuapp
- tags: bluetooth ci_build sysbuild
- #2024.10.20 Sunday Engineer from here
- sample.usb.console:
- depends_on:
- - usb_device
- - usb_cdc
- tags: usb
- harness: console
- harness_config:
- fixture: fixture_usb_cdc
- #2024.10.20 Sunday Engineer to here
main.c
- /*
- * Copyright (c) 2021 Nordic Semiconductor ASA
- *
- * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
- */
- /** @file
- * @brief Nordic Distance Measurement sample
- */
- #include <stdint.h>
- #include <zephyr/kernel.h>
- #include <zephyr/sys/printk.h>
- #include <zephyr/sys/byteorder.h>
- #include <zephyr/bluetooth/bluetooth.h>
- #include <bluetooth/scan.h>
- #include <bluetooth/services/ddfs.h>
- #include <dk_buttons_and_leds.h>
- /*2024.10.20 Sunday Engineer from here*/
- #include <zephyr/kernel.h>
- #include <zephyr/sys/printk.h>
- #include <zephyr/usb/usb_device.h>
- #include <zephyr/usb/usbd.h>
- #include <zephyr/drivers/uart.h>
- /*2024.10.20 Sunday Engineer to here*/
- #include <dm.h>
- #include "peer.h"
- #include "service.h"
- #define DEVICE_NAME CONFIG_BT_DEVICE_NAME
- #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
- #define RUN_STATUS_LED DK_LED2
- #define CON_STATUS_LED DK_LED3
- #define RUN_LED_BLINK_INTERVAL 1000
- #define SUPPORT_DM_CODE 0xFF55AA5A
- struct adv_mfg_data {
- uint16_t company_code; /* Company Identifier Code. */
- uint32_t support_dm_code; /* To identify the device that supports distance measurement. */
- uint32_t rng_seed; /* Random seed used for generating hopping patterns. */
- } __packed;
- static struct adv_mfg_data mfg_data;
- struct bt_le_adv_param adv_param_conn =
- BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE |
- BT_LE_ADV_OPT_NOTIFY_SCAN_REQ,
- BT_GAP_ADV_FAST_INT_MIN_2,
- BT_GAP_ADV_FAST_INT_MAX_2,
- NULL);
- struct bt_le_adv_param adv_param_noconn =
- BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_USE_IDENTITY |
- BT_LE_ADV_OPT_SCANNABLE |
- BT_LE_ADV_OPT_NOTIFY_SCAN_REQ,
- BT_GAP_ADV_FAST_INT_MIN_2,
- BT_GAP_ADV_FAST_INT_MAX_2,
- NULL);
- struct bt_le_adv_param *adv_param = &adv_param_conn;
- static const struct bt_data ad[] = {
- BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
- BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
- };
- static const struct bt_data sd[] = {
- BT_DATA(BT_DATA_MANUFACTURER_DATA, (unsigned char *)&mfg_data, sizeof(mfg_data)),
- BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_DDFS_VAL),
- };
- static struct bt_le_scan_param scan_param = {
- .type = BT_LE_SCAN_TYPE_ACTIVE,
- .interval = BT_GAP_SCAN_FAST_INTERVAL,
- .window = BT_GAP_SCAN_FAST_WINDOW,
- .options = BT_LE_SCAN_OPT_NONE,
- .timeout = 0,
- };
- static struct bt_scan_init_param scan_init = {
- .connect_if_match = 0,
- .scan_param = &scan_param,
- .conn_param = NULL
- };
- static uint32_t scanner_random_share;
- static struct bt_le_ext_adv *adv;
- static void adv_work_handle(struct k_work *item);
- static K_WORK_DEFINE(adv_work, adv_work_handle);
- static void adv_update_data(void);
- static uint32_t scanner_addr_to_random_share(const bt_addr_t *p_scanner_addr);
- static uint32_t get_id_addr_random_share(void);
- static struct bt_scan_manufacturer_data scan_mfg_data = {
- .data = (unsigned char *)&mfg_data,
- .data_len = sizeof(mfg_data.company_code) + sizeof(mfg_data.support_dm_code),
- };
- static bool data_cb(struct bt_data *data, void *user_data)
- {
- struct adv_mfg_data *recv_mfg_data;
- struct dm_request req;
- switch (data->type) {
- case BT_DATA_MANUFACTURER_DATA:
- if (sizeof(struct adv_mfg_data) == data->data_len) {
- recv_mfg_data = (struct adv_mfg_data *)data->data;
- bt_addr_le_copy(&req.bt_addr, user_data);
- req.role = DM_ROLE_INITIATOR;
- req.ranging_mode = peer_ranging_mode_get();
- /* We need to make sure that we only initiate a ranging to a single peer.
- * A scan response that is received by this device can be received by
- * multiple other devices which can all start a ranging at the same time
- * as a consequence. To prevent this, we need to make sure that we set a
- * per-peer random as the random seed. This helps the ranging library to
- * avoid interference from other devices trying to range at the same time.
- *
- * This means that the initiator and the reflector need to set the same
- * value for the random seed.
- */
- req.rng_seed =
- sys_le32_to_cpu(recv_mfg_data->rng_seed) + scanner_random_share;
- req.start_delay_us = 0;
- req.extra_window_time_us = 0;
- dm_request_add(&req);
- }
- return false;
- default:
- return true;
- }
- }
- static uint32_t get_id_addr_random_share(void)
- {
- bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
- size_t count = CONFIG_BT_ID_MAX;
- bt_id_get(addrs, &count);
- __ASSERT(count == 1, "The sample assumes a single ID addr");
- return scanner_addr_to_random_share(&addrs[0].a);
- }
- static uint32_t scanner_addr_to_random_share(const bt_addr_t *p_scanner_addr)
- {
- return (p_scanner_addr->val[0] | p_scanner_addr->val[1] << 8 |
- p_scanner_addr->val[2] << 16 | p_scanner_addr->val[3] << 24) +
- (p_scanner_addr->val[4] | p_scanner_addr->val[5] << 8);
- }
- static void scan_filter_match(struct bt_scan_device_info *device_info,
- struct bt_scan_filter_match *filter_match,
- bool connectable)
- {
- bt_addr_le_t addr;
- bt_addr_le_copy(&addr, device_info->recv_info->addr);
- peer_supported_add(device_info->recv_info->addr);
- bt_data_parse(device_info->adv_data, data_cb, &addr);
- }
- BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL, NULL, NULL);
- static void adv_scanned_cb(struct bt_le_ext_adv *adv,
- struct bt_le_ext_adv_scanned_info *info)
- {
- struct dm_request req;
- if (peer_supported_test(info->addr)) {
- bt_addr_le_copy(&req.bt_addr, info->addr);
- req.role = DM_ROLE_REFLECTOR;
- req.ranging_mode = peer_ranging_mode_get();
- /* We need to make sure that we only initiate a ranging to a single peer.
- * A scan response from this device can be received by multiple peers which can
- * all start a ranging at the same time as a consequence. To prevent this,
- * we need to make sure that we set a per-peer random as the random seed.
- * This helps the ranging library to avoid interference from other devices
- * trying to range at the same time.
- *
- * This means that the initiator and the reflector need to set the same value
- * for the random seed.
- */
- req.rng_seed = peer_rng_seed_get() + scanner_addr_to_random_share(&info->addr->a);
- req.start_delay_us = 0;
- req.extra_window_time_us = 0;
- dm_request_add(&req);
- adv_update_data();
- }
- }
- const static struct bt_le_ext_adv_cb adv_cb = {
- .scanned = adv_scanned_cb,
- };
- static void adv_update_data(void)
- {
- int err;
- if (!adv) {
- return;
- }
- mfg_data.rng_seed = peer_rng_seed_prepare();
- err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
- if (err) {
- printk("Failed setting adv data (err %d)\n", err);
- }
- }
- static int adv_start(void)
- {
- int err;
- struct bt_le_ext_adv_start_param ext_adv_start_param = {0};
- if (adv) {
- err = bt_le_ext_adv_stop(adv);
- if (err) {
- printk("Failed to stop extended advertising (err %d)\n", err);
- return err;
- }
- err = bt_le_ext_adv_delete(adv);
- if (err) {
- printk("Failed to delete advertising set (err %d)\n", err);
- return err;
- }
- }
- err = bt_le_ext_adv_create(adv_param, &adv_cb, &adv);
- if (err) {
- printk("Failed to create advertising set (err %d)\n", err);
- return err;
- }
- err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
- if (err) {
- printk("Failed setting adv data (err %d)\n", err);
- return err;
- }
- err = bt_le_ext_adv_start(adv, &ext_adv_start_param);
- if (err) {
- printk("Failed to start extended advertising (err %d)\n", err);
- return err;
- }
- return err;
- }
- static int scan_start(void)
- {
- int err;
- bt_scan_init(&scan_init);
- bt_scan_cb_register(&scan_cb);
- err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_MANUFACTURER_DATA, &scan_mfg_data);
- if (err) {
- printk("Scanning filters cannot be set (err %d)\n", err);
- return err;
- }
- err = bt_scan_filter_enable(BT_SCAN_MANUFACTURER_DATA_FILTER, false);
- if (err) {
- printk("Filters cannot be turned on (err %d)\n", err);
- return err;
- }
- scanner_random_share = get_id_addr_random_share();
- err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
- if (err) {
- printk("Scanning failed to start (err %d)\n", err);
- return err;
- }
- return err;
- }
- static void adv_work_handle(struct k_work *item)
- {
- adv_start();
- }
- static void connected(struct bt_conn *conn, uint8_t conn_err)
- {
- adv_param = &adv_param_noconn;
- k_work_submit(&adv_work);
- dk_set_led_on(CON_STATUS_LED);
- }
- static void disconnected(struct bt_conn *conn, uint8_t reason)
- {
- adv_param = &adv_param_conn;
- k_work_submit(&adv_work);
- dk_set_led_off(CON_STATUS_LED);
- }
- BT_CONN_CB_DEFINE(conn_callbacks) = {
- .connected = connected,
- .disconnected = disconnected,
- };
- static int bt_sync_init(void)
- {
- /* Synchronisation is based on advertising and scanning modes.
- * It occurs when SCAN_REQ and SCAN_RESP packets are exchanged.
- */
- int err;
- printk("DM Bluetooth LE Synchronization initialization\n");
- mfg_data.company_code = sys_cpu_to_le16(CONFIG_BT_COMPANY_ID_NORDIC);
- mfg_data.support_dm_code = sys_cpu_to_le32(SUPPORT_DM_CODE);
- mfg_data.rng_seed = sys_cpu_to_le32(peer_rng_seed_prepare());
- err = adv_start();
- if (err) {
- printk("Failed to start advertising (err %d)\n", err);
- return err;
- }
- err = scan_start();
- if (err) {
- printk("Failed to start scanning (err %d)\n", err);
- }
- return err;
- }
- static void data_ready(struct dm_result *result)
- {
- if (result->status) {
- peer_update(result);
- }
- }
- static struct dm_cb dm_cb = {
- .data_ready = data_ready,
- };
- /*2024.10.20 Sunday Engineer from here*/
- BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart),
- "Console device is not ACM CDC UART device");
- #if defined(CONFIG_USB_DEVICE_STACK_NEXT)
- static struct usbd_context *sample_usbd;
- static int enable_usb_device_next(void)
- {
- int err;
- sample_usbd = sample_usbd_init_device(NULL);
- if (sample_usbd == NULL) {
- return -ENODEV;
- }
- err = usbd_enable(sample_usbd);
- if (err) {
- return err;
- }
- return 0;
- }
- #endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK_NEXT) */
- /*2024.10.20 Sunday Engineer to here*/
- int main(void)
- {
- /*2024.10.20 Sunday Engineer from here*/
- const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
- uint32_t dtr = 0;
- #if defined(CONFIG_USB_DEVICE_STACK_NEXT)
- if (enable_usb_device_next()) {
- return 0;
- }
- #else
- if (usb_enable(NULL)) {
- return 0;
- }
- #endif
- /* Poll if the DTR flag was set */
- while (!dtr) {
- uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
- /* Give CPU resources to low priority threads. */
- k_sleep(K_MSEC(100));
- }
- //while (1) {
- printk("Hello World! %s\n", CONFIG_ARCH);
- k_sleep(K_SECONDS(1));
- //}
- /*2024.10.20 Sunday Engineer to here*/
- int err;
- uint32_t blink_status = 0;
- struct dm_init_param init_param;
- printk("Starting Distance Measurement example\n");
- err = dk_leds_init();
- if (err) {
- printk("LEDs init failed (err %d)\n", err);
- return 0;
- }
- err = peer_init();
- if (err) {
- printk("Peer init failed (err %d)\n", err);
- return 0;
- }
- init_param.cb = &dm_cb;
- err = dm_init(&init_param);
- if (err) {
- printk("Distance measurement init failed (err %d)\n", err);
- return 0;
- }
- err = service_ddfs_init();
- if (err) {
- printk("DDF Service init failed (err %d)\n", err);
- return 0;
- }
- err = bt_enable(NULL);
- if (err) {
- printk("Bluetooth init failed (err %d)\n", err);
- return 0;
- }
- err = bt_sync_init();
- if (err) {
- printk("Synchronisation init failed (err %d)\n", err);
- return 0;
- }
- for (;;) {
- dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
- k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
- service_azimuth_elevation_simulation();
- }
- }
↑の変更を適用した後、Add build configuration
Board targetのドロップダウンリストに52833と入力して、nrf52833dkを選ぶ
下のほうまでスクロールしてBuild Configuration
なんじゃかんじゃやっている
おわったっぽい、、、警告が13個もあるが、いったん、掘らない
実行とデバッグアイコンを押す
launch.jsonファイルを作成します。を押す
ここでの選択は全く意味ないけどCortex Debugを押す
エディタにlanuch.jsonが開くので、これを入力(てかコピペ)
今回もCMSIS-DAPと化したSeeeduinoXIAOを使う
- {
- "version": "0.2.0",
- "configurations": [
- {
- "name": "Cortex Debug",
- "type": "cortex-debug",
- "request": "launch",
- "servertype": "openocd",
- "cwd": "${workspaceRoot}",
- "executable": "${workspaceFolder}/build/zephyr/zephyr.elf",
- "configFiles": [
- "interface/cmsis-dap.cfg",
- "target/nrf52.cfg"
- ],
- "runToEntryPoint": "main",
- "postRestartCommands": [
- "break main",
- "continue"
- ],
- "serverpath": "/usr/bin/openocd", // OpenOCDのインストールパス
- "gdbPath": "/home/hoge/ncs/toolchains/e9dba88316/opt/zephyr-sdk/arm-zephyr-eabi/bin/arm-zephyr-eabi-gdb", // GDBのパス
- "armToolchainPath": "/home/hoge/ncs/toolchains/e9dba88316/opt/zephyr-sdk/arm-zephyr-eabi/bin/" // ARMツールチェーンのパス
- }
- ]
- }
デバッグを開始する
mainの直後でいったん止まる
再生ボタンを押す、、、とDTRフラグ待ち(USB接続待ちってことになるのかな?)になる
VSCodeのシリアルモニターで、ポートの再読み込みやらポートの選択やらして、監視の開始を押すとちゃんと動いていることがわかる
さらに再生ボタンを押す
ちゃんと動いているっぽい。で、一旦PCから取っ払って、もう1つのボードをつないで、デバッグを開始する部分からおんなじことをやる。
まぁ、こういう状態
で、さっきぶっこぬいたボードを、、、まぁうちの場合、WindowsPCのほうにつないでTeraTermでポートを開く(1つのPCでも問題ないはずなんやけど、紛らわしさを避けるために)と、
こんな感じで、両方のボードからコンソールに出力される、、、いくつかの方法で推定しているっぽい。まぁこの値、正しくはなさそうだけど、距離を変えたときにそれに伴って値が動くかどうかってのが重要。で、今日はしんどいので、ここまでにする。とりあえず、動くところまでいったところがえらいぞ、じぶん!いや、役に立つのかどうかわからんのに、時間やお金を自分に投資しているのがえらいぞ、じぶん!