The Arduino LoRa library: long-range packets with an SX1278
Sandeep Mistry鈥檚 LoRa library drives Semtech鈥檚 SX1276, SX1277 and SX1278 radios, the chips on the Ra-02, RFM95W and RFM96W modules and on many ESP32 LoRa boards. It sends raw LoRa packets point to point, a few bytes to a couple of hundred, across hundreds of meters to kilometers, with no network or gateway in between (that is LoRaWAN, a different stack).
Built in on Mokxi: #include <LoRa.h> and it builds, with nothing to install. Free, and no account needed.
What LoRa does
The module is on SPI with three more pins: NSS (chip select), RESET and DIO0, the interrupt pin that signals a packet has arrived or finished sending. The library assumes pins 10, 9 and 2; call setPins() before begin() if yours differ. The radio is a 3.3 V part, so an Uno needs level shifting on its signals.
Two radios only hear each other when their settings agree: the frequency band (433E6, 868E6 or 915E6, which must be legal where you are), the spreading factor, the bandwidth and the sync word. Change one on the sender and not the receiver and nothing arrives, with no error on either side.
| Library Manager name | LoRa |
|---|---|
| Author | Sandeep Mistry |
| Include | #include <LoRa.h> |
| Boards | every board Mokxi compiles for but ATtiny85 |
| In the simulator | Simulated: it runs against the part the way it does on the bench. |
| Parts it drives | LoRa module, SX1278 (Ra-02) |
Install it
It builds on every board Mokxi compiles for but ATtiny85.
In Mokxi it is built in: #include <LoRa.h> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board, install "LoRa" by Sandeep Mistry from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add LoRa to lib_deps in PlatformIO. Mokxi follows the calls of release 0.8.0, so a sketch written here builds there too.
What to know in the simulator: Two modules hear each other when frequency, sync word, spreading factor and bandwidth match. RSSI and SNR are fixed numbers: there is no distance. Invert IQ is stored, not modeled.
ESP32-C3 路 Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 ESP32-C6 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Arduino Pro Mini 3.3 V 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi
The calls you will use
In the order a sketch meets them.
LoRa.setPins(10, 9, 2)
Names the NSS, RESET and DIO0 pins. Call it before begin().
LoRa.begin(433E6)
Resets the radio and starts it on 433 MHz. Returns 0 when the chip did not answer on SPI.
if (!LoRa.begin(433E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}LoRa.beginPacket()
Starts a packet. Fill it with LoRa.print() or LoRa.write(), then send it with endPacket().
LoRa.endPacket()
Sends the packet and waits until it has gone. endPacket(true) returns at once, with onTxDone() to hear when it finished.
int packetSize = LoRa.parsePacket()
Checks for a received packet and returns its size, 0 when none. Then read it with LoRa.available() and LoRa.read().
LoRa.packetRssi()
The signal strength of the last packet in dBm: about -30 close by, -120 near the edge of range. packetSnr() gives the signal to noise ratio.
LoRa.setSpreadingFactor(10)
Sets the spreading factor, 6 to 12. Higher reaches further and sends slower. Both radios must match.
LoRa.setSyncWord(0xF3)
Sets the sync word, a byte that keeps your network apart from others on the same frequency. Both sides must use the same one.
LoRa.onReceive(onReceive)
Calls your function from DIO0 when a packet arrives; start listening with LoRa.receive(). Keep the handler short.
Example: Send LoRa packets
On the Arduino Uno R3. It runs in the browser exactly as printed.
#include <SPI.h>
#include <LoRa.h>
int counter = 0;
void setup() {
Serial.begin(9600);
Serial.println("LoRa Sender");
LoRa.setPins(10, 9, 2); // NSS, RESET, DIO0
if (!LoRa.begin(433E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}
}
void loop() {
Serial.print("Sending packet: ");
Serial.println(counter);
LoRa.beginPacket();
LoRa.print("hello ");
LoRa.print(counter);
LoRa.endPacket();
counter++;
delay(200);
}Wiring
- Arduino Uno R3 13 to LoRa module, SX1278 (Ra-02) SCK
- Arduino Uno R3 11 to LoRa module, SX1278 (Ra-02) MOSI
- Arduino Uno R3 12 to LoRa module, SX1278 (Ra-02) MISO
- Arduino Uno R3 10 to LoRa module, SX1278 (Ra-02) NSS
- Arduino Uno R3 9 to LoRa module, SX1278 (Ra-02) RST
- Arduino Uno R3 2 to LoRa module, SX1278 (Ra-02) DIO0
- Arduino Uno R3 3V3 to LoRa module, SX1278 (Ra-02) 3.3V
- Arduino Uno R3 GND to LoRa module, SX1278 (Ra-02) GND
Common errors and how to fix them
Starting LoRa failed!
The library could not talk to the chip over SPI. Check NSS and RESET match setPins(), that MOSI, MISO and SCK are on the board鈥檚 SPI pins, and that the module has 3.3 V, not 5 V.
The sender says it sent, the receiver never gets anything
Compare the frequency, spreading factor, bandwidth and sync word on both sides: any one that differs and the receiver hears nothing. Check also that each module has its antenna attached.
onReceive() never runs
DIO0 is not wired, or not to the pin given to setPins(), or LoRa.receive() was not called after registering the callback. On an AVR the pin must also be an interrupt pin, 2 or 3 on an Uno.
Projects that use LoRa
Built-in projects that include it. Each page has the full sketch and opens in the editor, already wired.
Keep going
More communication libraries
Try LoRa without installing anything
Open the example, change the sketch, and keep your version in a free account.