Time-difference-of-arrival positions a tag from a single transmitted blink, heard by several time-synchronised anchors.
Where TWR spends a multi-frame exchange and two fixed turnarounds per position, TDoA spends one frame total — the tag transmits and says nothing else. That difference is what lets a site track many tags at a high update rate.
TDoA moves the burden from airtime to infrastructure time synchronisation.
The implementation is purpose-built rather than a generic TDoA stack. Four properties define it.
Anchors take one of two TDoA roles, configured per unit:
| Role | Function |
|---|---|
| Master anchor | Transmits the reference frames that synchronise nearby anchors, and acts as the coordinate origin for the installation. |
| Slave anchor | Timestamps both the master's reference frames and the tag blink, and reports all three timestamps. |
The role is a stored parameter, so the same firmware image and the same hardware serve both positions — a unit is promoted or demoted by configuration, not by reflashing.
Synchronisation is wireless. No cabling or external clock distribution is installed between anchors: the master's own transmissions carry the timebase over the air. Each anchor therefore reports three timestamps per tag blink, all taken on its own free-running counter:
| Timestamp | Meaning |
|---|---|
timestamp_ref_1 | arrival of the master's first reference frame |
timestamp_ref_2 | arrival of the master's second reference frame |
timestampTDoA | arrival of the tag blink |
Because all three are measured on the same local counter, the pair of reference arrivals gives that anchor a known interval to measure the blink against — which is what removes the need for the anchors' clocks to agree in absolute terms.
A TDoA transmission is the same blink frame the device line already uses for discovery — the tag transmits and no reply is sent. Nothing new is added to the air interface for TDoA, and a tag needs no TDoA-specific frame type.
Each anchor that hears the blink records the tag address, the arrival timestamp and the frame's encoding header. Anything that is not a blink is discarded on this path.
Selecting TDoA switches the radio callbacks to a TDoA-specific transmit-done and receive-OK pair, rather than running TDoA logic inside the TWR state machine. The two methods therefore do not share a code path at runtime — a TWR exchange and a TDoA capture cannot interfere with each other.
Arrival times are taken from the UWB timestamp counter — 40 bits at 63.8976 GHz, about 15.65 ps per tick — not from an MCU clock. This is the same counter the ranging engine uses, and its resolution is what makes a difference of arrival times meaningful at these distances.
Anchors do not compute position. Each reports its timestamps for a blink, the server groups the reports belonging to the same blink — matched on tag identity and the blink's counter value — and solves for the position once enough anchors have reported.
Each anchor's timestamps are converted into a ratio rather than used as absolute times:
reference_interval = timestamp_ref_2 − timestamp_ref_1
tag_offset = timestampTDoA − timestamp_ref_1
ratio = tag_offset / reference_interval
All subtraction is modulo the 40-bit counter width, so a counter wrap between the reference frames and the blink is handled without special-casing. Expressing the blink arrival as a fraction of the master's reference interval is what makes reports from anchors with independent, drifting clocks directly comparable.
For every unique pair of reporting anchors, the differences of the reference intervals and of the tag offsets are combined, corrected by the mean of the two anchors' ratios, and converted from counter ticks to distance:
tdoa = Δtag_offset − Δreference_interval × mean_ratio
ΔD = tdoa × k + (dist₂ − dist₁)
where k converts counter ticks to centimetres and dist is each anchor's distance from the reference anchor. The mean-ratio term is the clock-drift correction: without it, a pair of anchors whose oscillators run at slightly different rates produces a bias that grows with the reference interval.
Published positions carry resolveMethod: "multilateration" along with latitude, longitude and floor.
TWR and TDoA are selected by the UWB RTLS method parameter (0x5106): 1 = TWR, 2 = TDoA. Both run inside the same Unified TDMA schedule and share the same fleet UWB PHY, so switching method does not change the schedule or the radio configuration.
TDoA capacity is bounded by transmissions, not conversations. A tag sends one blink and every anchor in earshot hears it, so a measurement costs a single frame regardless of how many anchors participate:
tags per second = 1000 ms ÷ slot duration
concurrent tags = tags per second ÷ update rate
Adding anchors costs no airtime. In TWR each additional anchor still owes a response window inside the exchange; in TDoA the same blink already reaches all of them and nothing is sent back. Extra anchors buy coverage and geometry — and therefore accuracy — rather than consuming capacity. This is the structural reason TDoA scales where TWR does not.
The same four working points as TWR, but a slot holds one blink rather than a full exchange, and carries none of the fixed 2600 µs turnaround. Slot is blink plus a 10% guard, with a 0.5 ms floor:
| Profile | Data rate | Preamble | Blink | Tags per second (per anchor) | Locations per second (3 anchors) |
|---|---|---|---|---|---|
| Maximum range | 110 kbps | 2048 | ≈ 3.74 ms | ≈ 194 | ≈ 194 |
| Long range — default PHY | 850 kbps | 2048 | ≈ 2.26 ms | ≈ 326 | ≈ 326 |
| Balanced | 850 kbps | 512 | ≈ 0.73 ms | ≈ 994 | ≈ 994 |
| High capacity | 6.8 Mbps | 256 | ≈ 0.31 ms | ≈ 994 | ≈ 994 |
The two columns are identical, and that is the whole point. A blink is heard by every anchor in range simultaneously, so one transmission already produces a position — there is no three-times cost for turning distances into coordinates. In TWR the same two columns differ by 3×.
Set against TWR at the same radio settings — 34, 52, 118 and 160 locations per second — TDoA delivers five to eight times the positioning throughput. None of that comes from a faster radio; it comes from not repeating the conversation per anchor.
| Default PHY | Locations/s |
|---|---|
| TWR — poll, three responses, final | ≈ 52 |
| TDoA — one blink per position | ≈ 326 |
Range figures are indicative, for clear line of sight, and should be confirmed by survey. TDoA needs three anchors to hear every blink, so the relevant question is not coverage but overlap — and shortening the frame shrinks the overlap much faster than it shrinks the coverage.
Fieldbus Anchor — no front-end amplification, uplink through a WiFi module:
| Profile | Locations/s | Range per anchor | Limited by |
|---|---|---|---|
| Maximum range | ≈ 194 | ≈ 85–140 m | airtime |
| Long range — default | ≈ 256 | ≈ 60–100 m | UART uplink — 256 reports/s |
| Balanced | ≈ 256 | ≈ 30–50 m | UART uplink — 256 reports/s |
| High capacity | ≈ 256 | ≈ 15–25 m | UART uplink — 256 reports/s |
Locator Pro — PA / LNA on UWB and BLE, Ethernet uplink:
| Profile | Locations/s | Range per anchor | Limited by |
|---|---|---|---|
| Maximum range | ≈ 194 | ≈ 420–700 m | airtime |
| Long range — default | ≈ 326 | ≈ 300–500 m | airtime |
| Balanced | ≈ 994 | ≈ 150–250 m | airtime |
| High capacity | ≈ 994 | ≈ 75–125 m | airtime |
On a Fieldbus Anchor, a faster PHY buys almost no TDoA capacity. The UART to the WiFi module carries 256 observations per second, so moving off the default trades range away for a ceiling the uplink will not deliver. TDoA at high tag counts is a Locator Pro deployment.
The difference is structural rather than incremental: Locator Pro holds roughly 5× the range at every profile and has no UART stage, so it is the only device in the line where the high-capacity profile actually yields high capacity.
Antenna delay is calibrated per product for the channel in use. Changing the PHY means recalibrating — an uncalibrated change shows up as a constant distance offset, which in TDoA becomes a constant position offset rather than an obvious error.
Airtime is only the first constraint. Every anchor that hears a blink produces its own report, so the traffic leaving the infrastructure is not the measurement rate — it is the measurement rate times the number of anchors in earshot:
reports/s = measurements/s × anchors hearing each blink
At the default profile with four anchors covering each point, 326 tags per second becomes 1300 reports per second reaching the server. The property that makes TDoA cheap on air makes it expensive on the backhaul, and the two scale in opposite directions as anchors are added.
Locator Pro suits TDoA on both counts.
Range. Its PA / LNA front ends amplify both UWB and BLE. TDoA needs at least three anchors to hear every blink, so coverage overlap — not merely coverage — is the requirement, and it is a far more demanding one over a large site. Longer reach per anchor is what makes triple overlap affordable across a yard, pit or port rather than only in a dense indoor grid.
Backhaul. Locator Pro uplinks directly over Ethernet LAN:
| Backhaul | At 1300 reports/s |
|---|---|
| CAN-FD chain | far beyond a shared 125 kbit/s bus, whose bit rate is itself capped by chain length |
| WiFi | shared medium and variable latency, competing with other site traffic |
| Ethernet LAN | not a practical limit |
TDoA at high tag counts is the case where backhaul choice stops being an implementation detail. A configuration that fits comfortably in the UWB schedule can still be undeliverable over a chained transport — and the symptom is lost reports, which look like poor coverage rather than a saturated bus.
On anchors whose uplink runs through a separate WiFi module, the limit arrives earlier still. A TDoA observation costs 45 bytes on the internal UART against 24 for a ranging result, and that link saturates before either the bus or the network does, at 256 observations per second. See Fieldbus Anchor for the arithmetic. Locator Pro has no such stage: the radio and the Ethernet interface share one processor.
| TWR | TDoA | |
|---|---|---|
| Frames per measurement | three, per anchor | one, total |
| Anchors needed | one | three |
| Anchor clock sync | not required | required |
| Tag power per position | higher | lower |
| Scales with tag count | airtime grows per tag | airtime stays small |
| Tag transmits | poll and final | blink only, no reply |
| Output | distance | position |
Reports reach the backend over MQTT on the /RTLS topic with DeviceType: "uwb2", carrying arrival timestamps for server-side multilateration rather than a single distance.