FHSS
IMPLEMENTATION
This page explains how FHSS protects drone communication links against enemy electronic warfare jamming, and how ELRS implements it in the EU 868 MHz ISM band for consumer-grade FPV radios. Silvus StreamCaster MANET uses the 140–600 MHz military band with a much larger channel count — both systems are covered below.
The Problem — Enemy Jamming Your Radio
Your FPV drone communicates with the ground station on a radio frequency — 868 MHz for ELRS in the EU ISM band. The enemy knows this. They have jammers that blast powerful noise on that frequency, drowning out your signal. Imagine trying to have a phone conversation while someone holds an air horn next to your ear. That's jamming.
If your radio stays on one fixed frequency, the enemy only needs one jammer on that frequency. Game over. Your drone loses contact and either crashes or flies away uncontrolled.
The Solution — Hop Between Channels
Instead of staying on one frequency, FHSS rapidly switches between many different channels. At 14:32:08.001, you're on channel 23. At 14:32:08.008, you're on channel 71. At 14:32:08.015, you're on channel 4. You change channel up to 150 times per second.
The hopping pattern looks random but is actually determined by a shared secret (the binding phrase). Your transmitter and receiver both know the pattern. The enemy doesn't. To jam FHSS, the enemy would need to jam ALL channels simultaneously — which requires enormously more power and expensive equipment than jamming a single channel.
ELRS in the 868 MHz band uses approximately 80 channels across the EU ISM allocation (863–870 MHz). Silvus MANET in the 140–600 MHz military band uses up to 4,600 channels. Even if the enemy jams many of those channels, FHSS keeps hopping and finds the ones that are clear. Your link degrades but doesn't die.
How ELRS Implements FHSS
ELRS 868 MHz FHSS PARAMETERS
ELRS actually combines TWO anti-jamming techniques. FHSS (channel hopping) makes it hard to find your signal. LoRa modulation (spread spectrum) makes the signal look like noise even if the enemy finds the right channel. Together, they make ELRS significantly harder to jam than older systems like analog FPV video (which sits on one fixed channel and is trivially jammed).
Trade-Offs: Speed vs Range vs Jam Resistance
Higher hop rate = harder to jam, but shorter range. At 500 Hz, you change channel 500 times per second — extremely hard to track. But each packet has very little time on air, so range drops to about 5 km. At 50 Hz, the signal stays on each channel longer, reaches 30+ km, but is easier for a sophisticated jammer to follow.
For military FPV operations in a jamming environment on ELRS 868 MHz, 150 Hz is the recommended balance: 10+ km range, 6.67ms per channel (too fast for most tactical jammers to follow), and low enough latency for responsive FPV flight.
What FHSS Cannot Protect Against
Mathematical Derivation — Why FHSS Defeats Narrowband Jamming
The "FHSS protects against jamming" claim rests on a specific mathematical inequality: the probability that a narrowband jammer happens to occupy the channel currently carrying the drone's link. This section derives that probability step-by-step, shows how it composes across multiple jammers and hops per second, and derives the power ratio required for a jammer to threaten FHSS. The math is standard probability and information theory (Proakis & Salehi, Digital Communications, McGraw-Hill 2008, ch. 12) — this page's contribution is specializing the derivation to ELRS and Silvus channel counts and showing the concrete packet-loss consequences.
Step 1 — Probability a narrowband jammer blocks one hop
A narrowband jammer occupies J contiguous channels out of N total. A uniformly random frequency hop lands on a blocked channel with probability:
P(hop_blocked) = J / N
For ELRS at 868 MHz with ~80 channels and a 1-channel jammer:
P(hop_blocked) = 1/80 = 1.25%
For Silvus MANET 140-600 MHz with 4600 channels and a 1-channel jammer:
P(hop_blocked) = 1/4600 = 0.022%
Per-hop probability is small but non-zero. Link survival depends on what happens over many hops, not one.
Step 2 — Consecutive-hop failure probability
The link survives if at least one packet out of the last K gets through (ARQ or FEC recovers from occasional packet loss). Probability of losing K consecutive packets to a single jammer:
P(K_consecutive_blocked) = (J/N)^K
For ELRS (N=80), single-channel jammer, 3-packet ARQ window:
P(3_consecutive_blocked) = (1/80)³ = 1.95 × 10⁻⁶ = 0.0002%
Mean time between triple-blocks at 150 Hz hop rate: 1 / (150 × 2e-6) = 3,300 s = 55 min
For Silvus (N=4600), single-channel jammer, 3-packet window:
P = (1/4600)³ = 1.03 × 10⁻¹¹
Mean time between triple-blocks at 100 Hz: 1 / (100 × 1e-11) = 10⁹ s = 31 years
Operational consequence: against a narrowband jammer, ELRS sees occasional packet loss (tolerable with FEC), while Silvus essentially never loses consecutive packets.
Step 3 — Multi-jammer composition
If the enemy deploys M narrowband jammers each covering J channels, and positioned on different frequencies, the effective blocked bandwidth is M × J channels (assuming no overlap):
P(hop_blocked, M jammers) = M·J / N (for M·J ≪ N)
ELRS with 10 narrowband jammers (each 1 channel):
P(hop_blocked) = 10/80 = 12.5%
Single-packet loss rate: 12.5%
3-packet-window loss rate: (0.125)³ = 0.20% — still recoverable
Silvus with 100 narrowband jammers:
P(hop_blocked) = 100/4600 = 2.2%
3-packet-window loss: (0.022)³ = 0.001% — imperceptible
Silvus with 1000 narrowband jammers:
P(hop_blocked) = 1000/4600 = 22%
3-packet-window loss: (0.22)³ = 1.1% — noticeable but not fatal
The linear scaling with M shows why jamming FHSS is expensive: the enemy needs thousands of narrowband jammers to make the link unusable, not just one.
Step 4 — Barrage jamming power ratio
A barrage jammer attempts to block ALL channels simultaneously by broadcasting noise across the full bandwidth. To produce the same per-channel power-spectral-density as a narrowband jammer, it needs N times the total power (same PSD × N bandwidth):
P_barrage / P_narrowband = N
For ELRS 7 MHz band vs 87.5 kHz channel: ratio = 7000/87.5 = 80×
For Silvus 460 MHz band vs 100 kHz channel: ratio = 460000/100 = 4600×
If a narrowband jammer requires 50 W to overcome the drone's TX power within one channel,
barrage-jamming Silvus requires 50 × 4600 = 230,000 W = 230 kW.
This is the power of a large vehicle-mounted EW system (Krasukha-4 class) — rare,
expensive, and easily targeted because of its RF emission signature.
Barrage jamming of Silvus MANET requires specialized strategic EW assets, not the squad-level tactical jammers prolific in current operations. This is the mathematical reason FSG-A specifies Silvus for battalion-above deployments rather than ELRS.
Worked Example 1 — ELRS link survival against 10 narrowband jammers
Russian Lesochek-type systems deploy 5–10 narrowband jammers in a defended area, each covering 1 MHz (≈10 ELRS channels) of the 863–870 MHz band.
Effective blocked bandwidth: 10 × 1 MHz = 10 MHz out of 7 MHz ELRS band.
Wait — 10 MHz > 7 MHz band. This means the entire ELRS band IS blocked.
ELRS link fails completely in this threat environment.
Operational conclusion: ELRS (878 MHz ISM) is VULNERABLE to modern Russian
tactical EW. It is suitable for training and permissive environments, NOT
for combat in a contested RF environment. FSG-A's tactical FPV deployment
must use either fiber-optic FPV (immune to RF) or migrate to military bands
(300 MHz MANET, 2.4 GHz with much wider channel allocation).
This is an uncomfortable finding for anyone using ELRS tactically. The math does not lie — ELRS was designed for hobby use with a handful of consumer drones nearby, not for operations where the enemy spends €5000 per jammer to deny your radio. The derivation makes this explicit rather than burying it in a footnote.
Worked Example 2 — Silvus MANET survival against 100 tactical jammers
Large-scale Russian deployment with 100 narrowband jammers each covering 4 MHz (40 Silvus channels), spread across the 140–600 MHz band.
Effective blocked bandwidth: 100 × 4 MHz = 400 MHz out of 460 MHz Silvus band.
Blocked channels: 400 MHz / 100 kHz = 4000 out of 4600.
Unblocked channels: 600 (13% of original).
Per-hop survival probability: 600/4600 = 13%
Per-hop loss probability: 87%
3-packet-window loss: (0.87)³ = 66%
Link performance: severely degraded, roughly 1 in 3 triple-packet windows lost.
Voice/video quality: poor; control data (small packets, FEC): still gets through.
Lisa 26 degradation response: MANET drops from 34 Mbps clean to ~1 Mbps usable.
Commander's COP updates every 5 seconds instead of every 100 ms. Still operational,
just slower. System degrades gracefully rather than failing catastrophically.
If the enemy deploys 1000 jammers (€5M investment for 1000 × €5k systems):
Blocked bandwidth: 1000 × 4 MHz = 4000 MHz > 460 MHz Silvus band → full saturation
Silvus link fails at this threat level.
Counter-counter-measure: operate FROM BEYOND the jammers' effective range,
or use directional beamforming to null jammer directions (see crpa-antennas.html).
Verification Code — Jamming Probability Calculator
def p_hop_blocked(n_channels, n_jammers, channels_per_jammer=1):
"""Probability that a uniform random hop lands on a jammed channel."""
blocked = min(n_channels, n_jammers * channels_per_jammer)
return blocked / n_channels
def p_k_consecutive_blocked(p_single, k):
"""Probability that K consecutive hops all hit blocked channels."""
return p_single ** k
def mean_time_between_blocks(p_single, hop_rate_hz, k=3):
"""Seconds between K-consecutive-block events on average."""
p_k = p_k_consecutive_blocked(p_single, k)
if p_k <= 0:
return float('inf')
return 1.0 / (hop_rate_hz * p_k)
def barrage_power_ratio(n_channels):
"""Power multiplier needed for barrage vs narrowband jamming."""
return n_channels
# Reproduce narrowband single-channel case
p_elrs_1 = p_hop_blocked(n_channels=80, n_jammers=1)
p_silvus_1 = p_hop_blocked(n_channels=4600, n_jammers=1)
print(f"ELRS 1 jammer: p_block={p_elrs_1*100:.2f}%") # Expected 1.25%
print(f"Silvus 1 jammer: p_block={p_silvus_1*100:.4f}%") # Expected 0.0217%
# 3-packet window losses
print(f"ELRS 3-consec: {p_k_consecutive_blocked(p_elrs_1, 3)*100:.6f}%")
print(f"Silvus 3-consec: {p_k_consecutive_blocked(p_silvus_1, 3)*100:.9f}%")
# Mean time between triple-blocks at typical hop rates
print(f"ELRS triple @150Hz: {mean_time_between_blocks(p_elrs_1, 150):.0f} s")
print(f"Silvus triple @100Hz: {mean_time_between_blocks(p_silvus_1, 100)/3600:.0f} h")
# Worked examples
print(f"\nELRS 10 jammers: p_block={p_hop_blocked(80, 10)*100:.1f}% — link SATURATED")
p_silvus_100 = p_hop_blocked(4600, 100, channels_per_jammer=40)
print(f"Silvus 100 jammers: p_block={p_silvus_100*100:.1f}%, 3-consec-loss={p_k_consecutive_blocked(p_silvus_100,3)*100:.1f}%")
# Barrage power requirements
print(f"\nBarrage power multiplier ELRS: {barrage_power_ratio(80):>5}× narrowband")
print(f"Barrage power multiplier Silvus: {barrage_power_ratio(4600):>5}× narrowband")
Why This Derivation Matters Operationally
Four operational decisions depend on the FHSS jamming math being correct. If we get this wrong the consequences are concrete: FSG-A deploys ELRS into a battlespace where it cannot survive, commanders invest in FHSS as their sole EW countermeasure when it isn't sufficient, and brigade signals officers pick band allocations that waste spectrum on jammer-vulnerable links.
First, band selection for tactical vs strategic use: Worked Example 1 shows that ELRS's 7 MHz ISM band is saturated by 10 narrowband jammers — a realistic Russian tactical deployment. The math says ELRS is UNSUITABLE for contested RF environments. Lesson: FSG-A must either use fiber-optic FPV (immune to all RF jamming, see fiber-fpv.html) or migrate tactical links to military bands with 500+ MHz of channel allocation. This is not an opinion — it is what the probability math forces.
Second, Silvus MANET justification: Worked Example 2 shows that even 100 narrowband jammers (a significant investment) only degrade Silvus to 13% channel availability — enough to lose most video but preserve control. This graceful degradation is the mathematical reason Silvus is specified for battalion-and-above tactical networks, not because of its MANET mesh features alone. A three-tier architecture using ELRS instead of Silvus would collapse in the same EW environment that Silvus survives.
Third, barrage jamming threat assessment: the 4600× power ratio for Silvus means a barrage jammer needs ~230 kW — only large vehicle-mounted Russian systems (Krasukha-4, Shipovnik-Aero) produce this level. These are strategic assets, not tactical, and they are easily targeted because of their RF signature. The derivation tells the planner that barrage jamming is a rare threat requiring specific CUAS response (anti-radiation drones, ISR location of emitter) rather than a constant operational concern.
Fourth, key rotation interval: the 24-hour key rotation for Silvus hopping sequences is derived from the assumption that even if the enemy records the sequence, the 2²⁵⁶ keyspace is computationally intractable. The math makes this explicit — changing the interval to 1 hour provides no cryptographic benefit (the key is already safe) but increases operational cost and risk of synchronization failures. 24 hours is the interval that balances cryptographic margin against operational practicality.
FHSS jamming probabilities are validated in provable_claims.py under FHSS_NARROWBAND_MISS (99.98% miss rate for single-channel jammer on 4600-channel system), FHSS_JAM_POWER_RATIO (4600× power requirement for barrage jamming), and FHSS_ELRS_SATURATED_10JAMMERS (new claim for the saturation finding). The HMAC-SHA256 security argument is validated under HMAC_COLLISION_YEARS.
Implementation
# FHSS Channel Hopping Demonstration
import hashlib, struct
def fhss_hop_sequence(seed_key, n_channels=4600, hops_per_sec=100):
"""Generate deterministic pseudo-random hop sequence."""
channels = []
for hop_index in range(hops_per_sec * 60): # 1 minute of hops
# HMAC-based channel selection (both sides have same seed)
h = hashlib.sha256(seed_key + struct.pack(">I", hop_index)).digest()
channel = struct.unpack(">H", h[:2])[0] % n_channels
channels.append(channel)
return channels
# Silvus StreamCaster: 140-600 MHz, 100 kHz channels
# 460 MHz / 100 kHz = 4,600 channels
hops = fhss_hop_sequence(b"SECRET_KEY_256BIT", n_channels=4600)
print(f"First 10 hops: {hops[:10]}")
print(f"Unique channels in 1 min: {len(set(hops[:6000]))}")
# Narrowband jammer on one channel: misses 4599/4600 = 99.98% of hops
# Barrage jammer across ALL 4600: needs 4600× more power
Sources
Mathematically verified estimates. "Narrowband jammer on one of 4,600 channels misses 99.98% of hops" — (N − 1) / N, validated in provable_claims.py under FHSS_NARROWBAND_MISS. "Barrage jamming requires 4,600× more power" — validated under FHSS_JAM_POWER_RATIO. HMAC-SHA256 256-bit key cryptographic strength (2²⁵⁶ values) — validated under HMAC_COLLISION_YEARS.
Parameter sources. ELRS band 863–870 MHz — EU ISM band regulated under ETSI EN 300 220. LoRa modulation model — Semtech whitepaper. ELRS packet rates 50/150/500 Hz — ExpressLRS documentation. RadioMaster Ranger 900 MHz module with 1 W TX — manufacturer specification. Silvus StreamCaster 140–600 MHz band with 4,600 channels — Silvus published data.
Operational estimates — not validated by FSG-A field testing. 30+/10+/5+ km ranges at 50/150/500 Hz are typical values from ExpressLRS documentation under line-of-sight conditions, not measured by FSG-A. The 24-hour key rotation interval is a Lisa 26 design choice, not operationally calibrated. The 30-second propagation time to all MANET nodes is an estimate based on Silvus beacon interval, not measured. Pole-21 jammer "limited area" effectiveness is a general characterization from RUSI reports, not quantitatively validated.
External standards and references. ExpressLRS protocol documentation (expresslrs.org, 2024). Semtech LoRa modulation whitepaper (semtech.com, 2023). RadioMaster Ranger 900 MHz specifications (radiomasterrc.com). "Electronic Warfare in the Ukraine Conflict" — RUSI report (2023). FOI Memo 8336 on drone EW hardening (2024). FSG-A has no own FHSS measurements — parameters are from ExpressLRS, Silvus, and Semtech published specifications.
Channel Hopping Sequence Security
The hopping sequence in Silvus StreamCaster is generated from a shared seed key using HMAC-SHA256. Both transmitter and receiver compute the same pseudo-random channel sequence from the key — without the key, the sequence is computationally unpredictable. An adversary attempting to follow the hops would need to discover the 256-bit key, which has 2²⁵⁶ possible values — brute force is infeasible with any current or projected computing technology.
An adversary with a wideband receiver (SDR spanning 140-600 MHz simultaneously) can observe the hopping pattern in real time — they see brief energy bursts appearing at random frequencies. However, observing the pattern does not reveal the key, and the pattern changes with every key rotation. Even if the adversary records the complete hopping sequence for one key period, this does not predict the sequence for the next key period. Key rotation interval in Lisa 26: every 24 hours, triggered by the brigade signals officer via a single Lisa 26 command that propagates to all MANET nodes within 30 seconds.