Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

SX1278 LoRa (Ra-02) with ESP32 DevKit V1 — VSPI wiring and ping test

Wire an SX1278 Ra-02 LoRa module to an ESP32 DevKit V1 on VSPI with NSS on D4, run a two-board ping test with RSSI, and pick the right frequency for India.

Arduino C++Verified — core esp32 3.3.12, LoRa 0.8.0, 3 Nov 2026Compile-only

Community draft — report a mistake

LoRa trades speed for range: a few bytes at a time, but over hundreds of metres to kilometres on very little power — ideal for a farm sensor or a water-tank level sender far from the house’s Wi-Fi.

The SX1278 talks SPI, and the ESP32 DevKit V1’s VSPI pins D18/D19/D23 are its natural bus. Chip select, reset and DIO0 go on pins that stay quiet at boot (D4, D27, D26). Flash the same sketch on two boards and each prints the other’s pings with signal strength — the quickest way to test range before building a real node.

Wiring

ESP32 DevKit V1Only the pins used are shown · 3.3 V logicSX1278 LoRa module (Ra-02, 433 MHz)D26D27GNDD23D19D18D43V33.3VGNDNSSSCKMOSIMISORSTDIO0
Also needed: 433 MHz antenna (spring or SMA) — fitted before power-up, 10 µF capacitor across 3.3V–GND at the module (recommended).
Every connection
ESP32 DevKit V1SX1278 LoRa module (Ra-02, 433 MHz)WireNotes
3V33.3Vred3.3 V only — never VIN. The module draws about 120 mA while sending; a 10 µF capacitor at the module helps on long wires.
GNDGNDblack
D18SCKyellowVSPI clock
D19MISOblueVSPI MISO
D23MOSIgreenVSPI MOSI
D4NSSpurpleChip select. Not D5: GPIO5 is a strapping pin.
D27RSTorangeNot D14 or D12 — those toggle or strap at boot.
D26DIO0whiteSignals “packet sent / received”. Any non-strapping pin works.

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

  • Both sides are 3.3 V, so the SX1278 wires straight to the ESP32 — no level shifting as on an Uno. The ESP32’s 3V3 regulator handles the 120 mA transmit peaks from USB.
  • Frequency must match the hardware. The SX1278 chip covers 137–525 MHz; the Ra-02 sold in India is tuned for 433 MHz, so the sketch uses 433E6. India’s LoRaWAN band is 865–867 MHz — for that you need an SX1276-based module (RFM95, Ra-01H) and 866E6, not an SX1278 set to a higher number.
  • Never transmit without the antenna. The power amplifier reflects its own output back and can be damaged. Solder the spring or screw on the SMA antenna first.
  • The sketch keeps power at 10 dBm (10 mW) with SF9. That reaches a few hundred metres in a town and keeps you within the low-power limits of the licence-exempt bands; check current WPC rules before raising it.
  • Most Ra-02 modules have 2 mm pitch pads, not 2.54 mm. Solder short wires or use an adapter board — they don’t fit a breadboard.

Code

lora-sx1278-esp32.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// SX1278 (Ra-02, 433 MHz) LoRa ping node on an ESP32 DevKit V1.
// 3.3V → 3V3, GND → GND, SCK → D18, MISO → D19, MOSI → D23 (VSPI),
// NSS → D4, RST → D27, DIO0 → D26. Flash the same sketch on two boards: each sends
// "ping N" every 10 s and prints whatever it hears, with RSSI and SNR.
// Screw the antenna on BEFORE powering up — transmitting without one can damage the module.
#include <SPI.h>
#include <LoRa.h>

constexpr uint8_t LORA_NSS = 4;
constexpr uint8_t LORA_RST = 27;
constexpr uint8_t LORA_DIO0 = 26;
constexpr long FREQ_HZ = 433E6;  // must match your module: Ra-02 = 433 MHz.
                                 // 865–867 MHz needs an SX1276 module (e.g. RFM95), not an SX1278.

uint32_t counter = 0;
uint32_t lastSend = 0;
uint32_t interval = 10000;

void setup() {
  Serial.begin(115200);
  SPI.begin(18, 19, 23);  // SCK, MISO, MOSI — the VSPI defaults, written out
  LoRa.setPins(LORA_NSS, LORA_RST, LORA_DIO0);
  if (!LoRa.begin(FREQ_HZ)) {
    Serial.println("LoRa module not found — check 3.3V, NSS on D4 and RST on D27");
    while (true) delay(1000);
  }
  LoRa.setTxPower(10);          // 10 dBm (10 mW): plenty for a few hundred metres
  LoRa.setSpreadingFactor(9);   // SF9: more range than the default SF7, still quick
  LoRa.enableCrc();
  Serial.printf("LoRa ready at %.1f MHz, SF9, 10 dBm\n", FREQ_HZ / 1e6);
}

void loop() {
  // Receive: parsePacket() returns the packet size, or 0 if nothing arrived.
  int size = LoRa.parsePacket();
  if (size) {
    String msg;
    while (LoRa.available()) msg += (char)LoRa.read();
    Serial.printf("Got \"%s\"  RSSI %d dBm  SNR %.1f dB\n", msg.c_str(), LoRa.packetRssi(), LoRa.packetSnr());
  }

  // Send every 10 s, with a little random offset so two nodes don't stay in step.
  if (millis() - lastSend > interval) {
    lastSend = millis();
    interval = 10000 + random(0, 1000);
    LoRa.beginPacket();
    LoRa.printf("ping %lu", (unsigned long)counter);
    LoRa.endPacket();  // blocks until sent (~0.2 s at SF9)
    Serial.printf("Sent \"ping %lu\"\n", (unsigned long)counter++);
  }
}

Library: LoRa (Sandeep Mistry) — compiled with LoRa 0.8.0.

Expected serial output

Serial Monitor · 115200Output
LoRa ready at 433.0 MHz, SF9, 10 dBm
Sent "ping 0"
Got "ping 0"  RSSI -61 dBm  SNR 9.5 dB
Sent "ping 1"
Got "ping 1"  RSSI -63 dBm  SNR 9.0 dB

Common errors

“LoRa module not found”

LoRa.begin() reads the chip version over SPI and got nothing. Check 3.3V and GND, that NSS is on D4 and RST on D27, and that MISO/MOSI are not swapped (D19 = MISO, D23 = MOSI).

Each board sends, but neither receives

Both must use the same frequency, spreading factor and sync word — flash the identical sketch on both. Also check both modules are the same band (433 vs 868 MHz look identical).

Range is only a few metres

No antenna, the wrong band’s antenna, or a module damaged by transmitting without one. Hold the antennas vertical and away from the ESP32 board.

↑↓ to move · Enter to open