Every networking technology we have explored so far — Wi-Fi mesh networks, ad-hoc wireless, peer-to-peer protocols — shares a fundamental assumption about the physical layer: you are trading range for bandwidth. Wi-Fi gives you hundreds of megabits per second, but only across tens of meters. Point-to-point microwave links can reach several kilometers, but they require careful antenna alignment, clear line of sight, and significant power. The faster you push data, the shorter the reach, and the hungrier the radio.
But what if you flipped that equation entirely? What if you were willing to send data at an absurdly slow rate — a few hundred bits per second, barely enough for a short text message — in exchange for a signal that could travel ten, fifteen, even twenty kilometers on a battery that lasts for years?
This is the domain of Low-Power Wide-Area Networks (LPWAN) — a family of technologies designed for a very specific and increasingly important use case: sending small amounts of data over very long distances using very little power. LPWAN does not replace Wi-Fi or cellular. It occupies a fundamentally different niche, one that turns out to be extraordinarily useful for alternative networks, off-grid communication, environmental monitoring, and the kind of infrastructure-independent connectivity that this book is all about.
Among the LPWAN technologies, one stands out for its openness, its accessibility, and its grassroots adoption: LoRa (Long Range), a radio modulation technique that enables anyone with a $10 module to transmit data across kilometers without a license, without a subscription, and without any infrastructure beyond the nodes themselves. Combined with LoRaWAN (the network protocol built on top of LoRa), Meshtastic (a mesh firmware that turns LoRa devices into a decentralized communication network), and The Things Network (a community-built global LoRaWAN infrastructure), LoRa has become the foundational technology for a growing movement of people building their own long-range networks from scratch.
This chapter is about understanding that technology from the physics up, and then building real things with it.
LPWAN stands for Low-Power Wide-Area Network. The name describes the three defining constraints of this technology class:
Low Power. LPWAN devices are designed to run on batteries — often coin cells or small lithium cells — for months or years without replacement. A typical LoRa sensor node consuming 10-50 milliamps during transmission and dropping to microamps during sleep can easily last two to five years on a pair of AA batteries, depending on how frequently it transmits. This is not a minor engineering detail; it is the entire point. A sensor deployed on a remote hilltop, in a river, on a fence post in the middle of a thousand-acre farm — it needs to just work, silently, for years, without anyone climbing up to change batteries.
Wide Area. LPWAN technologies achieve ranges measured in kilometers, not meters. In open rural terrain, 10-15 km is routine. In urban environments with buildings and interference, 2-5 km is typical. Record-setting experiments have achieved hundreds of kilometers in extreme conditions (high-altitude balloons, mountain-to-valley paths, over water). This is not Wi-Fi. This is closer to the reach of a cellular tower, but without the cellular tower.
Network. LPWAN is not just a radio link — it is a network architecture. Protocols like LoRaWAN define how thousands of devices can share the airwaves, how data is routed from end devices through gateways to application servers, how devices are authenticated and data is encrypted. The “N” in LPWAN means these technologies are designed to scale from a single sensor to city-wide or even country-wide deployments.
The trade-off for all of this is bandwidth. LPWAN data rates range from about 300 bits per second to around 50 kilobits per second, depending on the technology and configuration. You are not streaming video. You are not browsing the web. You are sending a temperature reading, a GPS coordinate, a soil moisture value, a short text message. And that turns out to be exactly what a huge number of applications need.
Several LPWAN technologies compete for adoption, each with different trade-offs:
LoRa / LoRaWAN uses a proprietary modulation technique called Chirp Spread Spectrum (CSS) operating in unlicensed ISM bands (868 MHz in Europe, 915 MHz in the US, 923 MHz in Asia). LoRa refers to the physical layer modulation; LoRaWAN is the MAC and network protocol built on top of it. LoRa’s greatest strengths are its operation in unlicensed spectrum (no fees, no subscription, no permission needed), its open ecosystem, and the existence of community networks like The Things Network. Hardware is cheap — a complete LoRa node can be built for under $15 — and the technology can be used with or without LoRaWAN, including in raw peer-to-peer or mesh configurations. This is the technology we will focus on in this chapter.
Sigfox is a French company that operates a proprietary LPWAN using ultra-narrowband (UNB) modulation. Sigfox operates its own network infrastructure — you buy a Sigfox-compatible module, and your data is carried on Sigfox’s network to Sigfox’s cloud, from which you access it via Sigfox’s API. The technology is efficient (devices can run for years on a coin cell) and the range is excellent, but the ecosystem is completely closed. You are renting capacity on someone else’s network, subject to their pricing, their terms, and their continued existence as a company. Sigfox went through bankruptcy proceedings in 2022 and was acquired by UnaBiz, casting a long shadow over its long-term reliability. For alternative networks, Sigfox is a cautionary tale about depending on proprietary infrastructure.
NB-IoT (Narrowband Internet of Things) is a cellular LPWAN standard developed by 3GPP — the same body that standardizes LTE and 5G. NB-IoT operates in licensed cellular spectrum, which means it is deployed by mobile operators and requires a SIM card and a subscription. The advantage is excellent coverage in areas where cellular infrastructure already exists, guaranteed quality of service, and relatively high data rates (up to about 250 kbps). The disadvantage is that you are dependent on a cellular operator, you pay monthly fees, and coverage in truly rural or off-grid areas may not exist. NB-IoT is a corporate IoT solution, not an alternative network technology.
LTE-M (LTE for Machines) is another 3GPP cellular LPWAN standard, positioned as a higher-bandwidth alternative to NB-IoT. LTE-M supports data rates up to about 1 Mbps and, critically, supports voice and mobility — making it suitable for asset tracking and wearable devices. Like NB-IoT, it requires cellular infrastructure and a subscription. It is even further from the alternative network philosophy than NB-IoT.
Mioty is a newer LPWAN technology using a patented modulation called Telegram Splitting Multiple Access (TSMA), which splits each message into many small sub-packets transmitted on different frequencies. This provides exceptional robustness against interference but requires specialized hardware. Adoption is still limited.
The comparison table makes the choice clear for alternative networks:
| Technology | Spectrum | Infrastructure | Cost Model | Openness | DIY Friendly |
|---|---|---|---|---|---|
| LoRa | Unlicensed | Self-deployed | Hardware only | Open | Excellent |
| Sigfox | Unlicensed | Operator network | Subscription | Closed | Poor |
| NB-IoT | Licensed | Cellular towers | SIM + plan | Standard | Poor |
| LTE-M | Licensed | Cellular towers | SIM + plan | Standard | Poor |
| Mioty | Unlicensed | Self-deployed | Hardware only | Limited | Limited |
LoRa is the only LPWAN technology that is simultaneously unlicensed, self-deployable, cheap, and supported by a vast open-source ecosystem. It is the LPWAN of the people, and it is what this chapter is really about.
The magic of LoRa is in its modulation technique: Chirp Spread Spectrum (CSS). To understand why this matters, you need to understand the fundamental challenge of long-range radio communication.
A radio signal weakens as it travels — roughly following the inverse square law, where received power decreases proportionally to the square of the distance. Double the distance, and you receive one-quarter the power. At long ranges, the signal becomes so weak that it disappears into the noise floor — the background electromagnetic noise from other radios, electronics, cosmic radiation, and thermal agitation in the receiver’s own circuitry. The question is not just “can the signal reach?” but “can the signal be distinguished from noise when it arrives?”
Traditional modulation techniques — the kind used in Wi-Fi and Bluetooth — encode data into short, precise bursts of particular frequencies. These work beautifully at short range where the signal-to-noise ratio (SNR) is high, but they fall apart when the signal drops near or below the noise floor. The receiver simply cannot tell the difference between signal and noise.
Chirp Spread Spectrum takes a radically different approach. Instead of encoding data as specific frequencies, CSS encodes data as chirps — signals that sweep continuously across a wide frequency band, from low to high (an up-chirp) or from high to low (a down-chirp). Each chirp occupies the entire bandwidth for an extended period of time.
The genius of this approach is that a chirp has a very distinctive mathematical signature. Even when a chirp signal is buried deep in noise — even when the signal power is below the noise floor — a receiver can detect it by correlating the incoming signal against the expected chirp pattern. The correlation process essentially “listens” for the characteristic frequency sweep across the entire bandwidth and the entire chirp duration, summing up the tiny contributions from each moment of the chirp. Noise, being random, does not correlate and averages out. The chirp signal, being structured, accumulates.
This is why LoRa can operate at signal-to-noise ratios as low as -20 dB — meaning the signal can be 100 times weaker than the noise and still be received. For comparison, Wi-Fi typically requires an SNR of at least +10 to +20 dB. This difference in receiver sensitivity is the fundamental reason LoRa can achieve ranges of 10+ km on milliwatts of transmit power.
LoRa’s implementation of CSS introduces a crucial tunable parameter: the Spreading Factor (SF). The spreading factor determines how long each chirp takes and, consequently, how many data bits each chirp encodes.
LoRa supports spreading factors from SF7 to SF12. At SF7, each chirp is relatively short (about 1 ms), the data rate is at its highest (roughly 5,470 bps at 125 kHz bandwidth), and the range is at its shortest. At SF12, each chirp is very long (about 32 ms), the data rate drops to roughly 250 bps, but the receiver can detect signals far below the noise floor, maximizing range.
Each step up in spreading factor doubles the chirp duration — SF8 chirps are twice as long as SF7, SF9 twice as long as SF8, and so on. This means SF12 chirps are 32 times longer than SF7 chirps. Longer chirps provide more gain through correlation, but they also take longer to transmit the same amount of data.
The practical implications:
| SF | Bit Rate (125 kHz BW) | Time on Air (10 bytes) | Relative Range | Receiver Sensitivity |
|---|---|---|---|---|
| SF7 | ~5,470 bps | ~36 ms | 1x (baseline) | -123 dBm |
| SF8 | ~3,125 bps | ~64 ms | ~1.2x | -126 dBm |
| SF9 | ~1,760 bps | ~113 ms | ~1.5x | -129 dBm |
| SF10 | ~980 bps | ~205 ms | ~1.8x | -132 dBm |
| SF11 | ~440 bps | ~413 ms | ~2.1x | -134.5 dBm |
| SF12 | ~250 bps | ~827 ms | ~2.5x | -137 dBm |
A critical and elegant property of LoRa is that different spreading factors are orthogonal — transmissions at different SFs do not interfere with each other, even on the same frequency at the same time. A receiver listening for SF10 will ignore SF7 transmissions and vice versa. This effectively multiplies the capacity of each frequency channel by the number of spreading factors in use.
LoRa supports three standard bandwidth settings: 125 kHz, 250 kHz, and 500 kHz. Wider bandwidth increases the data rate but decreases the receiver sensitivity (and therefore range). The 125 kHz bandwidth is the most common choice for LoRaWAN deployments because it provides the best range. The 500 kHz bandwidth is used in some US deployments where higher data rates are needed and the wider ISM band provides more spectrum.
The relationship is straightforward: doubling the bandwidth doubles the data rate but reduces sensitivity by approximately 3 dB, which translates to roughly 30% less range in practice.
LoRa operates in the ISM (Industrial, Scientific, and Medical) bands — portions of the radio spectrum that most countries have set aside for unlicensed use. The specific bands vary by region:
EU868 — Europe uses the 863-870 MHz band. LoRaWAN typically uses eight channels centered at 868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, and 867.9 MHz. The European regulations impose a 1% duty cycle limit on most sub-bands, meaning a device can only transmit for 1% of the time. This translates to about 36 seconds per hour — a strict limit that fundamentally shapes how European LoRa networks are designed.
US915 — The United States and much of the Americas use the 902-928 MHz band, which is significantly wider than the European allocation. This band supports 64 uplink channels (125 kHz) and 8 uplink channels (500 kHz), plus 8 downlink channels (500 kHz). There is no duty cycle limitation, but there is a maximum dwell time of 400 ms per channel for frequency-hopping systems. The wider band and relaxed duty cycle rules give US deployments significantly more capacity than European ones.
AS923 — Much of Asia uses channels around 923 MHz, with country-specific variations. Japan, for instance, uses the 920-928 MHz band with a maximum transmit power of 20 mW — significantly lower than the 25 mW (EU) or 1 W (US) limits in other regions.
AU915 — Australia uses a plan similar to US915, operating in the 915-928 MHz band.
IN865 — India uses the 865-867 MHz band with a maximum transmit power of 1 W.
These regional variations are not just regulatory trivia — they directly affect the hardware you buy, the firmware you flash, and the performance you can expect. A LoRa module configured for US915 is illegal to operate in Europe, and vice versa. Always verify which frequency plan applies in your country before purchasing or deploying hardware.
The link budget is the accounting of all gains and losses between a transmitter and a receiver. It determines whether a signal will be receivable at a given distance. The basic formula is:
\[P_{received} = P_{transmit} + G_{transmit} - L_{cable,tx} - L_{path} + G_{receive} - L_{cable,rx}\]Where:
Where $d$ is the distance in meters and $f$ is the frequency in Hz.
For a successful link, $P_{received}$ must exceed the receiver sensitivity. With LoRa at SF12 having a receiver sensitivity of -137 dBm and a typical transmit power of +14 dBm, the total link budget is approximately 151 dB. In free space, this corresponds to a theoretical range of over 700 km at 868 MHz. In practice, terrain, vegetation, buildings, and atmospheric conditions reduce this dramatically — but even with 30-40 dB of additional loss, ranges of 10-15 km are readily achievable.
import math
def lora_link_budget(tx_power_dbm=14, tx_gain_dbi=2.15,
rx_gain_dbi=2.15, rx_sensitivity_dbm=-137,
frequency_mhz=868, margin_db=10):
"""Calculate maximum theoretical range for a LoRa link."""
link_budget = (tx_power_dbm + tx_gain_dbi + rx_gain_dbi
- rx_sensitivity_dbm - margin_db)
freq_hz = frequency_mhz * 1e6
max_distance_m = 10 ** ((link_budget - 20 * math.log10(freq_hz)
+ 147.55) / 20)
return link_budget, max_distance_m / 1000 # km
budget, range_km = lora_link_budget()
print(f"Link budget: {budget:.1f} dB")
print(f"Max free-space range: {range_km:.1f} km")
LoRa is a physical layer — a way to modulate radio waves. By itself, it can send chirps between two devices with matching settings. But building a network requires much more: addressing, authentication, encryption, scheduling, acknowledgment, and the management of thousands of devices sharing the same airwaves. This is where LoRaWAN comes in.
LoRaWAN is an open standard maintained by the LoRa Alliance, defining the MAC (Medium Access Control) layer, the network architecture, and the security model for networks built on LoRa radio. It transforms raw LoRa links into a structured, scalable network that can support millions of devices.
A LoRaWAN network has four layers, arranged in a star-of-stars topology:
End Devices (also called nodes or motes) are the sensors and actuators at the edge of the network. A soil moisture sensor in a field, a water level detector in a well, a GPS tracker on livestock — these are end devices. They transmit small packets of data over LoRa and spend most of their time in deep sleep to conserve battery. End devices do not communicate with each other; they only communicate with gateways.
Gateways are the bridges between the LoRa radio world and the IP network world. A gateway is essentially a multi-channel LoRa receiver connected to the internet (via Ethernet, Wi-Fi, or cellular). It receives LoRa packets from any end device within range and forwards them to the network server over a standard IP connection. Crucially, a LoRaWAN gateway is not associated with specific end devices — it forwards all packets it can receive, from any device, to the network server. Multiple gateways may receive the same packet from the same device, providing spatial diversity and redundancy.
Network Server is the brain of the LoRaWAN network. It receives packets from all gateways, deduplicates them (since multiple gateways may have received the same packet), selects the best copy, manages device addressing and authentication, handles adaptive data rate optimization, and routes packets to the appropriate application server. In community networks like The Things Network, the network server is operated as shared infrastructure. For private networks, you can run your own network server using open-source software like ChirpStack.
Application Server is where your data ends up. It receives the decrypted payload from the network server and does whatever your application requires — store it in a database, display it on a dashboard, trigger an alert, send a command back to a device. The application server is entirely under your control.
The separation between network server and application server is not just architectural elegance — it is a security feature. The network server handles network-level encryption and routing but cannot read your application data. The application server holds the application encryption keys and can read the data but does not manage the network. This separation of concerns means that even the operator of a shared network like TTN cannot read your sensor data.
LoRaWAN defines three device classes that trade off between power consumption and downlink latency — how quickly the device can receive a message from the server:
Class A is the most energy-efficient and the default for battery-powered sensors. A Class A device transmits when it has data to send and then opens two short receive windows (RX1 and RX2) immediately after the transmission. Outside these windows, the device is in sleep mode and cannot receive data. The server can only send a downlink message during these receive windows, which means the server must wait until the device happens to transmit before it can send anything back. Downlink latency is unpredictable — it depends entirely on the device’s transmission schedule. But power consumption is minimal, making Class A ideal for battery-powered sensors that primarily send data and rarely need to receive commands.
Class B adds scheduled receive windows using synchronized beacons broadcast by the gateways. At regular intervals (typically every 128 seconds), the device wakes up and opens a receive window, giving the server a predictable opportunity to send downlinks. This provides deterministic latency at the cost of slightly higher power consumption (the device must wake up for every beacon period even if there is nothing to receive). Class B is useful for actuators that need to respond to commands within a known timeframe, such as a valve controller that should respond within a few minutes.
Class C keeps the receive window open continuously — the device is always listening except during its own transmissions. This provides the lowest downlink latency (essentially real-time) but the highest power consumption. Class C devices are typically mains-powered, such as street lights, industrial controllers, or gateway devices that act as relays.
For alternative network purposes, Class A is by far the most relevant. Battery-powered sensors and Meshtastic nodes all operate in patterns similar to Class A, minimizing power consumption to extend deployment lifetime.
Before a device can participate in a LoRaWAN network, it must be activated — a process that establishes the session keys used for encryption and the device’s network address. LoRaWAN supports two activation methods:
OTAA (Over-The-Air Activation) is the recommended method. The device is provisioned with three root values: a DevEUI (a globally unique device identifier, like a MAC address), an AppEUI (also called JoinEUI, identifying the application), and an AppKey (a secret AES-128 key). When the device first powers up, it sends a Join Request message. If the network server recognizes the device and validates the request, it sends back a Join Accept message containing session keys and a device address. The session keys are derived from the AppKey using data from both the Join Request and Join Accept, ensuring that even if someone intercepts the join exchange, they cannot derive the session keys without knowing the AppKey.
OTAA has significant advantages: session keys are unique per session and are rotated whenever the device rejoins, compromising one session does not compromise past or future sessions, and the device’s network address is assigned dynamically rather than hardcoded. The downside is that the device must be within range of a gateway and successfully complete the join handshake before it can send data.
ABP (Activation By Personalization) skips the join procedure entirely. The device is pre-provisioned with a fixed Device Address, a Network Session Key, and an Application Session Key. It can start transmitting immediately without any join handshake. The advantage is simplicity — no join procedure to fail, no need for gateway connectivity during activation. The disadvantages are severe: the session keys never change (unless manually reprogrammed), the device address is static (making the device trivially trackable), and if the keys are compromised, there is no automatic recovery. ABP is appropriate only for simple, low-security deployments or for testing.
LoRaWAN provides two independent layers of encryption:
Network-level encryption uses the Network Session Key (NwkSKey) to compute a Message Integrity Code (MIC) for every packet. The MIC ensures that packets have not been tampered with in transit and that they originate from a legitimate device. The network server uses the NwkSKey to validate packets.
Application-level encryption uses the Application Session Key (AppSKey) to encrypt the payload — the actual sensor data. This encryption is end-to-end between the device and the application server. The network server, the gateways, and anyone who intercepts the packets cannot read the payload.
Both layers use AES-128 encryption. The MIC protects integrity; the AppSKey protects confidentiality. Together, they provide a security model that is significantly stronger than most consumer IoT protocols, though not without its own weaknesses — replay protection depends on frame counters, and devices using ABP with no counter reset protection can be vulnerable to replay attacks after a power cycle.
Meshtastic is an open-source project that transforms inexpensive LoRa hardware into a decentralized mesh communication network. If LoRaWAN is the enterprise IoT protocol — structured, server-dependent, optimized for sensor data — Meshtastic is its wild, anarchic cousin: a peer-to-peer mesh network designed for human communication, requiring no internet, no infrastructure, and no subscription.
Meshtastic was created in 2020 by a developer frustrated that existing LoRa communication tools were either too complex, too expensive, or too limited. The project’s ethos is radically simple: buy a cheap LoRa board, flash the Meshtastic firmware, pair it with your phone via Bluetooth, and you have a long-range text messaging device that works anywhere on Earth. No cell towers. No Wi-Fi. No internet. Just radio waves and a mesh network that forms automatically between any Meshtastic devices within range.
Meshtastic uses LoRa in raw mode — it does not use the LoRaWAN protocol at all. Instead, it implements its own mesh networking protocol optimized for small groups of users communicating over text.
When you send a message on Meshtastic, your device broadcasts it over LoRa. Every other Meshtastic device within radio range receives the message, and — if the message is not addressed directly to them or if mesh relaying is enabled — they rebroadcast it. This store-and-forward mesh means your message can hop across multiple devices, reaching recipients who are far beyond the radio range of your own device. With several nodes spread across a valley, a message sent from one end can reach the other end through a chain of relays, with each hop potentially covering several kilometers.
The protocol includes flood routing with duplicate suppression — each message has a unique ID, and nodes track which message IDs they have already relayed to avoid infinite rebroadcast loops. There is a configurable hop limit (default is 3) that prevents messages from circulating indefinitely. Position data is shared automatically, so each node knows (approximately) where other nodes are located, enabling map-based awareness of your mesh network.
Meshtastic supports several message types:
Meshtastic supports a range of inexpensive LoRa development boards, all based on the ESP32 or nRF52 microcontrollers combined with Semtech SX1262 or SX1276/SX1278 LoRa radio chips:
LILYGO T-Beam — The classic Meshtastic device. Combines an ESP32, an SX1262/SX1276 LoRa radio, a GPS module, a 18650 battery holder, and a charge controller on a single board. Costs around $25-35. The T-Beam Supreme adds a better GPS, improved power management, and a BME280 environmental sensor. Its built-in GPS makes it ideal for position tracking and mapping.
Heltec LoRa 32 — A compact board with an ESP32, SX1262/SX1276, and a small OLED display. Cheaper than the T-Beam (around $15-20) but lacks built-in GPS. Good for stationary nodes or where you want a small form factor. The V3 variant uses the more efficient SX1262 radio.
RAK WisBlock — A modular system from RAKwireless based on the nRF52840 microcontroller. The nRF52 platform offers significantly better power efficiency than ESP32, making RAK boards the best choice for battery-powered deployments where you need maximum runtime. The modular design lets you snap together a base board, a LoRa radio module, a GPS module, and various sensor modules. More expensive than the basic ESP32 boards ($30-50 for a complete setup) but worth it for long-term deployments.
LILYGO T-Echo — An nRF52-based board with an e-ink display, GPS, and SX1262 radio. The e-ink display consumes zero power when not updating, making it extremely efficient for a wearable or dashboard-style device.
Station G2 — A more powerful device designed for fixed installations, with improved RF performance, a better antenna connector (N-type), and a weatherproof enclosure option. Designed as a high-performance relay node.
Setting up a Meshtastic device is straightforward:
Flash the firmware. Download the Meshtastic firmware from the project’s website. For ESP32 boards, the web-based flasher at flasher.meshtastic.org lets you flash directly from a browser via USB — no programming tools required. For nRF52 boards, you drag-and-drop the UF2 firmware file.
Install the app. Meshtastic has companion apps for Android (Google Play), iOS (App Store), and desktop (Python CLI or web interface). The phone app connects to your Meshtastic device via Bluetooth (or Wi-Fi on ESP32 boards) and provides the user interface for messaging, settings, and map display.
Configure the region. This is critical. You must set the correct frequency region for your country (EU_868, US, ANZ, etc.) before transmitting. Transmitting on the wrong frequencies can violate radio regulations and interfere with other services.
Set a channel. Meshtastic uses channels to create groups. The default channel uses a well-known encryption key (so anyone with a Meshtastic device can receive default-channel messages), but you can create private channels with custom encryption keys for secure group communication.
Set your name. Give your node a human-readable name so others can identify you on the mesh.
# Meshtastic Python CLI — basic device configuration
# Install: pip install meshtastic
import meshtastic
import meshtastic.serial_interface
interface = meshtastic.serial_interface.SerialInterface()
node = interface.getNode("^local")
# Set region (CRITICAL — do this first)
node.setOwner("MyNode")
node.setRegion("EU_868")
# Configure LoRa parameters
prefs = node.localConfig
prefs.lora.region = 3 # EU_868
prefs.lora.hop_limit = 3
prefs.lora.tx_power = 14 # dBm
node.writeConfig("lora")
interface.close()
Meshtastic channels deserve special attention because they determine who can read your messages. Each channel has:
The default channel uses a PSK of 1 (a well-known value), which means all Meshtastic devices on the default channel can read each other’s messages. This is intentional — it allows open community communication — but for private groups, you should generate a random PSK.
You can share channel configurations via QR codes or URLs, making it easy to invite people to your private channel without manually entering long encryption keys.
Real-world Meshtastic performance depends heavily on terrain, antenna quality, and spreading factor:
The default Meshtastic preset (“Long Fast” on most regions) uses SF11 with 250 kHz bandwidth, providing a good balance of range and throughput. For maximum range, the “Very Long Slow” preset uses SF12 with 125 kHz bandwidth but limits message size and significantly increases transmission time.
Meshtastic is arguably the single most accessible tool for off-grid alternative communication:
Building your own LoRa sensor network — outside the Meshtastic or LoRaWAN frameworks — gives you maximum flexibility and teaches you how the technology actually works at the radio level. The essential hardware:
ESP32 + SX1276/SX1278 module — The combination of an ESP32 microcontroller (with built-in Wi-Fi and Bluetooth) and a Semtech SX1276 (for 868 MHz) or SX1278 (for 433 MHz) LoRa radio is the workhorse of DIY LoRa projects. The Heltec WiFi LoRa 32 and LILYGO TTGO boards integrate both onto a single PCB. Cost: $10-20.
Raspberry Pi + LoRa HAT — For the receiving/gateway side, a Raspberry Pi with a LoRa HAT (Hardware Attached on Top) gives you a full Linux environment for receiving, logging, and processing sensor data. The RAK2245 Pi HAT or Dragino LoRa GPS HAT are popular choices. A single-channel receiver based on an SX1276 module wired to a Pi’s GPIO also works for simple setups.
Sensors — Whatever you want to measure. Common choices: BME280 (temperature, humidity, pressure), SHT31 (temperature, humidity), soil moisture sensors, water level sensors, rain gauges, anemometers, UV sensors, air quality sensors (MQ series or PMS5003).
Antennas — The antenna is arguably the most important component for range. The short whip antennas that come with development boards are functional but mediocre. A half-wave dipole or a quarter-wave ground plane antenna cut to the correct length for your frequency band will dramatically improve performance. For 868 MHz, a half-wave dipole is about 17.3 cm. For 915 MHz, about 16.4 cm. For fixed installations, a collinear antenna or a Yagi can add 3-9 dBi of gain, doubling or tripling your effective range.
Here is a minimal MicroPython example for an ESP32 with an SX1276 module, reading a BME280 temperature/humidity sensor and transmitting the data over LoRa:
# sensor_node.py — MicroPython LoRa sensor transmitter
from machine import Pin, SPI, I2C
from sx1276 import SX1276
from bme280 import BME280
import struct, time
# Initialize LoRa radio (SPI connection to SX1276)
spi = SPI(1, baudrate=10000000, polarity=0, phase=0,
sck=Pin(5), mosi=Pin(27), miso=Pin(19))
lora = SX1276(spi, cs=Pin(18), reset=Pin(14),
frequency=868000000, sf=10, bw=125000)
# Initialize BME280 sensor (I2C)
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
sensor = BME280(i2c=i2c)
NODE_ID = 1
while True:
temp, hum, pres = sensor.read_compensated_data()
payload = struct.pack(">BffH", NODE_ID,
temp / 100, hum / 1024, int(pres / 256))
lora.send(payload)
print(f"Sent: T={temp/100:.1f}°C H={hum/1024:.1f}% P={pres/25600:.0f}hPa")
time.sleep(300) # Send every 5 minutes
On the receiving end, a Raspberry Pi with a LoRa module runs a Python script that listens for incoming packets, decodes them, and logs the data:
# receiver.py — Raspberry Pi LoRa receiver and logger
import struct, csv, time
from datetime import datetime
from SX127x.LoRa import LoRa
from SX127x.board_config import BOARD
BOARD.setup()
class LoRaReceiver(LoRa):
def on_rx_done(self):
payload = bytes(self.read_payload(nocheck=True))
rssi = self.get_pkt_rssi_value()
snr = self.get_pkt_snr_value()
if len(payload) >= 11:
node_id, temp, hum, pres = struct.unpack(">BffH", payload[:11])
row = [datetime.now().isoformat(), node_id,
f"{temp:.1f}", f"{hum:.1f}", pres, rssi, snr]
with open("sensor_log.csv", "a") as f:
csv.writer(f).writerow(row)
print(f"Node {node_id}: {temp:.1f}°C {hum:.1f}% "
f"{pres}hPa RSSI:{rssi} SNR:{snr}")
self.reset_ptr_rx()
self.set_mode(0x85) # Back to RX continuous
This gives you a complete pipeline: sensor reads data → LoRa transmits → receiver logs to CSV. From there, you can feed the CSV into any visualization or alerting system you like — Grafana, a simple web page, or even a script that sends you a Meshtastic message if a temperature exceeds a threshold.
While LPWAN technologies were designed primarily for IoT — machines talking to machines — the off-grid and alternative network communities quickly recognized that LoRa’s extreme range and low power made it valuable for human communication, too. Not for voice calls or video (the bandwidth is far too low), but for the kind of communication that matters most when infrastructure fails: short text messages, location sharing, and emergency alerts.
Meshtastic (discussed above) is the dominant solution for LoRa-based text messaging, but it is not the only approach. Reticulum is a networking stack designed specifically for long-range, low-bandwidth communication. It provides a complete networking layer — addressing, routing, encryption, and transport — that can run over LoRa (as well as TCP/IP, serial links, and other transports). Reticulum’s companion application Sideband provides a messaging interface similar to Meshtastic but built on a more sophisticated network protocol that supports true end-to-end encryption, asymmetric key exchange, and multi-hop routing without the limitations of Meshtastic’s simpler flood routing.
For DIY text messaging without Meshtastic or Reticulum, you can build a minimal system with two LoRa nodes and a simple serial protocol:
# simple_chat.py — Minimal LoRa text chat (MicroPython)
from machine import Pin, SPI
from sx1276 import SX1276
import sys
spi = SPI(1, baudrate=10000000, sck=Pin(5),
mosi=Pin(27), miso=Pin(19))
lora = SX1276(spi, cs=Pin(18), reset=Pin(14),
frequency=868000000, sf=10, bw=125000)
while True:
# Check for incoming message
if lora.received():
msg = lora.read_payload().decode("utf-8", "ignore")
print(f"\n[RECV] {msg}")
# Check for user input (non-blocking)
if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
text = input()
lora.send(text.encode("utf-8")[:200])
print(f"[SENT] {text}")
LoRa is excellent for asset tracking and personnel tracking in off-grid environments. A GPS module paired with a LoRa transmitter can broadcast position updates at intervals of a few seconds to a few minutes, providing real-time location awareness across a wide area.
Practical applications abound. Farmers tracking livestock across open range. Search-and-rescue teams maintaining awareness of team positions across mountainous terrain. Parents tracking children at outdoor events. Sailors monitoring the positions of boats in a fleet. In all these cases, the combination of long range, low power, and no infrastructure dependency makes LoRa the ideal transport.
Meshtastic includes GPS tracking natively — every node with a GPS module automatically shares its position. For custom solutions, the payload is just a few bytes:
# gps_tracker.py — LoRa GPS tracker (MicroPython)
from machine import Pin, SPI, UART
from sx1276 import SX1276
from micropyGPS import MicropyGPS
import struct, time
spi = SPI(1, baudrate=10000000, sck=Pin(5),
mosi=Pin(27), miso=Pin(19))
lora = SX1276(spi, cs=Pin(18), reset=Pin(14),
frequency=868000000, sf=10, bw=125000)
gps_uart = UART(2, baudrate=9600, tx=17, rx=16)
gps = MicropyGPS()
while True:
while gps_uart.any():
gps.update(chr(gps_uart.read(1)[0]))
if gps.fix_type >= 2:
payload = struct.pack(">ff", gps.latitude[0], gps.longitude[0])
lora.send(payload)
time.sleep(30)
A LoRa-connected weather station is perhaps the quintessential off-grid sensor application. A solar-powered station in a field, on a mountaintop, or by a river can transmit temperature, humidity, pressure, wind speed, rainfall, and UV index data to a base station kilometers away, running autonomously for years.
The key design considerations:
For farms and homesteads, LoRa enables distributed monitoring that would be impractical with any other technology. Soil moisture sensors at multiple points across a field, water level sensors in tanks and ponds, temperature sensors in greenhouses, frost alerts, rain gauges — all feeding data back to a central display or alert system.
The economics are compelling. A commercial agricultural monitoring system costs thousands of dollars and typically requires a cellular subscription. A DIY LoRa system covering the same area can be built for under $200 in total hardware costs, with no ongoing fees.
A LoRa emergency beacon is a simple but potentially life-saving device: a button that, when pressed, transmits a GPS position and a distress code over LoRa. Any Meshtastic node or custom receiver within range picks up the signal and can relay it further. Unlike commercial PLBs (Personal Locator Beacons) that depend on satellite infrastructure, a LoRa beacon works within the range of your own network — a perfect complement to a community Meshtastic deployment.
The Things Network (TTN) is a global, community-built LoRaWAN network. The concept is beautifully simple: anyone can deploy a LoRaWAN gateway and connect it to TTN’s shared network server. Once connected, that gateway provides coverage for any TTN device in range — not just the gateway owner’s devices. The result is a growing patchwork of community-provided coverage, free to use, requiring no subscription.
As of 2026, TTN has over 25,000 gateways deployed worldwide, with dense coverage in the Netherlands (where the project originated), Germany, the UK, and growing coverage across much of Europe, the Americas, Asia, and Australia. Some cities have near-complete coverage entirely from community-deployed gateways.
TTN operates on the V3 stack (also known as The Things Stack Community Edition), which provides:
The fair use policy is important — TTN is a shared resource, and devices that transmit excessively consume airtime that could be used by others. For applications that need more capacity, The Things Industries offers commercial plans.
Helium took a different approach to building a community LoRaWAN network: cryptocurrency incentives. Gateway operators were rewarded with HNT tokens for providing coverage, with proof-of-coverage mechanisms designed to verify that gateways were actually operational and located where they claimed to be.
Helium’s network grew explosively — at its peak, over 900,000 hotspots were deployed worldwide, making it one of the largest LoRaWAN networks in existence. However, the project has been controversial. Many gateway operators found that mining rewards did not cover the cost of equipment and electricity. The proof-of-coverage mechanism was plagued by gaming and spoofing. In 2023, Helium migrated from its own blockchain to the Solana blockchain and began pivoting toward cellular (5G) coverage.
For alternative network builders, Helium is a cautionary lesson: building infrastructure on cryptocurrency incentives can drive rapid deployment but also attracts speculators rather than genuine network builders, and the economic sustainability depends on token prices that the participants cannot control. TTN’s volunteer model is slower but more sustainable.
If TTN coverage does not exist in your area, you can create it by deploying your own gateway. The key components:
Hardware options:
Placement considerations:
# ttn_uplink_handler.py — TTN MQTT integration example
import paho.mqtt.client as mqtt
import json, base64
TTN_BROKER = "eu1.cloud.thethings.network" # or your region
APP_ID = "your-app-id"
API_KEY = "your-api-key"
def on_message(client, userdata, msg):
data = json.loads(msg.payload)
dev_id = data["end_device_ids"]["device_id"]
payload_raw = data["uplink_message"]["frm_payload"]
payload = base64.b64decode(payload_raw)
rssi = data["uplink_message"]["rx_metadata"][0]["rssi"]
print(f"Device: {dev_id}, Payload: {payload.hex()}, RSSI: {rssi}")
client = mqtt.Client()
client.username_pw_set(f"{APP_ID}@ttn", API_KEY)
client.tls_set()
client.on_message = on_message
client.connect(TTN_BROKER, 8883)
client.subscribe(f"v3/{APP_ID}@ttn/devices/+/up")
client.loop_forever()
Once you have a gateway deployed, you want to know how far it reaches. TTN Mapper is a community tool that crowd-sources coverage data — you carry a TTN device while walking or driving, and it logs GPS positions along with signal quality. The results are displayed on a map, showing exactly where your gateway provides usable coverage.
For Meshtastic, similar mapping can be done using the built-in position reporting — walk around with a Meshtastic node while another node at the base station records which messages it receives and at what signal quality.
Coverage mapping is not just satisfying — it is practical. It identifies dead zones where additional gateways or relay nodes are needed, verifies that antenna installations are performing as expected, and provides documentation for community network planning.
In a LoRaWAN network, devices do not have to use a fixed spreading factor. Adaptive Data Rate (ADR) is a mechanism by which the network server analyzes the signal quality of each device’s transmissions and instructs the device to adjust its spreading factor and transmit power. A device that the gateway is receiving with a strong signal can be told to use a lower SF (higher data rate, shorter airtime) and lower transmit power, freeing up airtime for other devices. A device at the edge of coverage can be told to use a higher SF to ensure reliable communication.
ADR is a powerful optimization for dense LoRaWAN deployments. It maximizes network capacity by ensuring that no device uses more airtime than necessary. However, ADR requires bidirectional communication (the server must be able to send commands to the device), which means it only works with Class A devices that transmit frequently enough to receive downlinks. For mobile devices with constantly changing link quality, ADR can be counterproductive — the network server’s most recent signal quality measurement may not reflect the device’s current position.
In European ISM bands, the 1% duty cycle limitation is not a guideline — it is a legal requirement. A device transmitting at SF12 with a 51-byte payload occupies the channel for about 1.8 seconds. At a 1% duty cycle, the device must wait at least 180 seconds before transmitting again on the same sub-band.
This limitation has profound implications for network design:
In the US (FCC Part 15 rules), there is no duty cycle limit, but there are restrictions on maximum transmit power (1 W for frequency-hopping systems) and dwell time (400 ms maximum per channel).
# duty_cycle.py — Calculate LoRa airtime and duty cycle budget
def lora_airtime_ms(payload_bytes, sf=10, bw_khz=125, cr=1,
preamble=8, explicit_header=True, crc=True):
"""Calculate time on air for a LoRa packet in milliseconds."""
t_sym = (2 ** sf) / (bw_khz * 1000) * 1000 # ms
t_preamble = (preamble + 4.25) * t_sym
de = 1 if (sf >= 11 and bw_khz == 125) else 0
h = 0 if explicit_header else 1
import math
payload_symbols = 8 + max(
math.ceil((8 * payload_bytes - 4 * sf + 28 + 16 * crc
- 20 * h) / (4 * (sf - 2 * de))) * (cr + 4), 0)
t_payload = payload_symbols * t_sym
return t_preamble + t_payload
airtime = lora_airtime_ms(20, sf=10)
msgs_per_hour = int(36000 / airtime) # 1% of 3600s = 36s
print(f"Airtime: {airtime:.1f} ms")
print(f"Max messages/hour (1% duty): {msgs_per_hour}")
LoRa’s CSS modulation provides inherent resilience against narrowband interference — a chirp sweeps across the entire bandwidth, so a narrow interferer only affects a small portion of each chirp. However, LoRa is not immune to interference, particularly from:
Practical interference management strategies:
LoRaWAN is a full network protocol with significant overhead: join procedures, frame counters, MAC commands, adaptive data rate negotiation, class-specific receive windows. This overhead exists for good reasons in large-scale deployments, but it is unnecessary — and even counterproductive — in many alternative network scenarios.
Use raw LoRa (without LoRaWAN) when:
Use LoRaWAN when:
For most readers of this book — people building small-scale, off-grid, alternative networks — raw LoRa or Meshtastic will be more practical than LoRaWAN. LoRaWAN becomes valuable when you want to connect your local network to a wider community infrastructure.
LoRa operates in unlicensed ISM bands, which means you do not need a license to transmit — but “unlicensed” does not mean “unregulated.” Every country imposes regulations on ISM band usage, and violating them can result in fines or equipment seizure.
Key regulations to understand:
Maximum transmit power. In the EU, the limit is typically 25 mW (14 dBm) ERP on most 868 MHz sub-bands. In the US, the limit is 1 W (30 dBm) conducted power. Higher power is not always better — it increases interference with other users and may violate regulations.
Duty cycle (EU). As discussed, most EU sub-bands have a 1% duty cycle limit. Some sub-bands (like 869.4-869.65 MHz) allow 10% duty cycle, which is valuable for applications needing more airtime.
Antenna restrictions. Some jurisdictions limit antenna gain or effective radiated power. A high-gain antenna combined with maximum transmit power may exceed legal limits.
Indoor/outdoor restrictions. Some frequency allocations distinguish between indoor and outdoor use.
Data content restrictions. In some countries, ISM band devices are restricted to specific types of data (telemetry, sensor data) and may not be used for general communication. The legal status of LoRa-based text messaging is ambiguous in some jurisdictions.
Always consult your national spectrum authority’s regulations. In the EU, this is typically the national telecom regulator (ARCEP in France, BNetzA in Germany, Ofcom in the UK). In the US, consult the FCC Part 15 rules. In Australia, the ACMA.
Let’s bring everything together with a complete, buildable project: a solar-powered LoRa weather station that transmits temperature, humidity, and barometric pressure readings to a Raspberry Pi base station, which logs the data to a CSV file and serves a simple web dashboard.
This project uses raw LoRa (not LoRaWAN or Meshtastic) for simplicity and to demonstrate the fundamentals of LoRa communication without protocol overhead.
Sensor Node: | Component | Example Part | Approximate Cost | |———–|————-|—————–| | ESP32 + LoRa board | Heltec WiFi LoRa 32 V3 | $18 | | BME280 sensor module | GY-BME280 breakout board | $4 | | 6V solar panel | 6V 1W mini solar panel | $5 | | LiPo battery | 3.7V 1000mAh | $5 | | TP4056 charge module | TP4056 with protection | $1 | | Weatherproof enclosure | ABS junction box, 100x68x50mm | $4 | | Antenna | 868/915 MHz SMA whip antenna | $3 | | Jumper wires and connectors | Assorted | $2 | | Total | | ~$42 |
Base Station: | Component | Example Part | Approximate Cost | |———–|————-|—————–| | Raspberry Pi | Pi 4 or Pi 3B+ (any model with GPIO) | $35-55 | | LoRa HAT or module | Dragino LoRa GPS HAT or SX1276 + wiring | $15-30 | | SD card | 32GB microSD | $8 | | Power supply | 5V 3A USB-C | $8 | | Antenna | 868/915 MHz SMA whip antenna | $3 | | Total | | ~$69-104 |
Total project cost: approximately $111-146 — a fraction of the cost of a single commercial weather station with remote data logging.
Sensor node (Heltec WiFi LoRa 32 V3 + BME280):
The Heltec board has the LoRa radio built in, so no LoRa wiring is needed. Connect the BME280:
For solar power, connect the solar panel through the TP4056 charge module to the LiPo battery, and connect the battery to the Heltec board’s battery connector (JST PH 2.0).
Base station (Raspberry Pi + SX1276 module):
If using a Dragino HAT, simply mount it on the Pi’s GPIO header. If using a bare SX1276 module:
# weather_station_node.py — Solar-powered LoRa weather station
from machine import Pin, SPI, I2C, deepsleep
from sx1276 import SX1276
from bme280 import BME280
import struct, time, esp32
# Configuration
NODE_ID = 0x01
FREQUENCY = 868000000 # Hz — change for your region
SF = 10
TX_INTERVAL_MIN = 10 # minutes between transmissions
# Initialize hardware
spi = SPI(1, baudrate=10000000, polarity=0, phase=0,
sck=Pin(5), mosi=Pin(27), miso=Pin(19))
lora = SX1276(spi, cs=Pin(18), reset=Pin(14),
frequency=FREQUENCY, sf=SF, bw=125000)
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
sensor = BME280(i2c=i2c)
# Read sensor and transmit
temp, hum, pres = sensor.read_compensated_data()
bat_mv = esp32.raw_temperature() # placeholder for ADC read
payload = struct.pack(">BhHH", NODE_ID,
int(temp), int(hum / 10), int(pres / 100))
lora.send(payload)
lora.sleep()
# Deep sleep until next transmission
deepsleep(TX_INTERVAL_MIN * 60 * 1000)
# weather_station_receiver.py — LoRa receiver + CSV logger
import struct, csv, os, time
from datetime import datetime
from SX127x.LoRa import LoRa
from SX127x.board_config import BOARD
BOARD.setup()
LOG_FILE = "weather_data.csv"
if not os.path.exists(LOG_FILE):
with open(LOG_FILE, "w", newline="") as f:
csv.writer(f).writerow(["timestamp", "node_id",
"temp_c", "humidity_pct", "pressure_hpa", "rssi", "snr"])
class WeatherReceiver(LoRa):
def __init__(self):
super().__init__(verbose=False)
self.set_mode(0x01) # Standby
self.set_freq(868.0)
self.set_spreading_factor(10)
self.set_bw(7) # 125 kHz
self.set_rx_crc(True)
self.set_mode(0x85) # RX continuous
print("Receiver ready. Waiting for data...")
def on_rx_done(self):
payload = bytes(self.read_payload(nocheck=True))
rssi = self.get_pkt_rssi_value()
snr = self.get_pkt_snr_value()
if len(payload) >= 7:
node_id, temp, hum, pres = struct.unpack(">BhHH", payload[:7])
row = [datetime.now().isoformat(), node_id,
temp / 100, hum / 10, pres, rssi, snr]
with open(LOG_FILE, "a", newline="") as f:
csv.writer(f).writerow(row)
print(f"[{row[0]}] Node {node_id}: {temp/100:.1f}°C "
f"{hum/10:.1f}% {pres}hPa | RSSI:{rssi} SNR:{snr}")
self.reset_ptr_rx()
self.set_mode(0x85)
receiver = WeatherReceiver()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
BOARD.teardown()
Once you have the basic weather station working, natural extensions include:
LoRa and LPWAN technologies occupy a unique and increasingly important position in the alternative networking landscape. They do not compete with Wi-Fi, cellular, or mesh networks on bandwidth — they compete on reach, power efficiency, and independence from infrastructure. A LoRa signal that travels 15 km on a coin cell battery, carrying a 20-byte sensor reading, is doing something that no other technology available to individuals can do at the same cost and simplicity.
The ecosystem is remarkably accessible. For under $20, you can buy a Meshtastic-capable device and join a decentralized mesh communication network that works without internet, without cell towers, and without anyone’s permission. For under $150, you can build a complete weather monitoring system with a solar-powered sensor node and a Raspberry Pi base station. For under $200, you can deploy a LoRaWAN gateway that provides coverage for an entire community.
The key concepts to carry forward:
In the next chapter, we will explore how communities have scaled alternative networks beyond individual deployments — building wireless ISPs, community networks, and shared infrastructure that serves hundreds or thousands of users.
| ← Previous: Ad-Hoc and Peer-to-Peer Networks | Table of Contents | Next: Community Networks and Wireless ISPs → |