ESP32/Other radios/67. LoRa for long range
Your chip
Your language
Other radios · 67 of 81

LoRa for long range

Kilometres from a coin cell, through buildings, with no infrastructure at all. The price is bandwidth measured in bytes per minute and a legal duty-cycle limit that decides your design before your code does.

/esp32/lora-for-long-range · arduino · S3

One dial, two effects

SF9, 20 bytes, 125 kHz
153 ms
Spreading factorSF9
Payload20 B
Time on air
153 ms
Messages per hour at 1%
235
Rough range
2.1 km
153 ms on air, about 2.1 km, 235 messages an hour allowed. Note what is not here: LoRa is not a network. Two boards with matching frequency, spreading factor and sync word talk to each other and to nobody else, which is all most projects need. LoRaWAN — gateways, join keys, a server — is a different and much larger thing.

Design for the duty cycle first

Work out how often the device must report, multiply by the airtime at the spreading factor your range needs, and check it against 1% of an hour. If it does not fit, the answer is not a better antenna — it is fewer, smaller messages.

A packed binary struct of six bytes at SF9 is about 60 ms on air. The same reading as JSON is four times that, for no extra information.

LoRa and LoRaWAN are not the same thing

LoRa is two radios talking to each other. Matching settings, a sync word, done. This is what most projects want.

LoRaWAN adds gateways, a network server, join procedures and keys, so your device can reach the internet through infrastructure somebody else runs. Much more capable, much more to set up, and unnecessary if the receiver is your own board on your own hill.

On your S3
ChipXtensa LX7 · 2 × 240 MHz
Board settingESP32S3 Dev Module
Default I2CSDA 8 · SCL 9
Watch out forThe port vanishes after upload

The code

The ESP32 has no LoRa radio - this is an SX1276 or SX1262 module on SPI. Frequency, spreading factor and sync word must match at both ends or the packets simply do not exist for the receiver.

lora_send.ino
#include <SPI.h>
#include <LoRa.h>

typedef struct { uint8_t id; int16_t temp; uint16_t mv; } Packet;

void setup() {
  Serial.begin(115200);
  LoRa.setPins(18, 14, 26);          // CS, reset, DIO0
  if (!LoRa.begin(868E6)) {          // check your region
    Serial.println("no radio");
    return;
  }
  LoRa.setSpreadingFactor(9);        // 7 fast and near, 12 slow and far
  LoRa.setSignalBandwidth(125E3);
  LoRa.setSyncWord(0x12);            // must match the receiver

  Packet p = { 3, 2140, 3820 };
  LoRa.beginPacket();
  LoRa.write((uint8_t *)&p, sizeof(p));
  LoRa.endPacket();
}

void loop() {}

868 MHz in Europe, 915 MHz in North America, 433 MHz in some regions. Transmitting on the wrong band is illegal, not merely unreliable.

When it does not work

Nothing is received and both boards say they are fine

Frequency, spreading factor, bandwidth and sync word all have to match. Any one of them wrong gives silence rather than errors - LoRa has no way to report a packet it did not decode.

The range is far worse than the datasheet promises

Antenna. A module transmitting without one can damage itself, and a coil of wire at the wrong length is close to no antenna. Get the length right for your band and keep it clear of the board.

It works for a while and then stops sending

You hit the duty-cycle limit and the stack is enforcing it, or the local regulator is. 1% at 868 MHz means roughly 36 seconds of transmission per hour.

I need it to reach the internet

That is LoRaWAN, not LoRa - gateways, join keys and a network server. Two boards talking directly is much simpler and covers most projects.

Where this goes next

Every radio on the last five pages was chosen for battery life. The next chapter is where that battery life actually comes from.

Deep sleep and wake sources

Edit this page — content/esp32/lora-for-long-range.mdx

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32 on the forum