LoRa sends small packets over kilometres on very little power, which makes it popular for farm sensors, tank levels and village-scale monitoring where Wi-Fi doesn’t reach. The cheap module in Indian shops is the Ra-02 (SX1278).
On the NodeMCU, SCK/MISO/MOSI go to D5/D6/D7 (hardware SPI). The ESP8266-specific choices are the other three: NSS on D2 to keep the D8 boot pin clear, RST on D0, and DIO0 on D1 because D0 can’t do interrupts.
Wiring
| NodeMCU ESP8266 | SX1278 LoRa module (Ra-02, 433 MHz) | Wire | Notes |
|---|---|---|---|
| 3V3 | 3.3V | red | About 120 mA while transmitting — within the NodeMCU regulator’s budget, but nothing else heavy on 3V3. |
| GND | GND | black | |
| D5 | SCK | yellow | D5 = GPIO14, hardware SPI clock. |
| D6 | MISO | green | D6 = GPIO12. |
| D7 | MOSI | blue | D7 = GPIO13. |
| D2 | NSS | purple | Chip select on D2 instead of D8, so the module can’t hold GPIO15 high at boot. |
| D0 | RST | white | RST only needs a plain output — a good use for D0. |
| D1 | DIO0 | orange | D1 = GPIO5, interrupt-capable (D0 is not). |
3.3 V only (1.8–3.7 V) part, 3.3 V board. The SX1278 is a 3.3 V part and its pins are not 5 V tolerant. ESP32 and Pico connect directly. With an Uno or Nano, level-shift NSS, SCK, MOSI and RST, and power the module from a 3.3 V regulator that can supply about 120 mA while transmitting.
Board quirks
- Frequency, honestly: the SX1278 / Ra-02 is a 433 MHz chip; it can’t reach India’s LoRa band of 865–867 MHz (used by LoRaWAN “IN865” gateways). For that you need an SX1276/RFM95 868 MHz module. The sketch uses 433.92 MHz, inside the 433.05–434.79 MHz short-range band, at low power (10 dBm) — check the current WPC rules before deploying anything.
- The SPI bus (D5/D6/D7) is fixed in hardware, but chip select is just a GPIO. Most ESP8266 LoRa examples put NSS on D8 (GPIO15); that works only if nothing pulls it high at reset. Moving NSS to D2 removes the risk and leaves D8 alone.
- D0 (GPIO16) has no interrupt, so it can’t be DIO0. It is fine for RST, which the library only pulses at
begin(). - The module is 3.3 V-only and connects directly — no level shifting on the ESP8266. Never feed its 3.3V pin from VIN.
LoRa.endPacket()blocks for the packet’s airtime (around 200 ms at SF9). That is fine, but higher spreading factors (SF11–12) block for over a second; keep Wi-Fi work out of the same moment or useendPacket(true)for async sending.
Code
// SX1278 (Ra-02, 433 MHz) LoRa module on a NodeMCU (ESP8266) — sends a counter and prints
// anything it hears. Load the same sketch on a second board to test a link.
// 3.3V → 3V3, GND → GND, SCK → D5, MISO → D6, MOSI → D7, NSS → D2, RST → D0, DIO0 → D1.
// NSS is on D2, not D8: D8 (GPIO15) must stay LOW at boot and is better left alone.
#include <SPI.h>
#include <LoRa.h>
const uint8_t LORA_NSS = D2; // GPIO4
const uint8_t LORA_RST = D0; // GPIO16 — a plain output is all RST needs
const uint8_t LORA_DIO0 = D1; // GPIO5 — interrupt-capable (D0 is not)
// 433.92 MHz keeps a 125 kHz channel inside the 433.05–434.79 MHz band. Keep power low.
const long FREQ = 433920000;
unsigned long lastSend = 0;
uint32_t counter = 0;
void setup() {
Serial.begin(115200);
Serial.println();
LoRa.setPins(LORA_NSS, LORA_RST, LORA_DIO0);
if (!LoRa.begin(FREQ)) {
Serial.println("LoRa init failed - check wiring and 3.3 V power");
while (true) delay(1000);
}
LoRa.setTxPower(10); // 10 dBm, the low end
LoRa.setSpreadingFactor(9);
Serial.println("LoRa ready on 433.92 MHz");
}
void loop() {
int size = LoRa.parsePacket();
if (size) {
String msg;
while (LoRa.available()) msg += (char)LoRa.read();
Serial.printf("Received '%s' RSSI %d dBm SNR %.1f dB\n", msg.c_str(), LoRa.packetRssi(), LoRa.packetSnr());
}
if (millis() - lastSend > 5000UL + random(0, 1000)) { // jitter so two boards don't keep colliding
lastSend = millis();
LoRa.beginPacket();
LoRa.print("hello ");
LoRa.print(counter);
LoRa.endPacket(); // blocks for the airtime (~0.2 s at SF9)
Serial.printf("Sent hello %u\n", counter++);
}
}// SX1278 (Ra-02, 433 MHz) LoRa module on a NodeMCU (ESP8266) — sends a counter and prints
// anything it hears. Load the same sketch on a second board to test a link.
// 3.3V → 3V3, GND → GND, SCK → D5, MISO → D6, MOSI → D7, NSS → D2, RST → D0, DIO0 → D1.
// NSS is on D2, not D8: D8 (GPIO15) must stay LOW at boot and is better left alone.
#include <SPI.h>
#include <LoRa.h>
const uint8_t LORA_NSS = D2; // GPIO4
const uint8_t LORA_RST = D0; // GPIO16 — a plain output is all RST needs
const uint8_t LORA_DIO0 = D1; // GPIO5 — interrupt-capable (D0 is not)
// 433.92 MHz keeps a 125 kHz channel inside the 433.05–434.79 MHz band. Keep power low.
const long FREQ = 433920000;
unsigned long lastSend = 0;
uint32_t counter = 0;
void setup() {
Serial.begin(115200);
Serial.println();
LoRa.setPins(LORA_NSS, LORA_RST, LORA_DIO0);
if (!LoRa.begin(FREQ)) {
Serial.println("LoRa init failed - check wiring and 3.3 V power");
while (true) delay(1000);
}
LoRa.setTxPower(10); // 10 dBm, the low end
LoRa.setSpreadingFactor(9);
Serial.println("LoRa ready on 433.92 MHz");
}
void loop() {
int size = LoRa.parsePacket();
if (size) {
String msg;
while (LoRa.available()) msg += (char)LoRa.read();
Serial.printf("Received '%s' RSSI %d dBm SNR %.1f dB\n", msg.c_str(), LoRa.packetRssi(), LoRa.packetSnr());
}
if (millis() - lastSend > 5000UL + random(0, 1000)) { // jitter so two boards don't keep colliding
lastSend = millis();
LoRa.beginPacket();
LoRa.print("hello ");
LoRa.print(counter);
LoRa.endPacket(); // blocks for the airtime (~0.2 s at SF9)
Serial.printf("Sent hello %u\n", counter++);
}
}Library: LoRa (Sandeep Mistry) — compiled with LoRa 0.8.0.
Expected serial output
LoRa ready on 433.92 MHz
Sent hello 0
Received 'hello 3' RSSI -71 dBm SNR 9.5 dB
Sent hello 1LoRa ready on 433.92 MHz Sent hello 0 Received 'hello 3' RSSI -71 dBm SNR 9.5 dB Sent hello 1
Common errors
“LoRa init failed”
Usually NSS or RST on the wrong pin, or MISO/MOSI swapped. Check NSS is on D2 and RST on D0 as in LoRa.setPins(), and that 3.3V is connected.
Board won’t boot after wiring the module
NSS (or another wire) is on D8 and holds GPIO15 high at reset. Move it to D2 — see boot mode (1,6).
Both boards send but neither receives
Settings must match exactly: frequency, spreading factor and bandwidth. Flash the same sketch on both, and fit antennas.