ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

UWB厘米级测距:802.15.4z时间戳、DS-TWR与STS机制

UWB厘米级测距:802.15.4z时间戳、DS-TWR与STS机制

简介:IEEE Std 802.15.4z-2020 标准文档面向从事低速率无线网络、UWB 精确定位与测距系统开发的工程师和研究人员,可用于查阅增强型超宽带物理层及配套测距技术的规范原文。文档重点给出 UWB PHY 新增编码选项与改进措施,以提升测距测量的完整性和精度,并说明 MAC 层如何支持飞行时间测距流程控制及测距设备间的信息交换;内容涉及 HRP/LRP UWB PHY、ERDEV、SS-TWR、DS-TWR、多节点测距、TOF 完整性以及 RTLS 等关键词,适合做协议实现、射频方案评估和标准符合性核对时参考。资源包共 1 个 PDF 文件,大小约 3.52MB,单文件即为标准正文,便于检索和离线阅读。已有 1737 人学习,说明其在 UWB 与无线测距方向具有较高关注度。读者可从中获得条款级技术定义、测距流程与参数约束,为算法设计、设备联调和问题排查提供权威依据。

1. UWB 测距能做到厘米级,靠的不是带宽而是时间戳

UWB 测距能到厘米级,这个结论被复述得太多次,反而很少有人追问它靠什么撑住。直觉答案通常是带宽:500 MHz 的带宽意味着纳秒级时域分辨率,换算成距离就是几厘米,故事似乎到此结束。但真正在产线上被距离读数折磨过的人会给出另一套说法——带宽只给了理论上限,决定同一台设备今天量出 10 cm、明天量出 80 cm 的,是时间戳打在哪个时刻、由谁记录、对方的时钟当时偏了多少。802.15.4z-2020 这份修正案干的正是后一件事:它没把 UWB 的带宽变宽,而是给「测距这件事」补上了时间戳的完整性、流程的可协商性,以及多设备共存时的秩序。搞懂它,等于搞懂厘米级定位里那些不写在指标上的部分。

2. 飞行时间:为什么「光速乘时间」会被晶振误差吃掉三十厘米

飞行时间(Time of Flight)测距的全部内容就是一句话:距离 = 光速 × 单程传播时间。公式简单到不像能撑起一个标准,真正难的地方在于——你手上没有任何一个时钟能直接测出「单程」那几十纳秒,只能测往返,再想办法把对方处理帧所花的时间减掉。这一减,问题全来了。往返时间里混进了两个不同晶振的计时误差,而这两个晶振的偏差量级是 ppm 级,也就是百万分之一,看着微不足道,乘上几十微秒的帧处理时间就变成几百纳秒,换算成距离是几十厘米到几米。UWB 测距的所有协议设计,本质上都是在跟这个误差项搏斗。

2.1 误差预算:15.65 ps 决定了天花板在哪

先把天花板算清楚。UWB 测距的时间基准通常挂在 499.2 MHz 的采样时钟上,标准在这一级之上再做 1/128 的细分,于是最小时间刻度是 1/(499.2 MHz × 128),约 15.65 ps。乘上光速,一个刻度对应的单程距离大约是 4.7 mm。这个数字很关键:它意味着只要你的时间戳精度能稳定在一个刻度上下,距离分辨率天然就在毫米级,不需要任何复杂的信号处理。

C = 299_792_458.0 # 光速,m/s TICK = 1.0 / (499.2e6 * 128) # 一个时间戳刻度 ≈ 15.65 ps print(TICK * C * 1e3) # 单程距离分辨率 ≈ 4.69 mm

上面这段只做一件事:把标准里的时间粒度翻译成距离粒度。参数只有两个,499.2 MHz 是 UWB 的基准采样率,128 是细分倍数,改任何一个都会直接改变分辨率。很多模组厂商标称「厘米级」,说的就是这个刻度乘以若干倍噪声后的实际抖动,而不是刻度本身。

天花板摆在这里,可现实里经常差出三十厘米,说明误差不来自刻度,而来自「谁在什么时刻按下了秒表」。这就引出两种最基础的测距流程:单边双向测距(SS-TWR)和双边双向测距(DS-TWR),它们的差别不在于算法复杂度,而在于对晶振误差的敏感程度差了一个数量级。

2.2 SS-TWR:Treply 是把误差放大一百倍的隐形杠杆

SS-TWR 只用两帧。设备 A 在 t1 发出 Poll,设备 B 在 t2 收到、在 t3 回 Response,A 在 t4 收到。A 自己算得出往返时间 Tround = t4 − t1,B 把 Treply = t3 − t2 告诉 A,于是单程飞行时间 Tprop = (Tround − Treply)/2。

看起来天衣无缝,问题出在 t1 到 t4 是 A 用自己的时钟量的,而 Treply 是 B 用自己的时钟量的。两个时钟的频率偏差不同,同一个物理时长在两边被记成了不同的数。做个不太严谨但足够说明问题的推导:A 的时钟偏差为 eA,B 为 eB(单位 ppm,百万分之一),那么

  • A 测到的往返 = 2·Tprop·(1+eA) + Treply·(1+eA)
  • B 报过来的处理时间 = Treply·(1+eB)

两者相减再除以二,误差项里会剩下 Treply·(eA − eB)/2。注意这个误差跟 Tprop 没关系,只跟 Treply 和两个晶振的偏差差有关。这一点非常反直觉,也是很多人第一次踩坑的地方。

def ss_twr_measured(distance_m, reply_us, ppm_a, ppm_b): t_prop = distance_m / C # 真实单程飞行时间 t_reply = reply_us * 1e-6 # 响应方的处理时间 t_round = 2 * t_prop * (1 + ppm_a * 1e-6) + t_reply * (1 + ppm_a * 1e-6) t_reply_measured = t_reply * (1 + ppm_b * 1e-6) t_prop_measured = (t_round - t_reply_measured) / 2 return t_prop_measured * C print(ss_twr_measured(10.0, reply_us=100, ppm_a=20, ppm_b=-20)) # 真实距离 10 m,量出来大约 10.6 m —— 三十厘米级的偏差

这段代码把三个参数摆在一起:真实距离、响应处理时间 Treply、两端晶振偏差。改 Treply 从 100 µs 到 500 µs,误差会线性放大五倍;改晶振偏差差从 40 ppm 到 4 ppm,误差会缩小十倍。所以工程上压低 SS-TWR 误差只有两条路——把 Treply 压到极短(受制于 MCU 和协议栈,很难),或者用一颗温补晶振把 ppm 压下去(成本上去了)。这也是为什么 SS-TWR 适合近距离、低精度、对功耗极敏感的场景,却在需要稳定厘米级的场合被抛弃。

注意:SS-TWR 的误差和距离无关,只和处理时间成正比。这意味着它在近距离反而更难看——1 米的目标偏 30 厘米,相对误差 30%。

2.3 DS-TWR:对称的 reply 时长把晶振误差约成一阶零

DS-TWR 加了一帧,也加了两个时间戳。A 发 Poll(t1),B 收(t2)回 Response(t3),A 收(t4)之后再发一个 Final(t5),B 收(t6)。于是有两组往返和两组处理时间:Tround1 = t4−t1、Treply1 = t3−t2、Tround2 = t6−t3、Treply2 = t5−t4。

标准给出的合成公式是:

Tprop = (Tround1 × Tround2 − Treply1 × Treply2) / (Tround1 + Tround2 + Treply1 + Treply2)

这个式子的精妙之处在于分子分母的时钟因子可以互相约掉。把每个测量值都乘上它所属设备的 (1+e),分子里会出现 (1+eA)(1+eB) 的公因子,分母里则是 (1+eA) 与 (1+eB) 分别乘在两对数上——只要让 Treply1 和 Treply2 大致相等(也就是两次响应耗时对称),分母就能提出同一个公因子,整体误差退化到 eA·eB 这样的二阶小量。40 ppm 的偏差差,二阶项只有 1.6×10⁻⁹,彻底掉到噪声底下去。

def ds_twr_tprop(t1, t2, t3, t4, t5, t6): # 所有时间戳单位一致即可,通常是 15.65 ps 的 tick r1 = t4 - t1 # A 侧第一次往返 p1 = t3 - t2 # B 侧第一次处理 r2 = t6 - t3 # B 侧第二次往返 p2 = t5 - t4 # A 侧第二次处理 return (r1 * r2 - p1 * p2) / (r1 + r2 + p1 + p2)

这里四个中间量的含义要分清:r1 和 p1 分别由 A、B 各自的时钟测量,r2 和 p2 则反过来,由 B、A 测量。正因为每个时钟都同时出现在分子和分母的对称位置,偏差才被抵消。参数上没有可调的余地,但工程上有——两次响应时间要尽量对齐,偏差越大,二阶项之前的残余误差越明显。我见过有人为了省电让第二次响应明显更快,结果测距曲线在 5 米之外开始系统性外扩,查了很久才发现是「对称」这个前提被破坏了。

代价也很直白:DS-TWR 要三帧,空口时间几乎是 SS-TWR 的两倍,功耗和信道占用同步上涨。这个取舍贯穿整个标准——所有「增强」都拿空口时间换确定性,没有例外。

3. PHY 层增强:802.15.4z 往空口里插了一段什么

如果说 DS-TWR 解决的是「算得准」,那 PHY 层要解决的是「测得对」。这两个词差别很大:算得准是把已知的时间戳处理好,测得对是保证你拿到的那个时间戳对应的是真实的那一帧,而不是被多径、干扰或者人为构造的信号骗出来的假峰。802.15.4z 在物理层做的所有事情,几乎都围绕后者。它没有推翻原来 HRP UWB 的帧结构,而是往帧里插了一段过去不存在的东西,同时把前导码和编码的可选档位重新排了一遍。

3.1 帧结构:RMARKER 为什么必须定在 SFD 的末尾

HRP UWB 的帧分成三段:SHR(同步头,含 SYNC 前导码和 SFD 帧定界符)、PHR(物理层头,携带数据率、帧长、是否含 STS 等标志)、PSDU(载荷)。802.15.4z 在这之后又加了一个可选的 STS 段,位置在 PHR 之后、PSDU 之前。

关键在于测距时间戳的参考点。标准把 RMARKER 定义在 SHR 结束的那一刻,也就是 SFD 最后一个符号的边界。所有 TOF 计算里的 t1、t2、t3、t4,本质上都是「RMARKER 出现的时刻」。为什么非要定在这个位置?因为前导码是一段接收方已知的固定序列,接收机可以通过相关运算找到一个极其尖锐的峰,这个峰的位置在硬件里是确定的、可复现的。如果把参考点定在载荷中间或者帧尾,时间戳就会受数据内容、编码方式、甚至重传策略影响,变成一个不确定的量。

前导码长度的档位通常是 16、64、1024、4096 个符号,一个符号约 2 ns。64 个符号的前导码只占 128 ns,4096 个则要 8.2 µs。前导码越长,接收机积分的时间越久,相关峰越干净,时间戳抖动越小;代价是每一帧都要在空口上多待几微秒。这个账很好算,但很多人在选型时只盯着「支持多少档」,没意识到档位选错会直接反映到测距方差上。

3.2 STS:一段加密随机脉冲如何成为测距的信任根

STS 全称是加密时间戳序列(Scrambled Timestamp Sequence)。它是一段由密钥派生出来的伪随机脉冲序列,只有持有相同密钥和相同初始向量的接收方才能够本地重构出来,进而做相干累加,得到一个位置精确的相关峰。

这段东西解决的是一个很现实的问题。普通的测距帧,前导码是公开的、固定的,任何一台设备只要抓过一次就能复现。攻击者可以录下完整的 Poll 帧,然后在稍早一点的时间点把它重放出去,接收方照样能相关成功、照样打出一个时间戳——只不过这个时间戳比真实到达时间早了那么一点点,算出来的距离就短了那么一点点。距离被系统性缩短,在数字钥匙这类场景里意味着「车以为钥匙就在旁边」,这就是中继攻击的经典形态,而且它攻击的不是加密算法,是物理层的测量过程本身。

STS 让重放失效的机制不是「加密了所以解不开」,而是「你不知道下一段序列长什么样」。序列由密钥和随时间变化的计数器共同决定,每次测距的 STS 都不同。攻击者录下上一帧的 STS 再重放,接收方用当前的期望序列去做相关,得到的峰是散的、位置是错的,硬件会直接判定这次测距无效。这就把「距离测量」和「身份认证」绑成了同一件事——你没法只伪造距离而不伪造序列。

注意:STS 只长在增强型设备(ERDEV)上。老设备能参与测距,但没有这层保护,混合组网时整条链路的完整性取决于最弱的那一环。

3.3 编码选项与前导码:所谓「增强」为什么反而更费电

修正案里还有一条容易被忽略的改动:新增了若干编码选项。原文的措辞是「additional coding options and improvements to increase the integrity and accuracy of ranging measurements」,翻译过来就是——通过更强的信道编码,让测距帧在低信噪比下也能被正确解出、正确打戳。

这件事的动机不难猜。UWB 的脉冲功率被发射限值压得很死,信号本身就弱,一旦遇到遮挡或者距离拉远,前导码检测就容易出错。出错的表现不是丢包,而是「解出来了但峰位置偏了几个纳秒」——比丢包更危险,因为它是静默的。加编编码之后,同样的信噪比下误帧率下降,时间戳的可靠性随之上升。

代价同样是空口时间。更强的编码意味着更低的码率,同样的载荷要占用更多符号;更长的前导码意味着每帧的固定开销更大。这两项叠加,结果是增强模式下的单次测距功耗明显高于基础模式。所以真实产品里很少全程开增强,通常是「平时用短前导码快速测距,进入安全敏感场景(比如靠近车辆、靠近门锁)再切到带 STS 的长前导码模式」。这种按场景切换的策略,标准本身没有规定,是工程上的常用做法。

4. MAC 层增强:测距从「算出来的」变成「谈出来的」

PHY 解决了单次测量可不可信,MAC 要解决的是「这次测量什么时候发生、由谁发起、参数怎么对齐」。这一层的东西看起来琐碎——无非是一些信息元素和命令帧——但它决定了这套机制能不能在多设备环境里跑起来。802.15.4z 在 MAC 上引入的核心概念是把设备分成两类,并且给测距流程配了一套可协商的控制信道。

4.1 RDEV 与 ERDEV:能力位决定了你走哪条流程

标准里区分了测距设备(RDEV)和增强测距设备(ERDEV)。前者能参与 TOF 测距流程,能收发测距相关的帧、能在 MAC 层交换时间戳;后者在此之上还支持 STS 那套增强机制,能处理加密序列、能做完整性校验。

这个二分不是为了分层好看,而是为了解决兼容性。一个空间里可能同时存在只支持基础测距的老设备和支持 STS 的新设备,如果强制要求全员增强,老设备直接出局;如果一律降级,新设备的能力白费。用能力位来协商,双方在测距开始前先确认「你支持到哪一档」,然后选一个交集里的流程跑,这是标准里非常典型的一种设计——把复杂性放在协商阶段,让执行阶段保持简单。

实际实现上,这个协商结果会影响后面所有的帧格式:走 ERDEV 路径的帧里要带 STS 段,STS 段的长度、密钥索引、序列起始点都要在测距开始前谈好;走 RDEV 路径的帧里没有这些字段,PHR 里的标志位也不一样。写驱动的人如果只按一种路径写死,遇到对端降级就会解析错位,症状是「帧收得到但时间戳全乱」,这种 bug 查起来相当费劲。

4.2 测距 IE 与时间戳路径:为什么必须由硬件在 PHY 边界锁存

MAC 层新增了用于携带测距控制参数和测距报告的信息元素(IE)。它们负责传的东西包括:本次测距的角色分配、STS 参数索引、各轮的时间戳、以及测距结果的状态码。这些字段本身没什么玄学,真正要命的是时间戳是在哪里产生的。

/* 示意:时间戳必须由硬件在 RMARKER 处锁存,不能由软件补打 */ volatile uint32_t ts_hi, ts_lo; void uwb_irq_handler(void) { uint32_t flags = REG_IRQ_STATUS; if (flags & IRQ_RX_SFD_DONE) { /* RMARKER 刚过去的那个时钟周期,硬件已把计数器快照写入寄存器 */ ts_lo = REG_RX_TS_LO; ts_hi = REG_RX_TS_HI; } if (flags & IRQ_TX_SFD_DONE) { ts_lo = REG_TX_TS_LO; /* 发送侧同理,在帧离开天线的时刻锁存 */ ts_hi = REG_TX_TS_HI; } }

这段是典型的时间戳采集路径,参数只有两个 32 位寄存器拼出来的 64 位计数器,低位通常就是前面说的 15.65 ps 刻度。关键在于它发生在中断里、读的是硬件快照,而不是在协议栈里调用一个取时间的函数。

为什么非要这么绕?因为软件路径上的不确定性太大。一次中断响应延迟、一次任务调度、一次总线竞争,动辄几微秒。几微秒乘光速是一公里多的距离误差,完全不可用。所以标准从一开始就把时间戳的语义绑死在 PHY 边界上:帧头到达的那一刻,硬件负责把本地计数器抄一份存起来,软件事后慢慢读都没关系,读到的永远是那个瞬间的值。

提示:调试测距异常时,第一件事是确认时间戳来源。如果发现距离读数随 CPU 负载波动,基本可以断定有人把时间戳打在了软件层。

4.3 多节点测距:一道关于时隙和正交性的调度题

单对单测距跑通之后,下一个问题永远是「一个空间里有几十个标签怎么办」。802.15.4z 支持多节点测距,核心思路是让一个发起者与多个响应者共享同一轮流程,而不是两两配对跑 N² 次。

这里有两种典型组织方式。一种是时分:发起者按调度表依次与每个响应者完成 TWR,每对分配一个互不重叠的时隙。这种方式确定性强、实现简单,缺点是节点数一多,轮询周期被拉长,实时性下降。另一种是并发:发起者广播一帧,多个响应者同时接收,各自在自己的时隙里回复,靠 STS 序列的正交性区分不同节点。这种做法把一轮测距的耗时压到接近单对单的水平,但对调度精度的要求高得多——两个响应者的回复在时间上稍有重叠,相关峰就会互相污染。

标准在这里提供的是机制和字段,不是具体调度算法。调度策略留给实现方,这也是为什么不同厂家的多标签方案在最大容量上差距很大——同样一套帧格式,时隙怎么切、并发度开多高、丢包后怎么补,全是工程决策。

5. 排查清单:UWB 测距上线后最容易翻车的五个地方

协议读懂了不代表设备能量准。下面这五条是实际调试中最常撞见的,症状各不相同,但根因往往就那几类。

5.1 静态偏差类:读数总是差那么一截

现象:所有距离都比卷尺量出来的多出固定的一截,比如统一多 12 cm,换距离、换角度都不变。重复性很好,就是不准。

原因:天线延迟没校准。信号从芯片引脚出来,经过匹配网络、走线、天线辐射,这一段也消耗时间,而这段时间被算进了飞行时间里。每块板子的走线长度、天线批次都不一样,所以这个偏移是设备固有的。标准不会替你定义这个值,它只定义 RMARKER 在哪。

解决:两点校准。在已知精确距离上(比如 1 m 和 5 m)各测一组,用线性拟合求出偏移量和比例因子,写进设备的校准参数里,运行时的距离先减偏移再做缩放。校准要按设备逐个做,不能整批共用一个值——同一批板子的天线延迟能差出好几厘米。

5.2 动态抖动类:同一位置量出三个不同的数

现象:设备静止不动,读数在 ±30 cm 范围内跳,方差大得离谱,但平均值是准的。换个前导码配置,抖动明显变小。

原因:时间戳的相关峰不够尖锐。前导码太短、信噪比不够、或者接收机为了省电关掉了一部分相干累加,都会导致峰值判决在相邻几个刻度之间摇摆。注意这和距离远近无关,近距离也可能抖,取决于多径环境。

解决:先把前导码档位往上调一档做对比实验,如果能明显改善,说明是积分时间不足;如果调了没用,去看时钟源,普通晶振在温度变化下的短期稳定度不够,会直接反映成刻度抖动,这种情况换温补晶振比改算法有效。

现象:单对单测距很稳,一旦场内有十几台设备同时工作,丢包率飙到 30% 以上,而且距离读数偶尔会跳出一个完全离谱的值。

原因:时隙冲突或者 STS 序列复用。前者是调度表没排开,两对设备在同一时刻发起测距;后者是不同设备用了相同的密钥索引和序列起始点,相关峰互相污染,接收机锁到了别人的帧上。

解决:先看丢包的时间分布,如果集中在固定周期内,是调度问题;如果随机分布,多半是序列冲突。前者重新排时隙并留出保护间隔,后者给每个设备分配互不相同的序列参数。这一步不做,后面所有的精度优化都是白费。

5.3 系统级:越测越不准的那些隐性问题

现象:刚上电时精度很好,跑几个小时之后整体漂移,重启又恢复。

原因:时钟温漂或者计数器溢出处理有 bug。前者在发热明显的设备上很常见,芯片温度上来之后晶振频偏变化,如果校准参数是开机时算的一次性值,就会失效;后者更隐蔽,64 位计数器在低 32 位溢出时如果没有正确进位,时间戳会突然跳变一个巨大的值。

解决:前者做周期性重校准或者在固件里加温度补偿表;后者老老实实检查进位逻辑,尤其是用两个 32 位寄存器拼接的写法,读的顺序和溢出标志的处理都要过一遍。

现象:视距内很准,一转身或者隔一堵墙,距离系统性偏大,而且偏得很有规律。

原因:非视距传播。信号穿过障碍物时传播速度变慢、路径变长,首达径的能量被衰减,接收机锁到了后面的多径分量上,测得的时间自然偏长。这不是 bug,是物理规律。

解决:在算法层做识别和抑制,常见做法是看首达径能量与总能量的比值,低于阈值就标记为可疑并降权,而不是直接输出距离。指望 PHY 层解决非视距是不现实的,标准能做的只是保证你拿到的时间戳是真实的、没被伪造的,拦不住墙。

6. 设计取舍:精度、空口时间和功耗组成的三元方程

把前面几章的内容收拢一下,会发现 802.15.4z 从头到尾都在解同一个方程:精度、空口时间、功耗,三者只能取其二。想精度高,就拉长前导码、开 STS、用 DS-TWR,每一样都在增加空口占用;想省电,就缩前导码、用 SS-TWR、跳过 STS,精度和安全性同步下滑。标准没有替你选,它提供的是可组合的档位。

配置组合单次测距空口时长(量级)适合场景主要代价
SS-TWR + 64 符号前导码数百微秒低功耗标签、粗略存在检测晶振误差直接进距离
DS-TWR + 1024 符号前导码1~2 毫秒常规室内定位功耗上升,容量下降
DS-TWR + 4096 符号前导码 + STS数毫秒安全敏感、远距离、强多径空口占用大,节点容量受限

这张表里的时长只是量级,具体数值取决于数据率、载荷长度和两次响应之间的处理间隔,但它足够说明一件事:所有「更准」的选项都在往同一个方向收费。

真正让这份修正案值得逐条读的地方,是它把「完整性」单独拎出来当成一个维度,而不是把它塞进精度的定义里。没有 STS 的时候,一个被重放的帧和一个真实到达的帧,在接收机眼里是完全一样的——相关峰一样尖,时间戳一样干净,算出来的距离一样漂亮。这种错误是静默的,你没有任何指标能看出来。加入 STS 之后,接收方多了一把尺子去判断「这一帧是不是刚刚才被发出来的」,测距结果第一次有了可验证的语义。

验证方法其实不复杂,但要花时间。我会在一套设备上同时跑带 STS 和不带 STS 两条链路,用一个可编程的延迟单元去人为构造「提前到达」的帧,观察不带 STS 的那条链路距离读数怎么被拖短、带 STS 的那条怎么报错。这个实验做完,对「完整性」这三个字的理解会比读十遍条款都深。

早些年我参与一个室内定位项目,最初只看平均误差,把一组方差极大的数据当成正常波动放了过去,结果在现场部署后发现标签在某个角落反复报出「负距离」。查了两周才定位到是时间戳软件补打加上计数器溢出,两个 bug 叠在一起。从那以后我每次接入新的 UWB 模组,都会先把「时间戳来源」和「溢出进位」这两条强制走一遍,哪怕模组厂商说已经处理好了。

这份标准的原文价值就在这里:它不会告诉你怎么调参,但它把每一个字段的语义、每一个状态机的边界都写死了,你可以在里面查到 STS 段的准确定义、MAC 命令帧的完整字段表、以及各种 IE 的编码方式。需要对着条款核对实现细节的时候,翻 PDF 比翻任何二手资料都靠得住,资源里就是这份完整的修正案原文。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表