SX1280 Hardware Ranging — Calibration¶
Project: Giga Ranger — GPS-independent distance measurement via SX1280 Time-of-Flight Hardware: LILYGO T3-S3 (ESP32-S3) · SX1280 @ 2.45 GHz · 13 dBi Yagi · 60 km fixed LOS link, Stubbornly Sovereign Alberta Method: Conducted (cabled) calibration — Wolf et al. (2019) §IV.A.1 + Semtech AN1200.29 Devices: Alpha (permanent master) · Chimp-001 (permanent slave) Calibration date: 2026-07-04 · Die temp: 31.3°C
| Parameter | Value |
|---|---|
| Spreading Factor | SF9 |
| Bandwidth | 1625 kHz |
CAL_TABLE[2][4] |
13089 |
| AN1200.29 default | 13430 |
| Total correction | −341 counts |
| Verification mean | +0.668 m |
| Cable electrical length | 0.695 m |
| Residual | −27 mm |
| CalibrationValue | 0 |
Theoretical accuracy at 60 km (calibration applied): ±0.47 m per exchange (1σ) · ±0.021 m averaged over 500 exchanges
1. Background¶
The SX1280 integrates a hardware Time-of-Flight ranging engine. The master transmits a ranging request; the slave responds after a fixed internal turnaround delay; the master measures the round-trip time and converts it to distance. The result is a 24-bit integer in units of c / (2 × BW × 2^SF) — for SF9/BW1625: 0.1803 m per count.
The SX1280 subtracts a nominal turnaround time internally, but each chip has a slightly different actual RX→TX switching delay. This systematic offset must be measured and corrected per board. The correction lives in Chimp-001's RxTxDelay register — adjusted via a calibration table passed to startRanging().
In RadioLib 7.7.1, setRangingCalibration() does not exist. The calibration is applied by passing a custom 3×6 table (rows = BW, columns = SF5–SF10) to startRanging() on every exchange.
See Appendix A for a detailed explanation of why calibration lives on the slave (Chimp-001).
2. Hardware Setup¶
Devices¶
| Device | Role | Notes |
|---|---|---|
| Alpha | Permanent master (initiator) | LILYGO T3-S3 V1.3, SX1280 |
| Chimp-001 | Permanent slave (responder) | LILYGO T3-S3 V1.3, SX1280 |
Calibration signal chain¶
[Alpha] ── SMA ── [40 dB atten] ── [1 m RG-316 coax] ── [Chimp-001]
TX power: −18 dBm (SX1280 minimum). With one 40 dB attenuator: −58 dBm at RX. No antenna fitted during calibration.
Reference cable¶
| Property | Value |
|---|---|
| Part | DigiKey J10302-ND — Amphenol RG-316 MIL-DTL-17 |
| Physical length | 1.000 m |
| Velocity factor | 0.695 (MIL-DTL-17 spec, confirmed from jacket markings) |
| Electrical length | 0.695 m (calibration target) |
Calibration rig — 2026-07-04¶
Figure 1 — Full setup: Alpha and Chimp-001 connected via 40 dB attenuator and 1 m RG-316 reference cable. RF enclosures sealed to reduce spurious coupling.

Figure 2 — Alpha (master)

Figure 3 — Chimp-001 (slave)

Figure 4 — Sealed enclosures during calibration run
3. Chimp Calibration Method¶
The Chimp Calibration method uses Alpha as the permanent master across all calibration runs. Only Chimp-001's RxTxDelay register is corrected — its slave-mode delay is what Alpha measures.
Steps:
- Flash Chimp-001 (
-e slave), then Alpha (-e master) - Assemble the cabled signal chain; seal RF enclosures
- Press SPACE on Alpha's serial monitor to start a 500-exchange collection pass
- Record
Mean,CalibrationValue, andESP32 die temp - Repeat 3–5 passes to establish a stable baseline mean
- Adjust
CAL_TABLE[2][4]by the CalibrationValue × empirical table rate - Reflash Alpha (Chimp-001 does not need reflashing — table is passed from Alpha at runtime)
- Repeat until
CalibrationValue ≈ 0andMean ≈ 0.695 m
Empirical table rate for SF9: ~0.0224 m per table count (measured from iteration 1 convergence). This is approximately half the SF10 rate (0.0456 m/count), consistent with the SF doubling relationship.
See Appendix B for a note on the AN1200.29 role-reversal averaging method and why it was not used here.
Empirical table rate: -22.313 mm per table count (fit) Measured from iter1: 22.4 mm per table count
Baseline avg σ: 713 mm Iter 1 avg σ: 451 mm Verification avg σ: 472 mm
4. Production Calibration Table¶
Copy this table directly into the ranging firmware. Pass it via startRanging() in both the Alpha and Chimp-001 builds — only Chimp-001's register is active during ranging, but both builds must supply the table.
// SF9, BW=1625 kHz — Alpha (master) + Chimp-001 (slave), LILYGO T3-S3 V1.3
// Calibration date: 2026-07-04 · ESP32 die temp: 31.3°C
// AN1200.29 default SF9/BW1625 = 13430 · total correction = −341 counts (−7.64 m)
static const uint16_t CAL_TABLE[3][6] = {
{ 10299, 10271, 10244, 10242, 10230, 10246 }, // BW 406.25 kHz — SF5–SF10
{ 11486, 11474, 11453, 11426, 11417, 11401 }, // BW 812.50 kHz — SF5–SF10
{ 13308, 13493, 13528, 13515, 13089, 13376 }, // BW 1625.00 kHz — SF5–SF10 (SF9 adjusted)
};
radio.startRanging(master, RANGING_ADDR, CAL_TABLE);
Calibration table unit¶
1 table count ≈ 22.4 mm of distance shift (empirical, SF9). This is approximately half the SF10 rate (45.6 mm/count), consistent with the 2× difference in ranging resolution between SF9 and SF10. The table uses an internal timer, not the result register counter.
Temperature sensitivity¶
The CAL_TABLE value is mildly temperature-sensitive via crystal oscillator drift. The LILYGO T3-S3 uses an AT-cut crystal near its thermal turnover point at calibration temperature (~31°C), which is the flattest part of the curve.
| Operating scenario | ΔT from calibration | Range error at 60 km |
|---|---|---|
| Warm summer (35°C) | +4°C | < 0.05 m |
| Cold morning (15°C) | −16°C | < 0.20 m |
| Full range (15–35°C) | ±16°C | < 0.20 m |
Maximum temperature drift is below the per-exchange noise floor (σ ≈ 0.47 m). Log BME280 ambient temperature alongside each ToF result to detect long-term drift. ESP32 die temperature baseline: 31.3°C.
References¶
[Wolf 2019] Wolf, F., Le Déroff, K., de Rivaz, S., Deparday, J., Guichard, R. (2019). Ranging and Positioning with the SX1280 in LoRa Modulation.
[AN1200.29] Semtech. SX1280 Ranging Calibration. Application Note AN1200.29.
[MIL-DTL-17] US Department of Defense. Detail Specification: Cables, Radio Frequency, Flexible and Semirigid, General Specification for. MIL-DTL-17H.
Appendix A — Why Calibration Lives on Chimp-001¶
The SX1280 ranging exchange:
- Alpha transmits a ranging request packet
- Chimp-001 receives it, switches from RX to TX mode, and sends a response after an internal turnaround delay
- Alpha measures the total round-trip time and computes distance
The chip subtracts a fixed nominal turnaround time internally. What it cannot account for is each board's actual RX→TX switching delay, which varies between chips due to component tolerances. The RxTxDelay register on Chimp-001 adjusts when it transmits its response — shifting Alpha's RTT measurement to compensate.
Because Alpha and Chimp-001 have permanently fixed roles:
- Chimp-001: its
RxTxDelayis corrected to match what Alpha's ranging engine expects - Alpha: its calibration register is unused while acting as master
Running multiple passes with Alpha as the fixed master directly measures Chimp-001's slave-mode delay. This is more accurate than the averaged role-reversal approach (see Appendix B) because it does not dilute Chimp-001's correction with Alpha's delay.
Appendix B — AN1200.29 Role-Reversal Method (Not Used)¶
Semtech AN1200.29 describes a two-pass calibration where each board acts as master in turn. The two CalibrationValue results are averaged to produce a single correction applied to both boards. This approach is designed for deployments where both boards may swap roles.
Why it was not used for Giga Ranger:
Alpha and Chimp-001 have permanently labelled fixed roles. Averaging the two CalibrationValues would dilute Chimp-001's correction with Alpha's delay — producing a less accurate result for a fixed-role deployment. The Chimp Calibration method (Alpha as master only, multiple passes) directly measures the delay that needs correcting.
For reference, a single role-reversal run (Chimp-001 as master) was performed during SF10 calibration and showed CalibrationValue = −8 for Alpha as slave, versus −96 for Chimp-001 as slave — confirming significant asymmetry between the two chips and validating the fixed-role approach.
Appendix C — SF10 Calibration (Historical Reference)¶
SF10 was evaluated before SF9 was confirmed as the production spreading factor. SF9 gives approximately 2× better ranging precision (σ ≈ 470 mm vs ~1600 mm) with sufficient link margin for the 60 km fixed LOS link.
SF10 calibration — 2026-07-03:
| Run | Mean | Std Dev | CalibrationValue |
|---|---|---|---|
| A1 | −7.985 m | 1542 mm | −96 |
| A2 | −8.179 m | 1753 mm | −98 |
| A3 | −8.351 m | 1795 mm | −100 |
| A4 | −8.292 m | 2260 mm | −100 |
| A5 | −8.344 m | 2018 mm | −100 |
| A6 | −8.250 m | 1431 mm | −99 |
| Avg | −8.242 m | −99 |
Final table value: CAL_TABLE[2][5] = 13180 (default 13376 − 196 counts). Verification residual = +53 mm.
