В этой статье мы изучим технологию сверхширокополосной связи с использованием модуля ESP32 DW3000 UWB. Сверхширокополосная связь (Ultra-wideband, UWB) — это протокол беспроводной связи малого радиуса действия, работающий посредством радиоволн и обеспечивающий надежное и точное определение дальности и зондирование (определение местоположения), создавая новое измерение пространственного контекста для беспроводных устройств.
Микросхема приемопередатчика IC DecaWave DW3000 UWB позволяет определять местоположение объектов с точностью до 10 см. Микросхема DW3000 имеет всемирную поддержку UWB благодаря работе на канале UWB 5 (6,5 ГГц) и канале 9 (8 ГГц). DW3000 совместим с микросхемой Apple U1 , что позволяет работать с экосистемой Apple.
В этом уроке мы рассмотрим конструкцию платы, ее технические характеристики и приложения. Затем мы узнаем, как использовать плату ESP32 DW3000 для высокоточного определения дальности и локализации.
Прежде чем двигаться дальше, советуем ознакомиться с основными правилами измерения дальности с помощью модуля ESP32 DW1000 UWB.
Необходимые компоненты
- Плата ESP32 DW3000 (купить на AliExpress).
- Модуль OLED дисплея SSD1306 128×64 с интерфейсом I2C (купить на AliExpress).
- Кабель Micro-USB
- Макетная плата.
- Соединительные провода/перемычки.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Что такое сверхширокополосная связь и как она работает?
UWB — это беспроводной протокол связи ближнего действия, похожий на Bluetooth или Wi-Fi. Он также использует радиоволны для связи и работает на очень высокой частоте. Как следует из его названия, он также использует широкий спектр в несколько ГГц. Один из способов представить его как радар, который может непрерывно сканировать всю комнату и точно захватить объект, как лазерный луч, чтобы обнаружить его местоположение и передать данные.
Основная цель Ultra Wideband (сверхширокополосной связи) — обнаружение местоположения и определение дальности действия устройства. В то время как Wi-Fi и Bluetooth были модифицированы для обеспечения большей точности в определении местоположения других устройств и подключении к ним, UWB изначально более точен и потребляет меньше энергии.
Передатчик UWB работает, отправляя миллиарды импульсов по широкому спектру частот. Соответствующий приемник получает сигнал, который преобразует импульсы в данные, прослушивая знакомую последовательность импульсов, отправленную передатчиком. Импульсы отправляются примерно один раз в две наносекунды, что помогает UWB достичь высокой точности в реальном времени.
Понятия “anchor” («якорь») и “tag” («тег») важны для понимания измерения расстояния и местоположения с помощью UWB. Якорь — это, как правило, фиксированное устройство UWB с известным местоположением. Тег — это, как правило, мобильное устройство UWB. Якорь и тег обмениваются информацией для установления расстояния между ними. Точное местоположение тега можно определить, связавшись с несколькими якорями. Некоторые устройства могут действовать как якорь или тег.
Чип DW3000
Чип DW3000 — это микроконтроллерный чип, производимый компанией Decawave. Он используется при разработке сверхширокополосной (UWB) беспроводной технологии для услуг на основе определения местоположения и точного позиционирования внутри помещений. Чип предназначен для использования в таких приложениях, как отслеживание активов, промышленная автоматизация и робототехника. Он использует измерение времени пролета (ToF) для определения расстояния между устройствами, что позволяет выполнять точное позиционирование и отслеживание местоположения.
Модуль имеет всемирную поддержку UWB благодаря работе на канале UWB 5 (6,5 ГГц) и канале 9 (8 ГГц). DW3000 оптимизирован для работы с низким энергопотреблением от батареи и имеет гораздо меньшее энергопотребление, почти 1/3 от DW1000.
Особенности DW3000
- Совместимость с чипом Apple U1.
- Поддерживает UWB-каналы 5 (6,5 ГГц) и 9 (8 ГГц).
- Полностью соответствует FiRa™ PHY, MAC и разработке сертификации.
- Интегрированная UWB IC, UWB чип-антенна, управление питанием и кристалл упрощают интеграцию проекта.
- Оптимизирован для работы от аккумулятора с низким энергопотреблением.
- Позволяет экономически эффективно внедрять решения UWB.
- Напряжение питания: от 2,5 до 3,6 В (VDD3V3), от 1,62 до 3,6 В (VDD1).
Применение DW3000
- Высокоточные системы определения местоположения в реальном времени.
- Беспроводные сенсорные сети с определением местоположения.
- Отслеживание активов.
- Автоматизация и безопасность завода/склада.
- Медицинский персонал и местоположение пациента.
- Безопасность розничной торговли, навигация и аналитика клиентов.
- Подключенный дом.
Плата ESP32 DW3000 UWB (сверхширокополосная)
Модуль ESP32 UWB Ultra Wideband состоит из Decawave DW3000 и модуля ESP32 WiFi. Эта плата производится компанией Makerfabs. Плата действует как непрерывно сканирующий радар, который точно фиксируется на другом устройстве (называемом Anchor) и связывается с ним, таким образом вычисляя свое собственное местоположение. Самое лучшее в плате то, что она совместима с чипом Apple U1, что позволяет работать с системой Apple.
Верхняя сторона платы имеет встроенный модуль ESP32 WROOM/Wrover с модулем DW3000 и другими пассивными электронными компонентами. Есть две кнопки, одна для вспышки, другая для отдыха. Плата имеет порт micro-USB для загрузки прошивки и для последовательной связи.
На задней стороне платы находится чип CP2102 для связи UART. Наименование портов ввода/вывода также указано на плате. Вы можете использовать штыревые или гнездовые разъемы и паять с обеих сторон платы.
Установка библиотеки DW3000
Для использования DW3000 с ESP32 в Arduino IDE нам нужна библиотека DW3000. Библиотека DW3000 предлагает функционал для использования чипов/модулей DW3000 от Decawave с любым микроконтроллером.
Библиотека DW3000 была разработана компанией NConcepts, но вы можете загрузить ее из следующего репозитория GitHub, поддерживаемого Makerfabs.
Библиотека поддерживает передачу сообщений и обработку временных меток (для приложений определения дальности и местоположения), а также реализует различные режимы работы, которые может предложить DW3000. Проект библиотеки призван предложить простой в использовании интерфейс для сложного и требующего больших настроек управления DW3000.
Настройка оборудования для якоря и тега
Давайте узнаем, как использовать плату ESP32 DW3000 UWB (Ultra Wideband) с Arduino IDE и измерить расстояние между платами. Для этого проекта вам понадобится пара плат. Одна из плат будет действовать как якорь, а другая как тег.
Для части Anchor (якоря) нам не нужно ничего, кроме кабеля Micro-USB. Но для части tag (тег) нам нужен 0,96″ I2C OLED дисплей и Powerbank. I2C OLED будет отображать расстояние тега (Tag) от якоря (Anchor). Powerbank или батарея будут обеспечивать питание подвижной Tag.
На теговой части подключите контакты I2C OLED-дисплея 0,96″ I2C (SDA и SCL) к контактам ESP32 GP21 и GP22. Подключите контакты VCC и GND OLED-дисплея к контактам ESP32 3,3 В и GND.
Исходный код программы для тестирования дальности
Код, который мы будем использовать для тестирования платы ESP32 DW3000, взят из примера библиотеки. Используя этот пример, мы можем провести тестирование диапазона, который фактически лежит в диапазоне 10-20 метров.
Прежде чем перейти к части тестирования, нам нужно понять что собой представляет калибровка задержки антенны. В сверхширокополосных (UWB) системах калибровка задержки антенны — это процесс измерения и компенсации внутренней задержки времени, которая возникает между передачей и приемом сигнала из-за физических свойств антенны. Эта задержка может меняться в зависимости от таких факторов, как частота сигнала, размер и форма антенны, а также расстояние между передатчиком и приемником. Калибровка задержки антенны важна для обеспечения точных измерений времени пролета (ToF) в системах UWB и для улучшения общей производительности системы. Это можно сделать, измерив импульсную характеристику канала и затем компенсировав задержку.
Для нашей части кода мы установили значения задержки антенны по умолчанию для частоты повторения импульсов 64 МГц как 16385. Вы можете изменить их в соответствии с поведением вашего UWB-модуля и точностью измерения дальности в следующих строках кода.
1 2 3 |
/* Default antenna delay values for 64 MHz PRF. See NOTE 2 below. */ #define TX_ANT_DLY 16385 #define RX_ANT_DLY 16385 |
Чтобы измерить расстояние между платами, нам необходимо загрузить код «Anchor» на одну плату ESP32, а код «Tag» на другую плату ESP32.
Код якоря
Скопируйте следующий код и загрузите его на первую плату UWB (сверхширокополосную), которая является якорной.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
#include "dw3000.h" #define APP_NAME "SS TWR RESP v1.0" // connection pins const uint8_t PIN_RST = 27; // reset pin const uint8_t PIN_IRQ = 34; // irq pin const uint8_t PIN_SS = 4; // spi select pin /* Default communication configuration. We use default non-STS DW mode. */ static dwt_config_t config = { 5, /* Channel number. */ DWT_PLEN_128, /* Preamble length. Used in TX only. */ DWT_PAC8, /* Preamble acquisition chunk size. Used in RX only. */ 9, /* TX preamble code. Used in TX only. */ 9, /* RX preamble code. Used in RX only. */ 1, /* 0 to use standard 8 symbol SFD, 1 to use non-standard 8 symbol, 2 for non-standard 16 symbol SFD and 3 for 4z 8 symbol SDF type */ DWT_BR_6M8, /* Data rate. */ DWT_PHRMODE_STD, /* PHY header mode. */ DWT_PHRRATE_STD, /* PHY header rate. */ (129 + 8 - 8), /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */ DWT_STS_MODE_OFF, /* STS disabled */ DWT_STS_LEN_64,/* STS length see allowed values in Enum dwt_sts_lengths_e */ DWT_PDOA_M0 /* PDOA mode off */ }; /* Default antenna delay values for 64 MHz PRF. See NOTE 2 below. */ #define TX_ANT_DLY 16385 #define RX_ANT_DLY 16385 /* Frames used in the ranging process. See NOTE 3 below. */ static uint8_t rx_poll_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, 'W', 'A', 'V', 'E', 0xE0, 0, 0}; static uint8_t tx_resp_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, 'V', 'E', 'W', 'A', 0xE1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* Length of the common part of the message (up to and including the function code, see NOTE 3 below). */ #define ALL_MSG_COMMON_LEN 10 /* Index to access some of the fields in the frames involved in the process. */ #define ALL_MSG_SN_IDX 2 #define RESP_MSG_POLL_RX_TS_IDX 10 #define RESP_MSG_RESP_TX_TS_IDX 14 #define RESP_MSG_TS_LEN 4 /* Frame sequence number, incremented after each transmission. */ static uint8_t frame_seq_nb = 0; /* Buffer to store received messages. Its size is adjusted to longest frame that this example code is supposed to handle. */ #define RX_BUF_LEN 12//Must be less than FRAME_LEN_MAX_EX static uint8_t rx_buffer[RX_BUF_LEN]; /* Hold copy of status register state here for reference so that it can be examined at a debug breakpoint. */ static uint32_t status_reg = 0; /* Delay between frames, in UWB microseconds. See NOTE 1 below. */ #ifdef RPI_BUILD #define POLL_RX_TO_RESP_TX_DLY_UUS 550 #endif //RPI_BUILD #ifdef STM32F429xx #define POLL_RX_TO_RESP_TX_DLY_UUS 450 #endif //STM32F429xx #ifdef NRF52840_XXAA #define POLL_RX_TO_RESP_TX_DLY_UUS 650 #endif //NRF52840_XXAA #define POLL_RX_TO_RESP_TX_DLY_UUS 450 /* Timestamps of frames transmission/reception. */ static uint64_t poll_rx_ts; static uint64_t resp_tx_ts; /* Values for the PG_DELAY and TX_POWER registers reflect the bandwidth and power of the spectrum at the current temperature. These values can be calibrated prior to taking reference measurements. See NOTE 5 below. */ extern dwt_txconfig_t txconfig_options; void setup() { UART_init(); test_run_info((unsigned char *)APP_NAME); /* Configure SPI rate, DW3000 supports up to 38 MHz */ /* Reset DW IC */ spiBegin(PIN_IRQ, PIN_RST); spiSelect(PIN_SS); delay(2); // Time needed for DW3000 to start up (transition from INIT_RC to IDLE_RC, or could wait for SPIRDY event) while (!dwt_checkidlerc()) // Need to make sure DW IC is in IDLE_RC before proceeding { UART_puts("IDLE FAILED\r\n"); while (1) ; } if (dwt_initialise(DWT_DW_INIT) == DWT_ERROR) { UART_puts("INIT FAILED\r\n"); while (1) ; } // Enabling LEDs here for debug so that for each TX the D1 LED will flash on DW3000 red eval-shield boards. dwt_setleds(DWT_LEDS_ENABLE | DWT_LEDS_INIT_BLINK); /* Configure DW IC. See NOTE 6 below. */ if (dwt_configure(&config)) // if the dwt_configure returns DWT_ERROR either the PLL or RX calibration has failed the host should reset the device { UART_puts("CONFIG FAILED\r\n"); while (1) ; } /* Configure the TX spectrum parameters (power, PG delay and PG count) */ dwt_configuretxrf(&txconfig_options); /* Apply default antenna delay value. See NOTE 2 below. */ dwt_setrxantennadelay(RX_ANT_DLY); dwt_settxantennadelay(TX_ANT_DLY); /* Next can enable TX/RX states output on GPIOs 5 and 6 to help debug, and also TX/RX LEDs Note, in real low power applications the LEDs should not be used. */ dwt_setlnapamode(DWT_LNA_ENABLE | DWT_PA_ENABLE); } void loop() { /* Activate reception immediately. */ dwt_rxenable(DWT_START_RX_IMMEDIATE); /* Poll for reception of a frame or error/timeout. See NOTE 6 below. */ while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_ALL_RX_ERR))) { }; if (status_reg & SYS_STATUS_RXFCG_BIT_MASK) { uint32_t frame_len; /* Clear good RX frame event in the DW IC status register. */ dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG_BIT_MASK); /* A frame has been received, read it into the local buffer. */ frame_len = dwt_read32bitreg(RX_FINFO_ID) & RXFLEN_MASK; if (frame_len <= sizeof(rx_buffer)) { dwt_readrxdata(rx_buffer, frame_len, 0); /* Check that the frame is a poll sent by "SS TWR initiator" example. As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */ rx_buffer[ALL_MSG_SN_IDX] = 0; if (memcmp(rx_buffer, rx_poll_msg, ALL_MSG_COMMON_LEN) == 0) { uint32_t resp_tx_time; int ret; /* Retrieve poll reception timestamp. */ poll_rx_ts = get_rx_timestamp_u64(); /* Compute response message transmission time. See NOTE 7 below. */ resp_tx_time = (poll_rx_ts + (POLL_RX_TO_RESP_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8; dwt_setdelayedtrxtime(resp_tx_time); /* Response TX timestamp is the transmission time we programmed plus the antenna delay. */ resp_tx_ts = (((uint64_t)(resp_tx_time & 0xFFFFFFFEUL)) << 8) + TX_ANT_DLY; /* Write all timestamps in the final message. See NOTE 8 below. */ resp_msg_set_ts(&tx_resp_msg[RESP_MSG_POLL_RX_TS_IDX], poll_rx_ts); resp_msg_set_ts(&tx_resp_msg[RESP_MSG_RESP_TX_TS_IDX], resp_tx_ts); /* Write and send the response message. See NOTE 9 below. */ tx_resp_msg[ALL_MSG_SN_IDX] = frame_seq_nb; dwt_writetxdata(sizeof(tx_resp_msg), tx_resp_msg, 0); /* Zero offset in TX buffer. */ dwt_writetxfctrl(sizeof(tx_resp_msg), 0, 1); /* Zero offset in TX buffer, ranging. */ ret = dwt_starttx(DWT_START_TX_DELAYED); /* If dwt_starttx() returns an error, abandon this ranging exchange and proceed to the next one. See NOTE 10 below. */ if (ret == DWT_SUCCESS) { /* Poll DW IC until TX frame sent event set. See NOTE 6 below. */ while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS_BIT_MASK)) { }; /* Clear TXFRS event. */ dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS_BIT_MASK); /* Increment frame sequence number after transmission of the poll message (modulo 256). */ frame_seq_nb++; } } } } else { /* Clear RX error events in the DW IC status register. */ dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR); } } |
Код тега
Скопируйте следующий код и загрузите его на вторую плату UWB (сверхширокополосную) под названием Tag.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 |
#include "dw3000.h" #include <Wire.h> #include <Adafruit_SSD1306.h> #define APP_NAME "SS TWR INIT v1.0" #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN_ADDRESS 0x3C // 0x3D for 128x64, 0x3C for 128x32 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // connection pins const uint8_t PIN_RST = 27; // reset pin const uint8_t PIN_IRQ = 34; // irq pin const uint8_t PIN_SS = 4; // spi select pin /* Default communication configuration. We use default non-STS DW mode. */ static dwt_config_t config = { 5, /* Channel number. */ DWT_PLEN_128, /* Preamble length. Used in TX only. */ DWT_PAC8, /* Preamble acquisition chunk size. Used in RX only. */ 9, /* TX preamble code. Used in TX only. */ 9, /* RX preamble code. Used in RX only. */ 1, /* 0 to use standard 8 symbol SFD, 1 to use non-standard 8 symbol, 2 for non-standard 16 symbol SFD and 3 for 4z 8 symbol SDF type */ DWT_BR_6M8, /* Data rate. */ DWT_PHRMODE_STD, /* PHY header mode. */ DWT_PHRRATE_STD, /* PHY header rate. */ (129 + 8 - 8), /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */ DWT_STS_MODE_OFF, /* STS disabled */ DWT_STS_LEN_64,/* STS length see allowed values in Enum dwt_sts_lengths_e */ DWT_PDOA_M0 /* PDOA mode off */ }; /* Inter-ranging delay period, in milliseconds. */ #define RNG_DELAY_MS 1000 /* Default antenna delay values for 64 MHz PRF. See NOTE 2 below. */ #define TX_ANT_DLY 16385 #define RX_ANT_DLY 16385 /* Frames used in the ranging process. See NOTE 3 below. */ static uint8_t tx_poll_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, 'W', 'A', 'V', 'E', 0xE0, 0, 0}; static uint8_t rx_resp_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, 'V', 'E', 'W', 'A', 0xE1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* Length of the common part of the message (up to and including the function code, see NOTE 3 below). */ #define ALL_MSG_COMMON_LEN 10 /* Indexes to access some of the fields in the frames defined above. */ #define ALL_MSG_SN_IDX 2 #define RESP_MSG_POLL_RX_TS_IDX 10 #define RESP_MSG_RESP_TX_TS_IDX 14 #define RESP_MSG_TS_LEN 4 /* Frame sequence number, incremented after each transmission. */ static uint8_t frame_seq_nb = 0; /* Buffer to store received response message. Its size is adjusted to longest frame that this example code is supposed to handle. */ #define RX_BUF_LEN 20 static uint8_t rx_buffer[RX_BUF_LEN]; /* Hold copy of status register state here for reference so that it can be examined at a debug breakpoint. */ static uint32_t status_reg = 0; /* Delay between frames, in UWB microseconds. See NOTE 1 below. */ #ifdef RPI_BUILD #define POLL_TX_TO_RESP_RX_DLY_UUS 240 #endif //RPI_BUILD #ifdef STM32F429xx #define POLL_TX_TO_RESP_RX_DLY_UUS 240 #endif //STM32F429xx #ifdef NRF52840_XXAA #define POLL_TX_TO_RESP_RX_DLY_UUS 240 #endif //NRF52840_XXAA /* Receive response timeout. See NOTE 5 below. */ #ifdef RPI_BUILD #define RESP_RX_TIMEOUT_UUS 270 #endif //RPI_BUILD #ifdef STM32F429xx #define RESP_RX_TIMEOUT_UUS 210 #endif //STM32F429xx #ifdef NRF52840_XXAA #define RESP_RX_TIMEOUT_UUS 400 #endif //NRF52840_XXAA #define POLL_TX_TO_RESP_RX_DLY_UUS 240 #define RESP_RX_TIMEOUT_UUS 400 /* Hold copies of computed time of flight and distance here for reference so that it can be examined at a debug breakpoint. */ static double tof; static double distance; /* Values for the PG_DELAY and TX_POWER registers reflect the bandwidth and power of the spectrum at the current temperature. These values can be calibrated prior to taking reference measurements. See NOTE 2 below. */ extern dwt_txconfig_t txconfig_options; void setup() { UART_init(); test_run_info((unsigned char *)APP_NAME); Wire.begin(); if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for (;;); // Don't proceed, loop forever } display.clearDisplay(); /* Configure SPI rate, DW3000 supports up to 38 MHz */ /* Reset DW IC */ spiBegin(PIN_IRQ, PIN_RST); spiSelect(PIN_SS); delay(2); // Time needed for DW3000 to start up (transition from INIT_RC to IDLE_RC, or could wait for SPIRDY event) while (!dwt_checkidlerc()) // Need to make sure DW IC is in IDLE_RC before proceeding { UART_puts("IDLE FAILED\r\n"); while (1) ; } if (dwt_initialise(DWT_DW_INIT) == DWT_ERROR) { UART_puts("INIT FAILED\r\n"); while (1) ; } // Enabling LEDs here for debug so that for each TX the D1 LED will flash on DW3000 red eval-shield boards. dwt_setleds(DWT_LEDS_ENABLE | DWT_LEDS_INIT_BLINK); /* Configure DW IC. See NOTE 6 below. */ if (dwt_configure(&config)) // if the dwt_configure returns DWT_ERROR either the PLL or RX calibration has failed the host should reset the device { UART_puts("CONFIG FAILED\r\n"); while (1) ; } /* Configure the TX spectrum parameters (power, PG delay and PG count) */ dwt_configuretxrf(&txconfig_options); /* Apply default antenna delay value. See NOTE 2 below. */ dwt_setrxantennadelay(RX_ANT_DLY); dwt_settxantennadelay(TX_ANT_DLY); /* Set expected response's delay and timeout. See NOTE 1 and 5 below. As this example only handles one incoming frame with always the same delay and timeout, those values can be set here once for all. */ dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS); dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS); /* Next can enable TX/RX states output on GPIOs 5 and 6 to help debug, and also TX/RX LEDs Note, in real low power applications the LEDs should not be used. */ dwt_setlnapamode(DWT_LNA_ENABLE | DWT_PA_ENABLE); } void loop() { /* Write frame data to DW IC and prepare transmission. See NOTE 7 below. */ tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb; dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS_BIT_MASK); dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0); /* Zero offset in TX buffer. */ dwt_writetxfctrl(sizeof(tx_poll_msg), 0, 1); /* Zero offset in TX buffer, ranging. */ /* Start transmission, indicating that a response is expected so that reception is enabled automatically after the frame is sent and the delay set by dwt_setrxaftertxdelay() has elapsed. */ dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED); /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */ while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR))) { }; /* Increment frame sequence number after transmission of the poll message (modulo 256). */ frame_seq_nb++; if (status_reg & SYS_STATUS_RXFCG_BIT_MASK) { uint32_t frame_len; /* Clear good RX frame event in the DW IC status register. */ dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG_BIT_MASK); /* A frame has been received, read it into the local buffer. */ frame_len = dwt_read32bitreg(RX_FINFO_ID) & RXFLEN_MASK; if (frame_len <= sizeof(rx_buffer)) { dwt_readrxdata(rx_buffer, frame_len, 0); /* Check that the frame is the expected response from the companion "SS TWR responder" example. As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */ rx_buffer[ALL_MSG_SN_IDX] = 0; if (memcmp(rx_buffer, rx_resp_msg, ALL_MSG_COMMON_LEN) == 0) { uint32_t poll_tx_ts, resp_rx_ts, poll_rx_ts, resp_tx_ts; int32_t rtd_init, rtd_resp; float clockOffsetRatio ; /* Retrieve poll transmission and response reception timestamps. See NOTE 9 below. */ poll_tx_ts = dwt_readtxtimestamplo32(); resp_rx_ts = dwt_readrxtimestamplo32(); /* Read carrier integrator value and calculate clock offset ratio. See NOTE 11 below. */ clockOffsetRatio = ((float)dwt_readclockoffset()) / (uint32_t)(1 << 26); /* Get timestamps embedded in response message. */ resp_msg_get_ts(&rx_buffer[RESP_MSG_POLL_RX_TS_IDX], &poll_rx_ts); resp_msg_get_ts(&rx_buffer[RESP_MSG_RESP_TX_TS_IDX], &resp_tx_ts); /* Compute time of flight and distance, using clock offset ratio to correct for differing local and remote clock rates */ rtd_init = resp_rx_ts - poll_tx_ts; rtd_resp = resp_tx_ts - poll_rx_ts; tof = ((rtd_init - rtd_resp * (1 - clockOffsetRatio)) / 2.0) * DWT_TIME_UNITS; distance = tof * SPEED_OF_LIGHT; /* Display computed distance on LCD. */ snprintf(dist_str, sizeof(dist_str), "DIST: %3.2f m", distance); test_run_info((unsigned char *)dist_str); display.setCursor(15, 0); //oled display display.setTextSize(2); display.setTextColor(WHITE); display.print("Distance"); display.setCursor(30, 30); //oled display display.setTextSize(2); display.print(distance); display.print("m"); display.display(); display.clearDisplay(); } } } else { /* Clear RX error/timeout events in the DW IC status register. */ dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR); } /* Execute a delay between ranging exchanges. */ Sleep(RNG_DELAY_MS); } |
Тест дальности с модулем ESP32 UWB DW3000
После загрузки кода якоря и кода тега устройства готовы к тестированию. Чтобы проверить дальность и точность, вы можете отметить расстояние на полу или на столе.
Я отметил расстояние в 1 метр и между ними отметил позиции 30 см, 50 см, 75 см, 100 см. Теперь устройство готово к тестированию.
На расстоянии 30 см он показывает расстояние 28 см.
На расстоянии 50 см он показывает расстояние 48 см.
При увеличении расстояния до 75 см он показывает расстояние 77 см.
Наконец, для расстояния 100 см он показывает расстояние 107 см.
Но для этого все еще требуется тест на расстояние 10 метров или больше. Поэтому я вышел на улицу, чтобы проверить расстояния. Со мной двое моих друзей, которые помогут мне протестировать этот продукт даже в такую холодную снежную погоду. У одного из друзей на руке Tag, и он питает модуль ESP32 UWB с помощью внешнего аккумулятора. У другого друга есть Anchor, который питается от ноутбука.
Когда метка находилась рядом, обнаруженное расстояние составляло почти 2 метра. При удалении от метки обнаруженное расстояние составляло почти 11,77 метра.
При дальнейшем перемещении на большее расстояние OLED показывает расстояние 23,75 метра. Затем он перестал принимать сигналы. Таким образом, по результатам нашего теста максимальное обнаруженное расстояние составило почти 24 метра, что превышает максимальную измерительную способность в 20 метров.
В целом, мы остались довольны работой и точностью модуля DW3000 UWB. Следовательно, мы можем сказать, что вы можете использовать этот модуль для высокоточной локализации и тестирования. Плата ESP32 DW3000 UWB также интерполирует с чипом Apple, что также требует тестирования.