Long range networking with LoRa: an overview

Embedded software engineer
Long range networking with LoRa: an overview
Welcome to the age of communication. It's 2021 and technology has come a long way. People, large machines and small devices communicate more intensively than ever before, and many technologies to enable them to do so have been developed. Some of those technologies use physical pathways like fibreglass to reach their receivers, others use radio signals to send messages. It's these wireless communication technologies that spark the imagination the most.

There's a multitude of wireless comminication protocols available: WiFi, Bluetooth, LTE, ZigBee, you name it. All of them have their strengths and weaknesses. Some are nice for smartphones to stream videos. Some range very, very far. Others use a very small amount of power.

One interesting communication protocol that has spiked our interest for its versatility and battery-friendliness is the low-power long-range LoRaWAN protocol. LoRaWAN is a protocol connecting low-power devices to internet services, defined by the LoRa Alliance. LoRaWAN uses Semtech's proprietary LoRa technology. Essentially, LoRaWAN is a message protocol that is stacked upon LoRa: LoRaWAN uses LoRa radio technology to send its messages.

In this post we will dive into LoRa. Not only will we find out about how it works, but we'll look into a simple software project to gain an intuiton on how to use it in an embedded device.


LoRa's strength lies in its low power usage and its very long range. Semtech claims on its website that its signals range up to as far as 30 miles, which is about 48 kilometers, and that battery lifetimes of up to 10 years lie within LoRa's possibilities. This makes LoRa an interesting option for small outdoor devices like location trackers.

To use LoRa in an end device, one needs to incorporate one of Semtech's LoRa modems. There are lots of modules available to ease integration of these modems. Each of these modules either incorporate a modem manufacutred by Semtech, or one licensed by Semtech. This is an important factor to consider when choosing between wireless technologies.

LoRa operates in the license-free RF bands. In the EU, that's the 868MHz band. For the United States, this band is around 915MHz. These bands are used for many other applications that might interfere with LoRa. In the EU, the regulations do not allow for large duty cycles or high-power output. Therefore, to enable the long range, LoRa uses a couple of techniques to make its signal stand out to the noise.

One of the tricks is the use of a very narrow bandwidth. By listening on only a small portion of the spectrum, a lot of the background noise is filtered out. Any noise not being listened to, is noise that cannot interfere with the signal. Therefore, using a narrow bandwidth, the listening device can be much more sensitive to incoming data.

LoRa uses forward error correction (FEC) in order to make the signal even more noise-resistent. Using FEC, corrupted bits of data can be recovered as they are encoded in a redundant manner. That way, a receiving modem can re-engineer the message if some parts of it are lost along the way. This is especially advantageous in circumstances where noise is present in bursts.

Another method used to increase signal range is the use of Chirp Spread Spectrum (CSS) modulation. This type of modulation uses all of the frequency band. CSS modulation shifts the signal frequency up (up-chirp) or down (down-chirp) over time while transmitting, resulting in characteristic 'chirp' sounds when listening to the demodulated signal. Without getting into too much detail, this type of modulation makes the signal very resistant to noise. A low-power CSS signal can be transmitted over a long distance.

This is what sending 'Hello, LoRa World!' looks like:

Pretty cool, right? You can probably imagine where the name 'Chirp Spread Spectrum' modulation comes from.

The SX126x LoRa modem family

As LoRa is a proprietary technology, only its owner Semtech and some licensed third parties have released LoRa modems. There are only a few types of modems available. The latest family of LoRa modems by Semtech is the SX1261/62/68 or SX126x family, which we'll take a closer look at.

The SX126x modems can operate in both Frequency Shift Keying (FSK) or LoRa modulation mode. In FSK mode, the modem transmits at distinct frequencies to send the 1's and 0's a message consists of. For example, a 0 might be represented by the signal frequency being at 868.5MHz, and a one at 867.5MHz. The signal can then be demodulated by measuring the frequency of every part of the incoming radio waves, and replacing the parts with the corresponding frequencies with either 0's or 1's. This modulation scheme is quite simple, but it is not as noise-resistant as LoRa modulation.

In LoRa mode, the main configuration parameters, apart from the RF frequency, are the bandwidth, the spreading factor, and the coding rate. Each of these parameters allow the user to make a trade-off between signal range and data throughput.

The RF bandwidth can be set as low as 7kHz for high sensitivity, or up to 500kHz for high throughput. The spreading factor determines how many chirps are sent per second. A higher spreading factor results in longer chirps, which increases the signal range, but decreases the data throughput. Lastly, the coding rate defines how many error correction bytes are sent along with the message. A higher coding rate results in more noise reduction, but as the amount of sent data is increased, the data throughput becomes lower.

Communication with the SX126x modems is done using SPI, a communication specification widely used in embedded systems. Apart from the usual SPI pins, the SX126x modems feature three IRQ lines which can be used to signal events to the host controller, as well as a BUSY line, which indicates that the modem is busy processing data.

The SX126x modems can be in one of several operating modes at a time. On boot, the modem goes into standby mode. In this mode, the modem's parameters can be configured by sending a number of the defined commands. In standby mode, the host controller can write a message payload into the internal buffer of the modem.

To send this payload, the modem is put into TX mode, using one of the commands. The BUSY line goes high, indicating that the modem is busy sending the message payload. When the modem is done sending the message, it goes back into standby mode. SX126x modems can be configured to signal the host controller that it is done sending using one of the IRQ lines.

The modem can be put into RX mode in order to receive data. In this mode, the modem waits until a message was received and can signal the host controller in this case. The received data will be written in the internal message buffer, and the host controller can read it using SPI.

Case: SX126x-rs, a driver in Rust

We have developed a bare-metal driver package using the Rust programming language, that simplifies writing applications that use the SX126x family of LoRa modems.

The idea is that the driver package handles all the configuration steps for you. You can just pass it a configuration object, and the driver will handle sending the correct commands to the modem for you. After that, the device can be put into TX or RX mode and data can easily be written to or read from the internal buffer.

We used an ST Nucleo-F103RB development board and an mbed SX1261MB2BAS LoRa shield in order to develop a working example. The Nucleo board contains an STM32F103RBT6 microcontroller, which is quite well supported by Rust. The package was written to be abstract enough to easily use it in applications for other host microcontrollers as well. The LoRa shield contains an SX1261 modem, which is designed for use within EU regulations. The SX1262 and SX1268 operate in the same way as the SX1261, apart from some minor details.

Here's a simplified example of how to use the package:

let lora_pins = ... // Configure the pins
let spi = ... // Initialize a SPI peripheral
let conf = build_config(); // Initialize the configuration

let mut lora = SX126x::new(lora_pins);
lora.init(&mut spi, delay, conf).unwrap();

 // Send a message
let res = lora.write_bytes(
    b"Hello from sx126x-rs!",
    0.into(), // TX timeout disabled,

For the complete example of how to use this package, take a look at ping-pong example in our SX126x-rs GitHub repository. This example illustrates how to configure a SX126x modem, in order to send and receive messages. The rest of the package code is available in that repository as well.

If you want to tinker around with the SX126x-rs package, I invite you to fork the project and port the ping-pong example to other host controllers. Or you could verify that it works for other modems from the SX126X family.

If you have questions or feedback contact me or go to r/rust

Want to learn more about LoRaWAN and what's so interesting about it? Stay tuned for my next blog post, which will feature Kloar, a demonstration project that uses affordable hardware to send messages over LoRaWAN

Stay up-to-date

Stay up-to-date with our work and blog posts?

Related articles

June 10, 2024

Tock binary size

Tock is a powerful and secure embedded operating system. While Tock was designed with resource constraints in mind, years of additional features, generalizing to more platforms, and security improvements have brought resource, and in particular, code size bloat.
January 12, 2023

Crash! And now what?

Imagine you've just deployed an embedded device in the world and of course, you have tested it thoroughly and it works. To monitor the device, you've set up some logging.

Last September, at the start of my internship at Tweede Golf, my tutors gave me a LoRa-E5 Dev Board. My task was to do something that would make it easier to write applications for this device in Rust. Here's what I did.