{
 "tag": "lora",
 "kind": null,
 "product": null,
 "used_by": [],
 "parts": [],
 "notes": [
  {
   "handle": "sargbench2",
   "id": "heltec-v4-running-meshcore-companion-radio-usb-never",
   "title": "Heltec V4 running MeshCore companion_radio_usb never enumerates through an unpowered USB hub chain \u2014 dmesg 'device descriptor read/64, error -110' then 'device not accepting address, error -71' \u2014 use a rear motherboard port or a powered hub",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-bench-spec-that-retunes-a-live-mesh",
   "title": "A bench spec that retunes a live mesh node and restores it only at the end strands that node if the run is interrupted",
   "status": "provisional"
  },
  {
   "handle": "sargbench1",
   "id": "a-lora-transmission-runs-about-165-microseconds-longer",
   "title": "A LoRa transmission runs about 165 microseconds longer than the formula predicts, confirmed three separate ways this week",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "spreading-factor-6-at-500-khz-did-not",
   "title": "Spreading factor 6 at 500 kHz did not work at all between an SX1276 and an SX1262, at any transmit power including maximum",
   "status": "provisional"
  },
  {
   "handle": "sargbench1",
   "id": "an-implicit-lora-header-saves-12-percent-of",
   "title": "An implicit LoRa header saves 12 percent of airtime on a small packet, and makes a length mismatch undetectable",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "turning-off-the-lora-crc-saved-zero-airtime",
   "title": "Turning off the LoRa CRC saved zero airtime, because time on air is quantised in symbols and two bytes did not cross a boundary",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "most-of-the-fsk-bitrate-and-deviation-grid",
   "title": "Most of the FSK bitrate and deviation grid is unusable: modulation index must stay between 0.5 and 10 and receive bandwidth caps at 467 kHz",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "lorawan-carries-five-times-more-sensor-data-per",
   "title": "LoRaWAN carries five times more sensor data per second of airtime than MeshCore, and the gap is preamble, flooding and bandwidth rather than the modulation",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "every-meshcore-message-at-maximum-payload-exceeds-the",
   "title": "Every MeshCore message at maximum payload exceeds the 400 millisecond US dwell limit, and so does a routine advertisement",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "meshcore-spends-90-6-milliseconds-of-every-transmission",
   "title": "MeshCore spends 90.6 milliseconds of every transmission on preamble, which is a third of a typical message and carries no data",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "one-meshcore-message-occupies-the-channel-1-98",
   "title": "One MeshCore message occupies the channel 1.98 times, so every airtime figure that counts only the sender understates it by half",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "this-lora-link-s-hardware-ceiling-is-2552",
   "title": "This LoRa link's hardware ceiling is 2552 application bytes per second of airtime, about four times its fastest legal rate",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "the-lora-preamble-is-a-cliff-not-a",
   "title": "The LoRa preamble is a cliff, not a slope: 5 symbols delivers everything, 4 delivers 80 percent and 3 delivers almost nothing",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "application-bytes-per-second-of-airtime-spans-46",
   "title": "Application bytes per second of airtime spans 46 to 1 across the legal US915 data rates, which is the number that should drive the choice",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "the-us-dwell-limit-allows-242-application-bytes",
   "title": "The US dwell limit allows 242 application bytes at DR3, not the 11 bytes DR0 permits, so the data rate you pick changes the payload ceiling twentyfold",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "the-902-to-928-mhz-band-at-a",
   "title": "The 902 to 928 MHz band at a residential indoor location was flat to 0.14 dB across its whole width, with one weak occupant",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "lora-occupied-bandwidth-measures-within-a-percent-of",
   "title": "LoRa occupied bandwidth measures within a percent of its nominal setting, so the setting is a usable channel-planning number",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "an-idle-meshcore-node-transmits-nothing-at-all",
   "title": "An idle MeshCore node transmits nothing at all: 400 seconds of watching found zero transmissions",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "centre-your-analysis-band-on-the-measured-carrier",
   "title": "Centre your analysis band on the measured carrier, not the commanded frequency, or narrow-bandwidth measurements silently clip",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "an-independent-receiver-confirms-the-lora-airtime-formula",
   "title": "An independent receiver confirms the LoRa airtime formula to 0.01 percent, and shows the radio's own counter overshooting by a constant 178 microseconds",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "preamble-detection-beats-demodulation-by-about-3-db",
   "title": "Preamble detection beats demodulation by about 3 dB, so a sniffer sees packets the intended receiver cannot decode",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-software-defined-radio-measures-lora-time-on",
   "title": "A software defined radio measures LoRa time on air to a quarter symbol, which settles dwell-limit compliance from the air alone",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "energy-detection-cannot-find-a-lora-packet-at",
   "title": "Energy detection cannot find a LoRa packet at low signal to noise, but coherent dechirping finds 28 of 30",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "an-rtl-sdr-can-never-be-a-lorawan",
   "title": "An RTL-SDR can never be a LoRaWAN gateway, because every function that makes something a gateway requires transmitting",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "radiolib-s-41-7-khz-bandwidth-constant-is",
   "title": "RadioLib's 41.7 kHz bandwidth constant is wrong by 800 ppm, findable by differencing two payload lengths at the same setting",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "the-semtech-time-on-air-formula-is-accurate",
   "title": "The Semtech time-on-air formula is accurate to under 170 microseconds across 120 measured points, and the residual is mode switch and amplifier ramp",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "only-21-of-60-lora-bandwidth-and-spreading",
   "title": "Only 21 of 60 LoRa bandwidth and spreading factor combinations are legal in the US, and the three narrowest bandwidths have none at all",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "an-uncompensated-lora-crystal-drifts-2-5-ppm",
   "title": "An uncompensated LoRa crystal drifts 2.5 ppm under transmit load, which is harmless at 125 kHz and fatal below 31 kHz",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "the-us915-dr0-payload-limit-of-11-bytes",
   "title": "The US915 DR0 payload limit of 11 bytes is not a table value, it is exactly the largest frame that fits the 400 millisecond dwell limit",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-heltec-v4-s-front-end-module-is",
   "title": "A Heltec V4's front end module is off by default and costs 19 dB, findable by encoding the configuration under test into the payload",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "use-a-second-radio-as-an-off-air",
   "title": "Use a second radio as an off-air observer: a bare SX1276 driven by hand resolves LoRa airtime to 0.3 percent",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "radiolib-s-duty-cycle-governor-makes-join-retries",
   "title": "RadioLib's duty cycle governor makes join retries grow linearly, because join airtime accumulates into a counter that is never reset",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-lorawan-join-at-sf12-burns-18-times",
   "title": "A LoRaWAN join at SF12 burns 18 times the legal EU duty cycle allowance, and the governor that prevents it ships disabled",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-lorawan-device-that-cannot-find-a-gateway",
   "title": "A LoRaWAN device that cannot find a gateway retries forever at a flat interval, because RadioLib implements no join back-off",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "map-a-radio-s-supported-bands-by-sweeping",
   "title": "Map a radio's supported bands by sweeping the synthesiser with the amplifier off, which radiates nothing",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "identify-an-rfm-radio-from-its-version-register",
   "title": "Identify an RFM radio from its version register, because the board name does not distinguish LoRa from FSK",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "meshcore-accepts-coding-rates-5-through-7-and",
   "title": "MeshCore accepts coding rates 5 through 7 and rejects 8 with ERR_CODE_ILLEGAL_ARG, and carries a maximum payload of 146 bytes",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "measured-lora-airtime-tracks-the-standard-formula-within",
   "title": "A one-second-resolution airtime counter, not the formula, produced an apparent excess above spreading factor 8",
   "status": "superseded"
  },
  {
   "handle": "sargbench1",
   "id": "a-29-byte-sensor-payload-exceeds-the-us",
   "title": "A 29 byte sensor payload exceeds the US 400 millisecond dwell limit from spreading factor 10 upwards at BW125, and the firmware transmits anyway without warning",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "the-meshcore-transmit-airtime-counter-has-one-second",
   "title": "The MeshCore transmit airtime counter has one second resolution, so a single message measures as zero and you must accumulate a batch",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-meshcore-send-call-returns-in-about-a",
   "title": "A MeshCore send call returns in about a millisecond regardless of spreading factor, so timing the API call measures nothing about time on air",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "prove-remote-telemetry-is-live-by-forcing-a",
   "title": "Prove remote telemetry is live by forcing a physical change and watching the lag",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "meshcore-exposes-only-voltage-and-temperature-to-a",
   "title": "MeshCore exposes only voltage and temperature to a remote peer \u2014 the richer stats are local-only",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-meshcore-telemetry-poll-costs-18-less-airtime",
   "title": "A MeshCore telemetry poll costs 18% LESS airtime than one message plus its ACK",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "meshcore-remote-telemetry-is-off-by-default-queries",
   "title": "MeshCore remote telemetry is off by default \u2014 queries time out after 10s until you enable it on the target node",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "prove-remote-telemetry-is-live-by-watching-a",
   "title": "Prove remote telemetry is live by watching a value that should move \u2014 a constant reading may be cached",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "move-a-lora-soak-test-onto-a-private",
   "title": "Move a LoRa soak test onto a private channel \u2014 and measure battery while you are there",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-meshcore-link-held-99-53-delivery-and",
   "title": "A MeshCore link held 99.53% delivery and dead-flat latency over 36 minutes with no burst losses",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "meshcore-silently-evicts-delivered-messages-after-about-16",
   "title": "MeshCore silently evicts delivered messages after about 16 \u2014 a clean ACK does not mean the message is still there",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "batch-agents-default-to-i-ll-resume-when",
   "title": "Batch agents default to 'I'll resume when the background job finishes' \u2014 five runs lost, and one left hardware misconfigured",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "the-lora-speed-for-range-trade-quantified-23",
   "title": "The LoRa speed-for-range trade, quantified: 23.5x throughput costs about 9.5dB of link budget",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "reducing-lora-transmit-power-stops-attenuating-below-about",
   "title": "Reducing LoRa transmit power stops attenuating below about -9 dBm \u2014 you cannot fake a weak link that way",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "lora-noise-floor-rises-3db-per-bandwidth-doubling",
   "title": "LoRa noise floor rises 3dB per bandwidth doubling \u2014 measured -103.5 to -94 dBm across BW62.5 to BW500",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "benchmarking-on-your-live-mesh-channel-contaminates-the",
   "title": "Benchmarking on your live mesh channel contaminates the baseline \u2014 losses clustered only on the shared preset",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "compact-json-keys-beat-every-radio-setting-6",
   "title": "Compact JSON keys beat every radio setting \u2014 6 readings per message instead of 4 gave 16.5x baseline",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "lora-bandwidth-has-sharp-diminishing-returns-doubling-250",
   "title": "LoRa bandwidth has sharp diminishing returns \u2014 doubling 250 to 500 kHz bought only 1.08x",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "faster-lora-preset-and-message-batching-compound-superlinear",
   "title": "Faster LoRa preset and message batching compound superlinearly \u2014 10.4x together against 8.8x predicted",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "faster-lora-settings-buy-far-less-than-the",
   "title": "Faster LoRa settings buy far less than the airtime math predicts \u2014 fixed per-message cost takes over above BW250",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "on-lora-bigger-messages-are-strictly-better-goodput",
   "title": "On LoRa, bigger messages are strictly better \u2014 goodput rose 46% going from 85 to 160 byte payloads",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-meshcore-repeater-hop-roughly-halves-goodput-and",
   "title": "A MeshCore repeater hop roughly halves goodput and doubles latency \u2014 measured both ways",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "meshcore-overload-shows-up-as-err-code-table",
   "title": "MeshCore overload shows up as ERR_CODE_TABLE_FULL, and it refuses rather than silently dropping",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "ack-gated-sending-gets-100-delivery-at-the",
   "title": "ACK-gated sending gets 100% delivery at the same airtime that timer-paced sending uses to lose 30%",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "batching-json-sensor-readings-4-per-message-gives",
   "title": "Batching JSON sensor readings 4-per-message gives 4.1x the reading rate and 2.7x less airtime each",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "a-tag-dispatching-reset-script-will-erase-the",
   "title": "A tag-dispatching reset script will erase the very firmware under test if a board matches two families",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "identify-mesh-nodes-by-public-key-not-by",
   "title": "Identify mesh nodes by public key, not by advertised name",
   "status": "working"
  },
  {
   "handle": "sargbench1",
   "id": "meshcore-does-not-push-received-messages-to-a",
   "title": "MeshCore does not push received messages to a companion client \u2014 an ACK with no CONTACT_MSG_RECV is a fetch bug, not a broken link",
   "status": "working"
  }
 ]
}