SF8 / 125 kHz: four-channel comparison at 5.1 chirps
Measured 2026-09-14. 12 packets received, then packet 13 missed. The first three balanced rounds passed (3/3 on every channel); the next probe on channel 3 failed. The run stopped at that miss. The target of 100 packets per channel was not reached. No RF retry or other channel count was tested.
Setup and comparison
Same XIAO ESP32-S3 + WIO SX1262 scanner (COM31) and SenseCAP Indicator ESP32-S3 reference transmitter (COM28). Four centers: 909.500, 909.750, 910.000 and 910.250 MHz. CR4/5, 32-symbol programmed preamble, 16-byte synthetic packets, -9 dBm, warm production fast RX and buffered 8 MHz SPI. Same production packet guards and read-only 64 us nominal IRQ polling; events buffered until each result. Randomized balanced channel order, seed 606125, varied arrival timing.
| Setting | Earlier SF6/125 | This SF8/125 |
|---|---|---|
| One symbol | 512 us | 2,048 us |
| Requested 5.1-symbol dwell, rounded up | 2,612 us | 10,445 us |
| 32 programmed preamble symbols | 16.384 ms | 65.536 ms |
| Whole-run average measured retune | 539.427 us | 524.124 us |
| Outcome before first miss | 7 received, packet 8 missed | 12 received, packet 13 missed |
| Miss trace | No observed preamble or hold | Off-channel preamble and prolonged hold |
Changing SF increases real listening and preamble durations together. This is not a matched same-image A/B or an isolated post-retune settling experiment. The small retune-time difference must not be treated as a new optimization; no extra settling delay was inserted. The earlier reporting-only held-visit timestamp correction is included in this trace-version-2 run.
Failed probe: an off-channel hold
Failed sequence 388715032 targeted channel 3 / 910.250 MHz. The scanner
instead observed PreambleDetected on channel 2 / 910.000 MHz, then its
normal packet guard deferred the intended jump to channel 3. It never observed
a valid header, header error, CRC event, or RxDone for that preamble.
Times are software observations relative to expectation arming:
| Time | Event |
|---|---|
| 207.649 ms | Last hop onto target channel 3 before the long gap |
| 240.542 ms | Hop onto channel 2 |
| 250.030 ms | PreambleDetected (0x0004) observed on channel 2 |
| 251.013 ms | Guard defers channel 2 → 3 at the 5.1-symbol deadline |
| 342.287 ms | Guard issues a clear of the still-latched preamble bit |
| 342.794 ms | Hop onto channel 3 finally completes |
| 342.851 ms | IRQ read confirms zero bits |
| 9,999.270 ms | Expectation timeout, RX mode, zero device errors |
Channel-2 occupancy was about 102 ms. The target channel's revisit gap grew to 135.145 ms, compared with its ordinary ~43.875 ms cycle and the 65.536 ms programmed preamble. The delayed retune itself took only 550 us.
The preamble-to-header budget from calcMaxPacketMillis() is
ceil((32 + 8 + 4.25) * 2.048) = 91 ms. The strict millisecond timeout in
CustomSX1262::isReceiving() clears a preamble that does not advance to a
header. The observed 92.257 ms from the first IRQ observation to that
clear is consistent with this existing protection mechanism.
This identifies a prolonged off-channel hold that removed the next listening opportunity. It does not show that the ~0.52 ms jump needs more settling time. The RF source of that preamble is not proven: adjacent-channel pickup/ false detection or unrelated RF are possibilities. There was no independent RF capture or synchronized MCU clock. The earlier SF6 miss had no observed preamble or hold; this result does not establish the same cause for that miss.
Simply shortening the guard risks cutting off valid long-preamble packets. Successful traces show that reception legitimately keeps a channel occupied well past 10.445 ms. No production guard change was made in this diagnostic.
Follow-up: the stationary preamble investigation reproduced transmitter-associated off-frequency indications with full RX initialization and no hopping, on both boards. It strengthens the off-channel detection explanation without independently identifying the RF source of this historical missed probe. The SF6 miss remains a separate unresolved case.
Measurements and checks
- All 12 successful payloads were valid; RSSI -42 to -41 dBm, SNR 12.0 to 14.2 dB. First observed preamble after logged hop completion ranged 7.433–9.485 ms; hop-to-RxDone ranged 105.056–146.836 ms.
- Entire run: 1,167 fast hops, mean retune 524.124 us, maximum 774 us. Idle dwell mean 10,452.444 us; held visits separately accounted for.
- Failed expectation: 910 trace events, zero overflow, 903 completed hops. The 902 unheld dwells were 10,445–10,480 us, mean 10,450.424 us.
- Excluding the one held cycle, target-channel revisit intervals were 43,847–43,928 us, mean 43,874.580 us (224 intervals).
- Failed-expectation retunes: 511–617 us, mean 520.443 us. The held occupancy accounts for the anomalous target-channel revisit gap.
- Zero retune failures, RX-mode errors, modulation-cache errors, CRC/read errors, USB stale replies or cached transport recovery. Reference TX rc=0.
- 133,217 extra IRQ polls during the failed capture; total cost 3,241,509 us, maximum 55 us. Polls add load; timestamps are observations, not exact IRQ edges. No per-event serial output occurs during capture.
This first-miss sample neither estimates a stable packet-error rate nor establishes a channel count with 100% reception.
Reproduction and provenance
python tools/hil/profile_switch_channels.py --receiver COM31 --sender COM28 --output tools/hil/sf8_125_5p1_trace_results.json --samples 100 --preamble 32 --max-channels 4 --dwell-symbols 5.1 --trace --sf 8
Raw result SHA-256:
0d7e97173937f42708febf8276cdadc36578740735058d5da39b1b576e9ca49e.
Tested firmware SHA-256:
- XIAO:
a68ab9834f62d0a5fb3f10c7a0b312c17d7d62795885cac4ea0dce483d6bf1ea - Indicator:
bca1514bc6e09af6b1a9daed5bf4d3dbeeab988bcb856acbc73f59334395280d
Base commit c329cf1fc1e7f2e8c8733ab0d000094730458fe3 plus local changes;
RadioLib 7.7.1 at 187ef24791c3d844939b2be13a68bd890bd04e4c, Espressif32
6.11.0 / Arduino ESP32 2.0.17. Both HIL targets built successfully. All 27
selected host/native tests passed, including SF scaling, propagation to both
RX staging slots and TX, cache checks, trace handling and first-miss stop.
Device handoff
Fresh full 8 MiB backups were saved and digest-verified before flashing:
- XIAO:
e9533742103c9d7af11a3dc0c40496ca412b072e11880c2be785c92ef80e4310 - Indicator:
d4f39a0be1339f142ed329b68606347adeb514d26d6cc8bad43fb3d343ac1e2a
Both were restored after the test, separately full-flash digest-verified, and hardware-reset. Backups remain in the private current-user backup directory. No identity or channel secrets were used in the synthetic RF probes. The RAK4631 and Indicator RP2040 were not modified; the XIAO soak logger was not restarted. The temporary HIL build overlay was removed. Source, tests and results were initially handed off locally before publication.