Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Nächste Überarbeitung
Vorhergehende Überarbeitung
mc_rxdelay_calc [2026/05/31 12:16] – angelegt bmke-a-2345-tdeckmc_rxdelay_calc [2026/05/31 12:22] (aktuell) – gelöscht bmke-a-2345-tdeck
Zeile 1: Zeile 1:
-====== MeshCore RX Delay Calculator ====== 
- 
-===== What is RX Delay? ===== 
- 
-**RX Delay** (''rxdelay'' / ''rx_delay_base'') is a MeshCore repeater setting that **delays processing of flood-routed packets** based on how good the received signal is (the **packet score**). 
- 
-**Purpose:** MeshCore uses "first packet wins" for route discovery. Without RX delay, a repeater might forward a packet from a **weak, distant hop** before a **stronger, better path** arrives. RX delay gives better signals a head start by holding weaker copies longer in an internal queue. 
- 
-**Only affects flood routes.** Direct-route packets are processed immediately. 
- 
-**Default:** ''rxdelay = 0'' (disabled). Recommended minimum for repeaters is often **2** or higher, depending on neighbor density. 
- 
-**Limits (firmware):** 
-  * Delay **< 50 ms** → packet processed **immediately** (no queue) 
-  * Delay **> 32 000 ms** → capped at 32 seconds 
-  * ''rxdelay'' CLI range: **0 … 20** (0 = off) 
- 
-Sources: [[https://github.com/meshcore-dev/MeshCore/blob/main/examples/simple_repeater/MyMesh.cpp|MyMesh.cpp]], [[https://github.com/meshcore-dev/MeshCore/issues/2064|Issue #2064]], [[https://github.com/meshcore-dev/MeshCore/issues/2123|Issue #2123]] 
- 
-===== The Formula ===== 
- 
-<code javascript> 
-/** 
- * MeshCore RX delay (milliseconds) 
- * 
- * @param {number} rxDelayBase  - CLI value "rxdelay" (0 = disabled, typical 2–10) 
- * @param {number} score        - packet score 0.0 … 1.0 (from SNR + packet length) 
- * @param {number} airtimeMs    - estimated on-air time of the packet in ms 
- * @returns {number} delay in ms (can be negative → treated as immediate) 
- */ 
-function calcRxDelay(rxDelayBase, score, airtimeMs) { 
-  if (rxDelayBase <= 0) return 0; 
-  return (Math.pow(rxDelayBase, 0.85 - score) - 1) * airtimeMs; 
-} 
-</code> 
- 
-**Excel equivalent** (same formula as in your spreadsheet): 
- 
-<code> 
-=(rx_delay_base ^ (0.85 - score) - 1) * airtime 
-</code> 
- 
-Your spreadsheet uses **airtime = 150 ms** as a fixed example. In firmware, ''airtime'' comes from ''getEstAirtimeFor(packet_length)'' and depends on SF, bandwidth, and payload size. 
- 
-===== Packet Score (0.0 – 1.0) ===== 
- 
-The **score** is //not// raw SNR. It is computed in ''packetScoreInt()'' from SNR, spreading factor, and packet length: 
- 
-<code> 
-score = clamp(0, 1, ((SNR - SNR_threshold[SF]) / 10) * (1 - packet_len / 256)) 
-</code> 
- 
-**Interpretation:** 
-  * **score = 1.0** → excellent signal, well above decoding threshold, short packet 
-  * **score = 0.5** → moderate margin above threshold 
-  * **score = 0.0** → at or below SNR threshold (should not decode reliably) 
- 
-SNR thresholds per SF (approx.): SF7 −7.5 dB, SF8 −10, SF9 −12.5, SF10 −15, SF11 −17.5, SF12 −20. 
- 
-**Example:** SF10, SNR = −5 dB, 64-byte packet → score ≈ ((−5 − (−15)) / 10) × (1 − 64/256) = **0.75** 
- 
-===== Reading the Table ===== 
- 
-Your Excel sheet layout: 
- 
-^ rx_delay_base \\ score ^ 0.1 ^ 0.2 ^ 0.3 ^ 0.4 ^ 0.5 ^ 0.6 ^ 0.7 ^ 0.8 ^ 0.9 ^ 1.0 ^ 
-| **1** | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 
-| **2** | 102 | 85 | 70 | 55 | 41 | 28 | 16 | 5 | −5 | −15 | 
-| … | … | … | … | … | … | … | … | … | … | … | 
- 
-  * **Rows** = ''rx_delay_base'' (1 … 19 in your sheet; CLI allows up to 20) 
-  * **Columns** = packet **score** (0.1 … 1.0) 
-  * **Cells** = delay in **milliseconds** (for airtime = 150 ms) 
- 
-**Key behaviors:** 
-  * ''rx_delay_base = 1'' → always **0 ms** delay (feature effectively off) 
-  * ''rx_delay_base'' **between 0 and 1** → **inverted** behavior: weak signals delayed //less// than strong ones (avoid!) 
-  * Higher ''rx_delay_base'' → longer delays overall → stronger collision/backoff spreading 
-  * Higher **score** (better signal) → **shorter** delay → better paths propagate first 
- 
-===== Interactive Calculator ===== 
- 
-Paste the block below into a DokuWiki page. Requires **HTML embed** enabled (''htmlok'' in config, or the htmlok plugin). Wrap in ''<html>…</html>'' if your wiki needs it. 
- 
-<html> 
-<style> 
-  #mc-rxdelay { font-family: sans-serif; max-width: 960px; } 
-  #mc-rxdelay table { border-collapse: collapse; width: 100%; font-size: 13px; } 
-  #mc-rxdelay th, #mc-rxdelay td { border: 1px solid #ccc; padding: 4px 6px; text-align: right; } 
-  #mc-rxdelay th { background: #eef; position: sticky; top: 0; } 
-  #mc-rxdelay td.row-hdr { background: #f5f5f5; font-weight: bold; text-align: center; } 
-  #mc-rxdelay .neg { color: #888; } 
-  #mc-rxdelay .imm { background: #e8f5e9; } 
-  #mc-rxdelay .queued { background: #fff8e1; } 
-  #mc-rxdelay .controls { margin: 12px 0; display: flex; flex-wrap: wrap; gap: 16px; align-items: center; } 
-  #mc-rxdelay .controls label { display: flex; align-items: center; gap: 6px; } 
-  #mc-rxdelay .result-box { background: #f0f7ff; border: 1px solid #9cf; padding: 10px; margin: 12px 0; border-radius: 4px; } 
-</style> 
- 
-<div id="mc-rxdelay"> 
-  <div class="controls"> 
-    <label>Airtime (ms): <input type="number" id="mc-airtime" value="150" min="1" max="5000" step="1"></label> 
-    <label>Highlight rx_delay_base: <input type="number" id="mc-highlight-rx" value="2" min="0" max="20" step="0.1"></label> 
-    <label>Highlight score: <input type="number" id="mc-highlight-score" value="0.5" min="0" max="1" step="0.05"></label> 
-    <button type="button" onclick="mcRxDelayUpdate()">Recalculate</button> 
-  </div> 
- 
-  <div class="result-box" id="mc-single-result"></div> 
- 
-  <div style="overflow-x:auto; max-height: 480px; overflow-y: auto;"> 
-    <table id="mc-rxdelay-table"> 
-      <thead></thead> 
-      <tbody></tbody> 
-    </table> 
-  </div> 
- 
-  <p style="font-size:12px;color:#666;margin-top:8px;"> 
-    Green = &lt; 50 ms (processed immediately) · Yellow = queued · Grey italic = negative (also immediate) 
-  </p> 
-</div> 
- 
-<script type="text/javascript"> 
-/* MeshCore RX delay – matches Excel "rxdelay calc.xlsx" and firmware MyMesh::calcRxDelay */ 
- 
-var MC_RX_SCORES = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]; 
-var MC_RX_BASES  = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]; 
-var MC_RX_THRESHOLD_MS = 50; 
-var MC_RX_MAX_MS = 32000; 
- 
-function mcCalcRxDelay(rxDelayBase, score, airtimeMs) { 
-  if (rxDelayBase <= 0) return 0; 
-  return (Math.pow(rxDelayBase, 0.85 - score) - 1) * airtimeMs; 
-} 
- 
-/** Optional: compute packet score from SNR (SF7–SF12), matching RadioLibWrappers.cpp */ 
-function mcPacketScore(snr, sf, packetLen) { 
-  var thresholds = [-7.5, -10, -12.5, -15, -17.5, -20]; 
-  if (sf < 7 || sf > 12) return 0; 
-  if (snr < thresholds[sf - 7]) return 0; 
-  var rate = (snr - thresholds[sf - 7]) / 10.0; 
-  var penalty = 1 - (packetLen / 256.0); 
-  return Math.max(0, Math.min(1, rate * penalty)); 
-} 
- 
-/** Firmware-applied delay (clamp + threshold) */ 
-function mcEffectiveRxDelay(rxDelayBase, score, airtimeMs) { 
-  var raw = mcCalcRxDelay(rxDelayBase, score, airtimeMs); 
-  if (raw < MC_RX_THRESHOLD_MS) return 0; 
-  return Math.min(Math.round(raw), MC_RX_MAX_MS); 
-} 
- 
-function mcRxDelayUpdate() { 
-  var airtime = parseFloat(document.getElementById('mc-airtime').value) || 150; 
-  var hlRx    = parseFloat(document.getElementById('mc-highlight-rx').value) || 0; 
-  var hlScore = parseFloat(document.getElementById('mc-highlight-score').value) || 0; 
- 
-  var raw = mcCalcRxDelay(hlRx, hlScore, airtime); 
-  var eff = mcEffectiveRxDelay(hlRx, hlScore, airtime); 
-  document.getElementById('mc-single-result').innerHTML = 
-    '<strong>Single value:</strong> rx_delay_base=' + hlRx + 
-    ', score=' + hlScore + ', airtime=' + airtime + ' ms<br>' + 
-    'Formula: (' + hlRx + '<sup>(0.85 − ' + hlScore + ')</sup> − 1) × ' + airtime + 
-    ' = <strong>' + raw.toFixed(1) + ' ms</strong> (raw)<br>' + 
-    'Firmware effective delay: <strong>' + eff + ' ms</strong>' + 
-    (raw < MC_RX_THRESHOLD_MS ? ' (below 50 ms threshold → immediate)' : ''); 
- 
-  var thead = '<tr><th>rx_delay_base \\ score</th>'; 
-  for (var s = 0; s < MC_RX_SCORES.length; s++) { 
-    thead += '<th>' + MC_RX_SCORES[s].toFixed(1) + '</th>'; 
-  } 
-  thead += '</tr>'; 
-  document.querySelector('#mc-rxdelay-table thead').innerHTML = thead; 
- 
-  var tbody = ''; 
-  for (var r = 0; r < MC_RX_BASES.length; r++) { 
-    var rx = MC_RX_BASES[r]; 
-    var rowClass = (Math.abs(rx - hlRx) < 0.01) ? ' style="outline:2px solid #39f;"' : ''; 
-    tbody += '<tr' + rowClass + '><td class="row-hdr">' + rx + '</td>'; 
-    for (var c = 0; c < MC_RX_SCORES.length; c++) { 
-      var sc = MC_RX_SCORES[c]; 
-      var val = mcCalcRxDelay(rx, sc, airtime); 
-      var cls = ''; 
-      if (val < 0) cls = 'neg'; 
-      else if (val < MC_RX_THRESHOLD_MS) cls = 'imm'; 
-      else cls = 'queued'; 
-      var hi = (Math.abs(rx - hlRx) < 0.01 && Math.abs(sc - hlScore) < 0.001) ? ' outline:2px solid #f90;' : ''; 
-      tbody += '<td class="' + cls + '" style="' + hi + '">' + 
-        (val < 0 ? '<span class="neg">' + val.toFixed(0) + '</span>' : val.toFixed(0)) + 
-        '</td>'; 
-    } 
-    tbody += '</tr>'; 
-  } 
-  document.querySelector('#mc-rxdelay-table tbody').innerHTML = tbody; 
-} 
- 
-if (document.readyState === 'loading') { 
-  document.addEventListener('DOMContentLoaded', mcRxDelayUpdate); 
-} else { 
-  mcRxDelayUpdate(); 
-} 
-</script> 
-</html> 
- 
-===== SNR → Score Helper (optional second widget) ===== 
- 
-<html> 
-<style> 
-  #mc-score-calc { font-family: sans-serif; max-width: 480px; } 
-  #mc-score-calc .controls { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 8px; } 
-  #mc-score-calc .out { background: #f5f5f5; padding: 8px; border-radius: 4px; } 
-</style> 
-<div id="mc-score-calc"> 
-  <p><strong>Estimate packet score from SNR</strong></p> 
-  <div class="controls"> 
-    <label>SNR (dB): <input type="number" id="mc-snr" value="-5" step="0.5"></label> 
-    <label>SF: <select id="mc-sf"><option>7</option><option>8</option><option>9</option><option selected>10</option><option>11</option><option>12</option></select></label> 
-    <label>Packet len: <input type="number" id="mc-plen" value="64" min="1" max="256"></label> 
-    <button type="button" onclick="mcScoreUpdate()">Calc</button> 
-  </div> 
-  <div class="out" id="mc-score-out"></div> 
-</div> 
-<script type="text/javascript"> 
-function mcScoreUpdate() { 
-  var snr = parseFloat(document.getElementById('mc-snr').value); 
-  var sf  = parseInt(document.getElementById('mc-sf').value, 10); 
-  var pl  = parseInt(document.getElementById('mc-plen').value, 10); 
-  var score = mcPacketScore(snr, sf, pl); 
-  document.getElementById('mc-score-out').innerHTML = 
-    'Score = <strong>' + score.toFixed(3) + '</strong> — use this in the table above.'; 
-} 
-mcScoreUpdate(); 
-</script> 
-</html> 
- 
-===== Practical Tuning Guide ===== 
- 
-  - **Start with ''rxdelay 2''** on repeaters in busy areas; increase if you still see duplicate flood collisions. 
-  - **Never use 0 < rxdelay < 1** — it reverses the logic (bad paths win). 
-  - **''rxdelay 1''** gives zero delay for all scores (same as off). 
-  - Compare delays for your typical packet airtime: a 300 ms airtime doubles all table values. 
-  - Newer firmware may **autotune** delays from neighbor count (CLI: ''get autotune'' / ''set autotune on''). 
-  - RX delay is complementary to **TX delay** (''txdelay''): TX delay spreads //transmissions//, RX delay spreads //reception/processing// of floods. 
- 
-===== CLI Reference ===== 
- 
-<code> 
-get rxdelay          # show current value (float, 0 = off) 
-set rxdelay 2          # enable with base 2 
-</code> 
- 
-Companion radio stores the value internally as millis × 1000; repeater/room/sensor use the float directly. 
  
  • mc_rxdelay_calc.1780222609.txt.gz
  • Zuletzt geändert: 2026/05/31 12:16
  • von bmke-a-2345-tdeck