Zum Hauptinhalt springen

Kollisionsanalyse: Timing, Wahrscheinlichkeit & Verbesserungsplan

Kontext

Alle Analysen beziehen sich auf EU/UK Narrow (SF8, BW 62,5 kHz, CR 4/8), Firmware simple_repeater, Stand März 2026.


1. Das Problem: Synchronisierter Trigger

Wenn ein Paket im Mesh geflutet wird, reagieren alle Repeater in Hörweite auf dasselbe Ereignis: das Ende des empfangenen Pakets. Jeder würfelt danach eine Verzögerung aus demselben Zufallsfenster. Die Kollisionswahrscheinlichkeit steigt damit schnell mit der Anzahl gleichzeitig reagierender Repeater.


2. Grundgrößen bei SF8, BW 62,5 kHz, CR 4/8

Symboldauer T_s = 2^8 / 62.500 ≈ 4,096 ms

Airtime für ein typisches Flood-Paket mit 40 Byte Nutzlast:

KomponenteSymboleZeit
Preamble (8 Sym. + 4,25 Overhead)12,2550 ms
Payload (CR 4/8, kein LDR)96393 ms
Gesamt108,25≈ 443 ms

Jede Kollision macht beide Pakete unlesbar und kostet mindestens 443 ms Kanalkapazität.


3. Timing-Analyse: Wann schlägt die Kollisionserkennung an?

MeshCore nutzt PREAMBLE_DETECTED-IRQ-Flags des SX1262 als primäre Kollisionserkennung. Entscheidend ist: wann genau feuert dieses Flag?

3.1 isReceivingPacket(): Reaktiv, nach Korrelatoranlauf

CustomSX1262.h
bool isReceivingPacket() {
uint16_t irq = getIrqFlags();
return (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED);
}

Der interne Korrelator des SX1262 muss genug Up-Chirp-Symbole akkumulieren, bevor er das Flag setzt. Bei SF8:

ZustandZeitpunkt nach TX-Start des anderen
Preamble beginnt0 ms
PREAMBLE_DETECTED feuert≈ 16-25 ms (4-6 Symbole × 4,096 ms)
HEADER_VALID feuert≈ 67 ms (Preamble + Sync Word)
Payload läuftab ≈ 67 ms

Kritisches Kollisionsfenster: Wenn Node B seinen TX innerhalb von ≤ 16-25 ms nach Node A startet, hat PREAMBLE_DETECTED noch nicht gefeuert. Node B sieht einen freien Kanal und sendet trotzdem.

3.2 Hardware-CAD: Proaktiv, 4x schneller

Der PR #1727 implementiert Hardware-CAD (scanChannel()) als aktiven Scan unmittelbar vor TX:

MechanismusErkennungszeitTyp
PREAMBLE_DETECTED IRQ≈ 16-25 ms nach TX-Startreaktiv (passiv)
Hardware-CAD (1 Symbol)≈ 4 msproaktiv (aktiver Scan)
Hardware-CAD (2 Symbole)≈ 8 msproaktiv (aktiver Scan)

CAD sucht spezifisch nach dem Up-Chirp-Muster der Preamble und benötigt nur 1-2 Symbole, weil es gezielt nach dem LoRa-Muster scannt statt auf Korrelatorkonvergenz zu warten. Das kritische Fenster schrumpft dadurch von ≈ 20 ms auf ≈ 4 ms.

SF8 · BW 62,5 kHz · 4.096 ms / Symbol
Szenario 1 / 3: Node B sendet 2 ms nach Node A
Beide Verfahren erkennen die Preamble noch nicht — Kollision
PREAMBLE_DETECTED (aktuell — Korrelator, ~20 ms)
Node ANode B20.5 ms
Hardware CAD (PR #1727 — aktiver Scan, ~4 ms)
Node ANode B4.1 ms
08162432404856647280ms
Preamble Node APreamble Node B (Kollision)Preamble Node B (verschoben)Node B wartet (CAD busy)PREAMBLE_DETECTED-SchwelleHardware CAD-Schwelleaktuelle Zeit

3.3 Mid-Packet-Erkennung: Strukturelle Lücke

Beide Mechanismen schützen nur gegen Preambles. Ein Paket, dessen Preamble nicht gehört wurde (weil der Node gerade aus TX zurückkam und startReceive() die IRQ-Flags resettet), ist weder per CAD noch per IRQ erkennbar:

SzenarioCADPreamble-IRQRSSI-LBT
Preamble läuft, jetzt erkannt✓ (nach 4-6 Sym.)✓ (wenn stark genug)
Preamble verpasst, Payload läuft✓ (wenn stark genug)
Schwaches Signal unter Noise Floor

Fazit: Es gibt kein Hardware-Feature das zuverlässig mid-packet erkennt wenn die Preamble verpasst wurde. LoRa dekodiert Signale bis zu 20 dB unterhalb des Noise Floors, RSSI-LBT ist daher für den Fernbereich strukturell ungeeignet.


4. Kollisionswahrscheinlichkeit

Methodik

Für ein kontinuierliches Zufallsfenster (Pure ALOHA) gilt die Poisson-Näherung:

P(≥1 Kollision) ≈ 1 − e^(−N×(N−1)×T / (2×W))

mit Paketdauer T (= Kollisionsfenster) und Fensterlänge W.

Ergebnisse (T = 443 ms)

Repeater Ntxdelay 0,5 (Default, W=1107 ms)txdelay 2,0 (Max, W=4430 ms)txdelay 4,0 (W=8860 ms)
233 %10 %5 %
370 %26 %14 %
491 %45 %25 %
598 %63 %39 %
6≈100 %78 %52 %
Kernbefund

Mit dem Standard-txdelay von 0,5 ist eine Kollision ab 3 Repeatern wahrscheinlicher als nicht. Bei 4+ Repeatern nahezu sicher.


5. PR-Bewertung

PR #1727: Hardware-CAD statt RSSI-LBT

PR #1727 ersetzt isChannelActive() vom RSSI-basierten Vergleich auf echten Hardware-CAD (scanChannel()). Zusätzlich wird der Default von interference_threshold auf 1 erhöht (aktiviert CAD).

RadioLibWrappers.cpp (nach PR #1727)
bool RadioLibWrapper::isChannelActive() {
if (_threshold == 0) return false;
int16_t result = performChannelScan();
state = STATE_IDLE;
startRecv(); // CAD-Done-IRQ sauber zurücksetzen
return result != RADIOLIB_CHANNEL_FREE;
}
  • 4x schnellere Erkennung: CAD detektiert nach ~4 ms (1 Symbol) statt nach ~16-25 ms
  • Keine Kalibrierung nötig: Noise-Floor-Konvergenz entfällt, sofort verlässlich
  • LoRa-spezifisch: Reagiert auf Chirp-Muster, nicht auf allgemeine RF-Energie
  • ISR korrekt behandelt: State-Reset und RX-Neustart nach CAD verhindert, dass der CAD-Done-Interrupt als empfangenes Paket fehlinterpretiert wird

Bewertung: Funktional sinnvoll und korrekt implementiert was den ISR-Reset betrifft. Die drei Implementierungsmängel sind reale Lücken, insbesondere der nicht-atomare CAD/TX-Abstand. Als-ist mergebar wenn man die konzeptionellen Grenzen akzeptiert; für produktionsreife Kollisionsvermeidung sollte zumindest der CAD-vor-TX Fix nachgezogen werden.


6. Verbesserungsplan

6.1 Sofortmaßnahmen (Konfiguration)

set txdelay 2.0: größtes Hebelpotenzial bei geringstem Aufwand:

Repeater im HörbereichEmpfehlungP(Kollision, N=3)
2-3txdelay 1.042 %
4-5txdelay 2.026 %
> 5Cap-Erhöhung nötig (s.u.)< 15 %
Cap-Erhöhung erforderlich

txdelay ist firmware-seitig auf 2,0 begrenzt (constrain(..., 0, 2.0f) in CommonCLI.cpp). Für höhere Werte muss der Cap im Quellcode angehoben werden.

set rx_delay_base 8.0: SNR-gewichtetes Backoff aktivieren:

Der Dispatcher enthält bereits einen SNR-basierten Verzögerungsmechanismus, per Default deaktiviert (rx_delay_base = 0):

Dispatcher.cpp
int Dispatcher::calcRxDelay(float score, uint32_t air_time) const {
return (int)((pow(_prefs.rx_delay_base, 0.85f - score) - 1.0) * air_time);
}

Ein Repeater mit schlechtem SNR (weiter entfernt) bekommt damit weniger Verzögerung und sendet früher, was physikalisch sinnvoll ist, da er das Paket für entferntere Empfänger weiterleitet. Ein Repeater nahe am ursprünglichen Sender wartet länger.

set af 9 für gesetzeskonformen Betrieb im deutschen 868-MHz-Band.

6.2 Kurzfristig: PRs mergen

PRMaßnahmeWirkung
#1727Hardware-CAD aktivierenKritisches Fenster: 20 ms → 4 ms

6.3 Mittelfristig: Slot-basiertes Backoff

Statt eines kontinuierlichen ms-Fensters (Pure ALOHA) könnten diskrete Slots eingeführt werden, wobei die Slot-Dauer der CAD-Scan-Zeit entspricht:

Slot-Dauer = 1-2 Symbole ≈ 4-8 ms (= Hardware-CAD-Dauer)
Anzahl Slots = konfigurierbar (z. B. 100-500)
Delay = random(0, N_slots) × slot_duration

Warum das hilft: Zwischen zwei möglichen TX-Startzeitpunkten liegt dann immer mindestens ein CAD-Zyklus. Hardware-CAD als Guard direkt vor TX wird damit strukturell wirksam, statt zufällig.

6.4 Mittelfristig: CAD direkt vor startSendRaw()

Aktuell läuft der CAD-Check nur über den loop()-Poll-Pfad. Eine explizite Prüfung direkt vor dem Senden schließt die Poll-Latenz-Lücke:

Dispatcher.cpp
if (_radio->isChannelActive()) {
next_tx_time = futureMillis(getCADFailRetryDelay());
return;
}
bool success = _radio->startSendRaw(raw, len);

Das entspricht dem CSMA/CA-Grundprinzip: last-moment check unabhängig vom Poll-Intervall.

6.5 Langfristig: Adaptives Contention Window

Analog zu Meshtastics Ansatz könnte das Backoff-Fenster dynamisch skalieren, z. B. nach Hop-Count oder erkannter Kanalauslastung:

W = base_slots × 2^(hop_count)

7. Maßnahmenübersicht

PrioritätMaßnahmeAufwandWirkung
🔴 Sofortset txdelay 2.0 + Cap auf 8,0 erhöhenMinimalP(N=3): 70 % → 26 %
🔴 Sofortset rx_delay_base 8.0MinimalNatürliche SNR-Entzerrung
🔴 Sofortset af 9 (DE/868 MHz)MinimalGesetzeskonformität
🟡 KurzfristigPR #1727 mergen (Hardware-CAD)NiedrigFenster 20 ms → 4 ms
🟢 MittelfristigCAD direkt vor startSendRaw()MittelLücke durch Poll-Latenz schließen
🟢 MittelfristigSlot-basiertes Backoff (CAD-Slot-Dauer)MittelStrukturelle Kollisionsvermeidung
🔵 LangfristigAdaptives Contention WindowHochSkaliert mit Netzgröße
Wichtigstes zuerst

txdelay und rx_delay_base sind sofort konfigurierbar und haben den größten Hebel bei geringstem Aufwand. Slot-basiertes Backoff ist die strukturell richtige Lösung, erfordert aber Code-Änderungen.


8. Vergleich: Meshtastic

Slotted ALOHA mit adaptivem Contention Window

Meshtastic: RadioInterface.cpp
uint8_t CWsize = map(channelUtilizationPercent(), 0, 100, CWmin, CWmax);
delay = random(0, pow_of_2(CWsize)) * slotTimeMsec;

Die Slot-Zeit entspricht exakt der CAD-Scan-Dauer plus Propagationszuschlag, zwischen zwei möglichen Startzeitpunkten liegt immer mindestens ein CAD-Zyklus. Hardware-CAD als Guard direkt vor TX wird damit strukturell wirksam.

SNR-gewichteter Offset für Relay-Nodes

Nodes mit schlechtem SNR senden früher, deckt sich mit dem rx_delay_base-Mechanismus in MeshCore.


9. Relevante Referenzen