简体中文
English
简体中文
日本語

Arduino 上手教程

2. 设备开发 & 案例程序

5. 扩展模块

6. 应用案例

Stamp UWB F Arduino 使用教程

1. 准备工作

2. 注意事项

注意
1. 为保证通信质量,请使用高 PSRR LDO 或电源纹波在 12mVpp 以内的电源给 Stamp UWB 供电。
2. UWB 测距至少需要 2 个设备,其中一个设备作为 Tag,另一个设备作为 Anchor。
3. 在进行整机设计时,请注意 FPC 排线及其连接器对模组天线性能的影响。FPC 排线不得经过模组 PCB 天线下方或天线净空区域,否则可能改变天线阻抗和辐射特性,降低射频性能并引入测距误差。建议将 FPC 排线布置在天线区域之外,并在整机装配完成后进行实际测试,以确保产品的通信距离和测距精度满足设计要求。

引脚兼容性
Stamp UWB 通过 SPI 接口通信。下方例程使用 Stamp C5 作为主控,使用其他主控或载板时,需要根据实际接线修改程序中的引脚定义。

Stamp C5 与 Stamp UWB F 的引脚连接如下:

Stamp UWB F 引脚 Stamp C5 GPIO
GP7 G23
IRQ G0
WAKEUP G24
RST G25
MISO G26
MOSI G27
CS G11
SCK G12

3. 双边测距(DS-TWR)

3.1 Tag 端

cpp
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
#include <Arduino.h>
#include <M5Stamp_UWB.h>

static constexpr uint32_t RANGE_INTERVAL_MS = 200;
static constexpr uint32_t LOG_INTERVAL      = 10;

M5Stamp_UWB uwb;
M5Stamp_UWBDSRangeConfig rangeConfig;
bool uwbReady        = false;
uint32_t lastRangeMs = 0;
uint32_t rangeCount  = 0;
uint32_t okCount     = 0;

static bool initUwb()
{
    // Stamp-C5 connections to the onboard QM33120 UWB transceiver.
    M5Stamp_UWBConfig config;
    config.pin_gp7    = 23;
    config.pin_irq    = 0;
    config.pin_wakeup = 24;
    config.pin_rst    = 25;
    config.pin_miso   = 26;
    config.pin_mosi   = 27;
    config.pin_cs     = 11;
    config.pin_sck    = 12;

    M5Stamp_UWBPHYConfig phy;
    phy.channel = M5Stamp_UWBChannel::Channel5;

    // Both devices must use the same network addresses and DS-TWR timing.
    rangeConfig.panId                          = 0xDECA;
    rangeConfig.initiatorAddress               = 0x0001;
    rangeConfig.responderAddress               = 0x0002;
    rangeConfig.responseRxAfterTxDelayUus      = 1500;
    rangeConfig.responseTxDelayUus             = 3000;
    rangeConfig.finalTxDelayUus                = 1800;
    rangeConfig.finalRxAfterResponseTxDelayUus = 500;
    rangeConfig.resultRxAfterFinalTxDelayUus   = 500;
    rangeConfig.rxTimeoutUus                   = 3000;
    rangeConfig.hostTimeoutMs                  = 100;
    rangeConfig.resultRepeatCount              = 3;
    rangeConfig.resultRepeatGapMs              = 3;

    if (!uwb.begin(config, phy)) {
        Serial.printf("UWB_BEGIN,result=FAIL,error=%s\n", uwb.lastErrorName());
        Serial.printf("UWB_RAW_ID,dev_id=0x%08lX\n", static_cast<unsigned long>(uwb.readRawDeviceId()));
        return false;
    }

    const uint32_t devId = uwb.deviceId();
    Serial.printf("UWB_ID,dev_id=0x%08lX,chip=%s\n", static_cast<unsigned long>(devId), uwb.chipName());
    if (devId != M5STAMP_UWB_QM33120_DEVICE_ID) {
        Serial.printf("UWB_ID,result=FAIL,expected=0xDECA0314\n");
        return false;
    }

    Serial.printf("UWB_CONFIG,result=OK,ch=%u,plen=%u,rate=6M8,tx_power=0x%08lX\n", static_cast<unsigned>(phy.channel),
                  static_cast<unsigned>(phy.preambleLength), static_cast<unsigned long>(phy.txPower));
    return true;
}

static void runRanging()
{
    // Start one DS-TWR exchange at the configured interval.
    if (millis() - lastRangeMs < RANGE_INTERVAL_MS) return;
    lastRangeMs = millis();

    const M5Stamp_UWBDSRangeResult result = uwb.requestDSRange(rangeConfig);
    rangeCount++;
    okCount += result.success;

    // Print accumulated statistics every LOG_INTERVAL attempts.
    if (rangeCount % LOG_INTERVAL) return;

    const uint32_t failCount = rangeCount - okCount;
    if (result.success) {
        Serial.printf(
            "DS_RANGE_STAT,count=%lu,ok=%lu,fail=%lu,last=OK,seq=%u,distance_mm=%ld,distance_m=%.3f,elapsed_ms=%lu\n",
            static_cast<unsigned long>(rangeCount), static_cast<unsigned long>(okCount),
            static_cast<unsigned long>(failCount), result.sequence, static_cast<long>(result.distanceMm),
            result.distanceM, static_cast<unsigned long>(result.elapsedMs));
    } else {
        Serial.printf("DS_RANGE_STAT,count=%lu,ok=%lu,fail=%lu,last=FAIL,seq=%u,error=%s\n",
                      static_cast<unsigned long>(rangeCount), static_cast<unsigned long>(okCount),
                      static_cast<unsigned long>(failCount), result.sequence, uwb.lastErrorName());
    }
}

void setup()
{
    Serial.begin(115200);
    delay(1000);
    Serial.printf("M5Stamp UWB DS-TWR TAG\n");
    Serial.printf("ROLE,mode=TAG\n");
    Serial.printf("TWR_MODE,mode=DS-TWR\n");
    uwbReady = initUwb();
    Serial.printf("TEST_START,result=%s\n", uwbReady ? "OK" : "FAIL");
}

void loop()
{
    if (uwbReady) runRanging();
    else delay(1000);
}

串口输出示例:

M5Stamp UWB DS-TWR TAG
ROLE,mode=TAG
TWR_MODE,mode=DS-TWR
UWB_ID,dev_id=0xDECA0314,chip=QM33120/DW3720
UWB_CONFIG,result=OK,ch=5,plen=128,rate=6M8,tx_power=0xFEFEFEFE
TEST_START,result=OK
DS_RANGE_STAT,count=10,ok=10,fail=0,last=OK,seq=10,distance_mm=164,distance_m=0.164,elapsed_ms=7
DS_RANGE_STAT,count=20,ok=20,fail=0,last=OK,seq=20,distance_mm=166,distance_m=0.166,elapsed_ms=7
DS_RANGE_STAT,count=30,ok=30,fail=0,last=OK,seq=30,distance_mm=171,distance_m=0.171,elapsed_ms=7
DS_RANGE_STAT,count=40,ok=40,fail=0,last=OK,seq=40,distance_mm=168,distance_m=0.168,elapsed_ms=7
DS_RANGE_STAT,count=50,ok=50,fail=0,last=OK,seq=50,distance_mm=153,distance_m=0.153,elapsed_ms=7
DS_RANGE_STAT,count=60,ok=60,fail=0,last=OK,seq=60,distance_mm=196,distance_m=0.196,elapsed_ms=7
DS_RANGE_STAT,count=70,ok=70,fail=0,last=OK,seq=70,distance_mm=172,distance_m=0.172,elapsed_ms=7
DS_RANGE_STAT,count=80,ok=80,fail=0,last=OK,seq=80,distance_mm=182,distance_m=0.182,elapsed_ms=7
DS_RANGE_STAT,count=90,ok=90,fail=0,last=OK,seq=90,distance_mm=160,distance_m=0.160,elapsed_ms=7
DS_RANGE_STAT,count=100,ok=100,fail=0,last=OK,seq=100,distance_mm=157,distance_m=0.157,elapsed_ms=7
DS_RANGE_STAT,count=110,ok=110,fail=0,last=OK,seq=110,distance_mm=210,distance_m=0.210,elapsed_ms=7
DS_RANGE_STAT,count=120,ok=120,fail=0,last=OK,seq=120,distance_mm=164,distance_m=0.164,elapsed_ms=7
DS_RANGE_STAT,count=130,ok=130,fail=0,last=OK,seq=130,distance_mm=174,distance_m=0.174,elapsed_ms=7

3.2 Anchor 端

cpp
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
#include <Arduino.h>
#include <M5Stamp_UWB.h>

static constexpr uint32_t LOG_INTERVAL = 20;

M5Stamp_UWB uwb;
M5Stamp_UWBDSRangeConfig rangeConfig;
bool uwbReady          = false;
uint32_t responseCount = 0;
uint32_t failCount     = 0;

static bool initUwb()
{
    // Stamp-C5 connections to the onboard QM33120 UWB transceiver.
    M5Stamp_UWBConfig config;
    config.pin_gp7    = 23;
    config.pin_irq    = 0;
    config.pin_wakeup = 24;
    config.pin_rst    = 25;
    config.pin_miso   = 26;
    config.pin_mosi   = 27;
    config.pin_cs     = 11;
    config.pin_sck    = 12;

    M5Stamp_UWBPHYConfig phy;
    phy.channel = M5Stamp_UWBChannel::Channel5;

    // Both devices must use the same network addresses and DS-TWR timing.
    rangeConfig.panId                          = 0xDECA;
    rangeConfig.initiatorAddress               = 0x0001;
    rangeConfig.responderAddress               = 0x0002;
    rangeConfig.responseRxAfterTxDelayUus      = 1500;
    rangeConfig.responseTxDelayUus             = 3000;
    rangeConfig.finalTxDelayUus                = 1800;
    rangeConfig.finalRxAfterResponseTxDelayUus = 500;
    rangeConfig.resultRxAfterFinalTxDelayUus   = 500;
    rangeConfig.rxTimeoutUus                   = 3000;
    rangeConfig.hostTimeoutMs                  = 100;
    rangeConfig.resultRepeatCount              = 3;
    rangeConfig.resultRepeatGapMs              = 3;

    if (!uwb.begin(config, phy)) {
        Serial.printf("UWB_BEGIN,result=FAIL,error=%s\n", uwb.lastErrorName());
        Serial.printf("UWB_RAW_ID,dev_id=0x%08lX\n", static_cast<unsigned long>(uwb.readRawDeviceId()));
        return false;
    }

    const uint32_t devId = uwb.deviceId();
    Serial.printf("UWB_ID,dev_id=0x%08lX,chip=%s\n", static_cast<unsigned long>(devId), uwb.chipName());
    if (devId != M5STAMP_UWB_QM33120_DEVICE_ID) {
        Serial.printf("UWB_ID,result=FAIL,expected=0xDECA0314\n");
        return false;
    }

    Serial.printf("UWB_CONFIG,result=OK,ch=%u,plen=%u,rate=6M8,tx_power=0x%08lX\n", static_cast<unsigned>(phy.channel),
                  static_cast<unsigned>(phy.preambleLength), static_cast<unsigned long>(phy.txPower));
    return true;
}

static void runResponder()
{
    // Wait for a Poll/Final exchange and return the DS-TWR distance result.
    const M5Stamp_UWBDSResponderResult result = uwb.respondDSRange(rangeConfig);
    if (!result.success) {
        // Idle receive timeouts are expected and are not counted as failures.
        if (result.error == M5Stamp_UWBError::RxTimeout) return;
        if (++failCount % LOG_INTERVAL == 0) {
            Serial.printf("DS_RESP_STAT,count=%lu,fail=%lu,last=FAIL,error=%s\n",
                          static_cast<unsigned long>(responseCount), static_cast<unsigned long>(failCount),
                          uwb.lastErrorName());
        }
        return;
    }

    // Print accumulated statistics every LOG_INTERVAL responses.
    if (++responseCount % LOG_INTERVAL == 0) {
        Serial.printf(
            "DS_RESP_STAT,count=%lu,fail=%lu,last=OK,seq=%u,requester=0x%X,distance_mm=%ld,distance_m=%.3f,elapsed_ms=%lu\n",
            static_cast<unsigned long>(responseCount), static_cast<unsigned long>(failCount), result.sequence,
            result.requester, static_cast<long>(result.distanceMm), result.distanceM,
            static_cast<unsigned long>(result.elapsedMs));
    }
}

void setup()
{
    Serial.begin(115200);
    delay(1000);
    Serial.printf("M5Stamp UWB DS-TWR ANCHOR\n");
    Serial.printf("ROLE,mode=ANCHOR\n");
    Serial.printf("TWR_MODE,mode=DS-TWR\n");
    uwbReady = initUwb();
    Serial.printf("TEST_START,result=%s\n", uwbReady ? "OK" : "FAIL");
}

void loop()
{
    if (uwbReady) runResponder();
    else delay(1000);
}

串口输出示例:

M5Stamp UWB DS-TWR ANCHOR
ROLE,mode=ANCHOR
TWR_MODE,mode=DS-TWR
UWB_ID,dev_id=0xDECA0314,chip=QM33120/DW3720
UWB_CONFIG,result=OK,ch=5,plen=128,rate=6M8,tx_power=0xFEFEFEFE
TEST_START,result=OK
DS_RESP_STAT,count=9500,fail=0,last=OK,seq=7,requester=0x1,distance_mm=162,distance_m=0.162,elapsed_ms=98
DS_RESP_STAT,count=9520,fail=0,last=OK,seq=27,requester=0x1,distance_mm=185,distance_m=0.185,elapsed_ms=93
DS_RESP_STAT,count=9540,fail=0,last=OK,seq=47,requester=0x1,distance_mm=181,distance_m=0.181,elapsed_ms=98
DS_RESP_STAT,count=9560,fail=0,last=OK,seq=67,requester=0x1,distance_mm=167,distance_m=0.167,elapsed_ms=98
DS_RESP_STAT,count=9580,fail=0,last=OK,seq=87,requester=0x1,distance_mm=193,distance_m=0.193,elapsed_ms=98
DS_RESP_STAT,count=9600,fail=0,last=OK,seq=107,requester=0x1,distance_mm=166,distance_m=0.166,elapsed_ms=98
DS_RESP_STAT,count=9620,fail=0,last=OK,seq=127,requester=0x1,distance_mm=164,distance_m=0.164,elapsed_ms=98

4. 单边测距(SS-TWR)

注意
此测距方式最终计算距离时只使用了 Tag 端的时间戳,因此测距精度受 Tag 端的时钟影响较大,误差较大,不推荐使用此方式。若需要更高精度的测距结果,请使用双边测距(DS-TWR)方式。

4.1 Tag 端

cpp
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
#include <Arduino.h>
#include <M5Stamp_UWB.h>

static constexpr uint32_t RANGE_INTERVAL_MS = 200;
static constexpr uint32_t LOG_INTERVAL      = 10;

M5Stamp_UWB uwb;
M5Stamp_UWBRangeConfig rangeConfig;
bool uwbReady        = false;
uint32_t lastRangeMs = 0;
uint32_t rangeCount  = 0;
uint32_t okCount     = 0;

static bool initUwb()
{
    // Stamp-C5 connections to the onboard QM33120 UWB transceiver.
    M5Stamp_UWBConfig config;
    config.pin_gp7    = 23;
    config.pin_irq    = 0;
    config.pin_wakeup = 24;
    config.pin_rst    = 25;
    config.pin_miso   = 26;
    config.pin_mosi   = 27;
    config.pin_cs     = 11;
    config.pin_sck    = 12;

    M5Stamp_UWBPHYConfig phy;
    phy.channel = M5Stamp_UWBChannel::Channel5;

    // Both devices must use the same PAN ID, addresses, and response timing.
    rangeConfig.panId                     = 0xDECA;
    rangeConfig.initiatorAddress          = 0x0001;
    rangeConfig.responderAddress          = 0x0002;
    rangeConfig.responseRxAfterTxDelayUus = 500;
    rangeConfig.responseTxDelayUus        = 3000;
    rangeConfig.rxTimeoutUus              = 6000;
    rangeConfig.hostTimeoutMs             = 100;

    if (!uwb.begin(config, phy)) {
        Serial.printf("UWB_BEGIN,result=FAIL,error=%s\n", uwb.lastErrorName());
        Serial.printf("UWB_RAW_ID,dev_id=0x%08lX\n", static_cast<unsigned long>(uwb.readRawDeviceId()));
        return false;
    }

    const uint32_t devId = uwb.deviceId();
    Serial.printf("UWB_ID,dev_id=0x%08lX,chip=%s\n", static_cast<unsigned long>(devId), uwb.chipName());
    if (devId != M5STAMP_UWB_QM33120_DEVICE_ID) {
        Serial.printf("UWB_ID,result=FAIL,expected=0xDECA0314\n");
        return false;
    }

    Serial.printf("UWB_CONFIG,result=OK,ch=%u,plen=%u,rate=6M8,tx_power=0x%08lX\n", static_cast<unsigned>(phy.channel),
                  static_cast<unsigned>(phy.preambleLength), static_cast<unsigned long>(phy.txPower));
    return true;
}

static void runRanging()
{
    // Start one SS-TWR exchange at the configured interval.
    if (millis() - lastRangeMs < RANGE_INTERVAL_MS) return;
    lastRangeMs = millis();

    const M5Stamp_UWBRangeResult result = uwb.requestRange(rangeConfig);
    rangeCount++;
    okCount += result.success;

    // Print accumulated statistics every LOG_INTERVAL attempts.
    if (rangeCount % LOG_INTERVAL) return;

    const uint32_t failCount = rangeCount - okCount;
    if (result.success) {
        Serial.printf(
            "SS_RANGE_STAT,count=%lu,ok=%lu,fail=%lu,last=OK,seq=%u,distance_mm=%ld,distance_m=%.3f,elapsed_ms=%lu\n",
            static_cast<unsigned long>(rangeCount), static_cast<unsigned long>(okCount),
            static_cast<unsigned long>(failCount), result.sequence, static_cast<long>(result.distanceMm),
            result.distanceM, static_cast<unsigned long>(result.elapsedMs));
    } else {
        Serial.printf("SS_RANGE_STAT,count=%lu,ok=%lu,fail=%lu,last=FAIL,seq=%u,error=%s\n",
                      static_cast<unsigned long>(rangeCount), static_cast<unsigned long>(okCount),
                      static_cast<unsigned long>(failCount), result.sequence, uwb.lastErrorName());
    }
}

void setup()
{
    Serial.begin(115200);
    delay(1000);
    Serial.printf("M5Stamp UWB SS-TWR TAG\n");
    Serial.printf("ROLE,mode=TAG\n");
    Serial.printf("TWR_MODE,mode=SS-TWR\n");
    uwbReady = initUwb();
    Serial.printf("TEST_START,result=%s\n", uwbReady ? "OK" : "FAIL");
}

void loop()
{
    if (uwbReady) runRanging();
    else delay(1000);
}

串口输出示例:

M5Stamp UWB SS-TWR TAG
ROLE,mode=TAG
TWR_MODE,mode=SS-TWR
UWB_ID,dev_id=0xDECA0314,chip=QM33120/DW3720
UWB_CONFIG,result=OK,ch=5,plen=128,rate=6M8,tx_power=0xFEFEFEFE
TEST_START,result=OK
SS_RANGE_STAT,count=10,ok=10,fail=0,last=OK,seq=10,distance_mm=2270,distance_m=2.270,elapsed_ms=4
SS_RANGE_STAT,count=20,ok=20,fail=0,last=OK,seq=20,distance_mm=2282,distance_m=2.282,elapsed_ms=4
SS_RANGE_STAT,count=30,ok=30,fail=0,last=OK,seq=30,distance_mm=2275,distance_m=2.275,elapsed_ms=4
SS_RANGE_STAT,count=40,ok=40,fail=0,last=OK,seq=40,distance_mm=2251,distance_m=2.251,elapsed_ms=4
SS_RANGE_STAT,count=50,ok=50,fail=0,last=OK,seq=50,distance_mm=2265,distance_m=2.265,elapsed_ms=4
SS_RANGE_STAT,count=60,ok=60,fail=0,last=OK,seq=60,distance_mm=2301,distance_m=2.301,elapsed_ms=4
SS_RANGE_STAT,count=70,ok=70,fail=0,last=OK,seq=70,distance_mm=2301,distance_m=2.301,elapsed_ms=4
SS_RANGE_STAT,count=80,ok=80,fail=0,last=OK,seq=80,distance_mm=2291,distance_m=2.291,elapsed_ms=4
SS_RANGE_STAT,count=90,ok=90,fail=0,last=OK,seq=90,distance_mm=2282,distance_m=2.282,elapsed_ms=4
SS_RANGE_STAT,count=100,ok=100,fail=0,last=OK,seq=100,distance_mm=2312,distance_m=2.312,elapsed_ms=4

4.2 Anchor 端

cpp
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
#include <Arduino.h>
#include <M5Stamp_UWB.h>

static constexpr uint32_t LOG_INTERVAL = 20;

M5Stamp_UWB uwb;
M5Stamp_UWBRangeConfig rangeConfig;
bool uwbReady         = false;
uint32_t responseCount = 0;
uint32_t failCount     = 0;

static bool initUwb()
{
    // Stamp-C5 connections to the onboard QM33120 UWB transceiver.
    M5Stamp_UWBConfig config;
    config.pin_gp7    = 23;
    config.pin_irq    = 0;
    config.pin_wakeup = 24;
    config.pin_rst    = 25;
    config.pin_miso   = 26;
    config.pin_mosi   = 27;
    config.pin_cs     = 11;
    config.pin_sck    = 12;

    M5Stamp_UWBPHYConfig phy;
    phy.channel = M5Stamp_UWBChannel::Channel5;

    // Both devices must use the same PAN ID, addresses, and response timing.
    rangeConfig.panId                     = 0xDECA;
    rangeConfig.initiatorAddress          = 0x0001;
    rangeConfig.responderAddress          = 0x0002;
    rangeConfig.responseRxAfterTxDelayUus = 500;
    rangeConfig.responseTxDelayUus        = 3000;
    rangeConfig.rxTimeoutUus              = 6000;
    rangeConfig.hostTimeoutMs             = 100;

    if (!uwb.begin(config, phy)) {
        Serial.printf("UWB_BEGIN,result=FAIL,error=%s\n", uwb.lastErrorName());
        Serial.printf("UWB_RAW_ID,dev_id=0x%08lX\n", static_cast<unsigned long>(uwb.readRawDeviceId()));
        return false;
    }

    const uint32_t devId = uwb.deviceId();
    Serial.printf("UWB_ID,dev_id=0x%08lX,chip=%s\n", static_cast<unsigned long>(devId), uwb.chipName());
    if (devId != M5STAMP_UWB_QM33120_DEVICE_ID) {
        Serial.printf("UWB_ID,result=FAIL,expected=0xDECA0314\n");
        return false;
    }

    Serial.printf("UWB_CONFIG,result=OK,ch=%u,plen=%u,rate=6M8,tx_power=0x%08lX\n", static_cast<unsigned>(phy.channel),
                  static_cast<unsigned>(phy.preambleLength), static_cast<unsigned long>(phy.txPower));
    return true;
}

static void runResponder()
{
    // Wait for a Poll frame and send the delayed SS-TWR Response frame.
    const M5Stamp_UWBResponderResult result = uwb.respondRange(rangeConfig);
    if (!result.success) {
        // Idle receive timeouts are expected and are not counted as failures.
        if (result.error == M5Stamp_UWBError::RxTimeout) return;
        if (++failCount % LOG_INTERVAL == 0) {
            Serial.printf("SS_RESP_STAT,count=%lu,fail=%lu,last=FAIL,error=%s\n",
                          static_cast<unsigned long>(responseCount), static_cast<unsigned long>(failCount),
                          uwb.lastErrorName());
        }
        return;
    }

    // Print accumulated statistics every LOG_INTERVAL responses.
    if (++responseCount % LOG_INTERVAL == 0) {
        Serial.printf("SS_RESP_STAT,count=%lu,fail=%lu,last=OK,seq=%u,requester=0x%X,elapsed_ms=%lu\n",
                      static_cast<unsigned long>(responseCount), static_cast<unsigned long>(failCount), result.sequence,
                      result.requester, static_cast<unsigned long>(result.elapsedMs));
    }
}

void setup()
{
    Serial.begin(115200);
    delay(1000);
    Serial.printf("M5Stamp UWB SS-TWR ANCHOR\n");
    Serial.printf("ROLE,mode=ANCHOR\n");
    Serial.printf("TWR_MODE,mode=SS-TWR\n");
    uwbReady = initUwb();
    Serial.printf("TEST_START,result=%s\n", uwbReady ? "OK" : "FAIL");
}

void loop()
{
    if (uwbReady) runResponder();
    else delay(1000);
}

串口输出示例:

M5Stamp UWB SS-TWR ANCHOR
ROLE,mode=ANCHOR
TWR_MODE,mode=SS-TWR
UWB_ID,dev_id=0xDECA0314,chip=QM33120/DW3720
UWB_CONFIG,result=OK,ch=5,plen=128,rate=6M8,tx_power=0xFEFEFEFE
TEST_START,result=OK
SS_RESP_STAT,count=1260,fail=0,last=OK,seq=12,requester=0x1,elapsed_ms=98
SS_RESP_STAT,count=1280,fail=0,last=OK,seq=32,requester=0x1,elapsed_ms=98
SS_RESP_STAT,count=1300,fail=0,last=OK,seq=52,requester=0x1,elapsed_ms=93
SS_RESP_STAT,count=1320,fail=0,last=OK,seq=72,requester=0x1,elapsed_ms=98
SS_RESP_STAT,count=1340,fail=0,last=OK,seq=92,requester=0x1,elapsed_ms=98

5. 编译上传

  • 选中设备端口,选择上述案例程序粘贴,点击 Arduino IDE 左上角编译上传按钮,等待程序完成编译并上传至设备。
Page Tools
PDF
On This Page