TOF方案在DW1000上的实现(三):SS-TWR方案实践

发布时间 2023-03-30 18:05:25作者: 不回本不改名

说明

在上一篇博客中对代码和原理进行了分析,现在对方案进行实践。

测试环境

本次测试硬件使用Nordic的nRF52840DK板作为主控,通过杜邦线连接到DWM1000模块上
软件环境使用Nordic V1.7.10 SDK和dw1000 V2.14 API库。

测试例程为:
Example 6a: single-sided two-way ranging (SS TWR) initiator
Example 6b: single-sided two-way ranging responder

将两个测试例程分别烧录到两个开发板上运行,即可查看运行结果。

测试中遇到的问题

虽说是官方的API库例程,但实际还是会有遇到跑不通的情况。这里分享下我的心得

responder端延时发送失败

问题情况:responder程序中接收到第一帧数据后调用dwt_starttx接口发送第二帧数据失败,API返回error,进入到函数内部能观察到读取芯片内部STATUS寄存器的HPDWARN标志位被置位。
原因分析:HPDWARN被置位说明延迟发送设置的时间点已经滞后于系统时钟,启动发送已经没有意义了,就直接终止发送。打个比方就是你本来打算定个早上8点钟的闹钟去上班,结果一看时间都9点了,那这个闹钟自然就定不成了。
出现这种情况一般是你主控运行的太慢了或者定的延时发送时间太短导致的,可以通过读取系统时间戳和延迟发送时间戳进行对比,正常延时发送的时间戳应该在系统时间戳之后。如果不是,那就说明是时间不够。

例如可以在responder例程中,在dwt_starttx启动发送代码后获取下系统时间戳,然后比较系统时间戳sys_ts和延时发送时间戳resp_tx_ts。如果resp_tx_ts小于sys_ts,那就要说明要增大延迟时间,或者提高主控运行速度(或者是SPI速率)

ret = dwt_starttx(DWT_START_TX_DELAYED);
sys_ts=get_sys_timestamp_u64();
								
printf("poll_rx_ts = %llx",poll_rx_ts);
printf("resp_tx_ts = %llx",resp_tx_ts);
printf("sys_ts     = %llx",sys_ts);

时间戳读取数据为0

问题情况:读取系统时间戳寄存器或者收发时间戳寄存器都是0
原因分析:时间戳寄存器需要通过初始化时调用DWT_LOADUCODE才会启动
解决方法:检查初始化时dwt_initialise接口的入参是不是DWT_LOADUCODE。

initiator收不到回发的第二帧数据

问题情况:initiator发的第一帧数据responder能收到,responder也回发成功了,但是initiator却收不到
原因分析:上一节博客代码分析我们直到,initiator在发完第一帧后,会设置自动延时开启接收,并且有接收超时参数。如果responder回发数据时超出了这个接收窗口,就会丢失接收。
特别是如果有修改过responder的延时发送参数超过了initiator的自动延时接收参数的话。
解决方法:initiator不使用发送完后延时启动接收,在发送完后干脆直接启动接收,然后一直轮询直到收到数据

//    dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);
//    dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS);

/* Activate reception immediately. */
dwt_rxenable(DWT_START_RX_IMMEDIATE);

不过这样会有缺点,一个是如果一直没说到数据就会一直卡在这。另一个就是一直开接收会导致功耗降不下来。