DW3000/DWM3001CDK — best approach for wireless anchor clock sync (custom TDoA)

Hi, I’m building a custom TDoA-based RTLS on DWM3001CDK boards (QM33 SDK 1.1.1). I moved to raw driver calls (dwt_starttx/dwt_setdelayedtrxtime) after finding that FiRa’s OWR_UL_TDOA round usage validates and goes ACTIVE, but doesn’t actually execute as one-way ranging — traffic stays TWR-shaped (RANGING_INITIATION/RANGING_RESPONSE) and the UL_TDOA_NTF callback never fires, even with every documented OWR-UT session parameter set (tx interval, timestamp length, device ID, report config).

My current approach for anchor-to-anchor clock sync: a reference anchor schedules a delayed TX via dwt_setdelayedtrxtime() + dwt_starttx(DWT_START_TX_DELAYED), embeds that scheduled time (plus TX antenna delay) in the payload, and other anchors capture it with their own RX timestamp to derive a clock offset. In testing, the computed offset between two boards is wildly unstable frame-to-frame, not just noisy, essentially random across the full 32-bit range, even after accounting for the documented SYS_TIME latch behavior and forcing DWT_DW_IDLE before reading system time.

Questions:

  1. Is there a working example or reference design for wireless (non-EXTCLK/OSTR) anchor-to-anchor clock sync on DW3000?
  2. Is OWR_UL_TDOA actually functional end-to-end in QM33 SDK 1.1.1, or is anchor-side reporting still incomplete? (fira_ul_tdoa_ranging_results only wraps a generic fira_ranging_info whose timestamp_ns is documented [NOT IMPLEMENTED].)
  3. Any guidance on getting a value from dwt_setdelayedtrxtime()'s scheduling to actually reflect a coherent, monotonically-advancing time across repeated once-per-second transmissions?

Happy to share logs/code if useful. Thanks!

The Qorvo QM33 SDK does not support TDoA use cases. However, the chipset is capable of it and there are many instances of customers developing such systems.

As an example, the QM33120WDK2 - Qorvo is capable of doing wireless sync between anchors needed for TDoA. Please contact @leapslabs, if you want to get more details on this.

We also have a list of UWB partners who can help with this application if needed: https://www.qorvo.com/innovation/ultra-wideband/partners

I’ve done something similar:

Time master sends a signal that includes the nominal Tx time and the Tx time error due to scheduling quantization.
Based on the receivers Rx time and the expected time of flight we calculate a clock offset between the two. All subsequent packets are then timestamped by taking the receive time, subtracting the offset and scaling the result by the clock difference between the local clock and the master time source.
I ended up smoothing the clock sync and clock difference (after allowing for drift rates) over 10 cycles to reduce noise. In theory you can employ more advanced filtering to cope with the inevitable noise but I found a simple averaging got my position errors down to ~6 cm which was good enough.

It sounds like you are using the same basic concept, I can’t think why it couldn’t be made to work. Even if you completely ignore clock rate differences you would still expect the offset to drift over time at a consistent rate rather than jump at random. Random jumps makes me think you’ve got some sort of logic bug somewhere.