Projects / LoRa

LoRa Long-Range Sensor Link

Send temperature and humidity kilometres away — no Wi-Fi, no SIM card.

Intermediate⏱ 2.5 hours4 ElectroTrical boards

Overview

LoRa trades speed for range: a few bytes a minute can travel 1–2 km in a city and much further with line of sight. That's perfect for a farm, a rooftop tank, a villa garden or a remote gate where Wi-Fi doesn't reach.

The sender is an ET-M09 ESP32-C3 battery board with an ET-S61 temperature/humidity sensor and an ET-C15 LoRa radio. It wakes once a minute, sends one packet with the readings and its battery voltage, and sleeps. The receiver — an ET-M02 with a second ET-C15 — prints each packet with its signal strength.

  • 1–2 km range in town, more in open country
  • Temperature, humidity and sender battery voltage
  • Signal strength (RSSI) and SNR for every packet
  • Sender runs for weeks on a LiPo

What you need

ElectroTrical boards

ET-C15 × 2LoRa 433 MHz BoardOne radio at each end
Coming soon
ET-M09ESP32-C3 Battery Dev BoardSender: LiPo charger and battery monitor built in
Coming soon
ET-S61AHT20 Temperature + Humidity SensorSensor at the remote end
Coming soon
ET-M02ESP32-S3 Dev BoardReceiver
Coming soon

You'll also need

  • 1S LiPo, 1,000–2,000 mAh with JST-PH connector, for the sender
  • 1 Qwiic cable
  • Jumper wires
  • Weatherproof box for the sender

Wiring

Never power a LoRa radio without its antenna fitted — transmitting into nothing can damage it. 433 MHz is a short-range-device band in the UAE and many countries; keep to the default power and check your local rules.

Sender: ET-C15 → ET-M09

FromToNote
VSYSVINUSB 5 V or battery; the radio has its own 3.3 V regulator
GNDGND
IO4SCK
IO5MISO
IO3MOSI
IO1CS
IO20RST
IO21DIO0

Sender: sensor

FromToNote
ET-M09 QwiicET-S61 Qwiic

Receiver: ET-C15 → ET-M02

FromToNote
VBUSVIN
GNDGND
IO12SCK
IO13MISO
IO11MOSI
IO10CS
IO4RST
IO5DIO0

Build it

  1. 01

    Fit the antennas

    Screw the spring antennas onto both ET-C15 boards and keep them vertical. Range depends far more on antenna height than on anything in the code.

  2. 02

    Wire both ends

    Wire the sender and receiver as in the tables. The ESP32-C3 pins are chosen to avoid its boot-strap pins (IO2, IO8, IO9).

  3. 03

    Set up the Arduino IDE

    Install the Espressif ESP32 package. For the sender select “ESP32C3 Dev Module”, for the receiver “ESP32S3 Dev Module”; set USB CDC On Boot to Enabled for both.

  4. 04

    Upload the two sketches

    Upload the receiver part to the ET-M02 and open Serial Monitor. Upload the sender part to the ET-M09. A packet should appear within a minute.

  5. 05

    Range test

    Run the sender on battery and walk away with the receiver on a laptop. RSSI around −120 dBm is the edge of reliable reception at these settings.

  6. 06

    Deploy

    Mount the sender box as high as possible with the antenna pointing up, out of direct sun.

Arduino code

Written for the ET-M09 ESP32-C3 Battery Dev Board (sender) and ET-M02 ESP32-S3 Dev Board (receiver). Install these libraries from the Arduino Library Manager:

  • LoRa by Sandeep Mistry
  • Adafruit AHTX0
lora_sender.ino + lora_receiver.ino
// ===================== SENDER (ET-M09, ESP32-C3) =====================
#include <SPI.h>
#include <Wire.h>
#include <LoRa.h>
#include <Adafruit_AHTX0.h>

const int SCK_PIN = 4, MISO_PIN = 5, MOSI_PIN = 3, CS_PIN = 1, RST_PIN = 20, DIO0_PIN = 21;
const int BATT_PIN = 0;             // battery / 2 on IO0
const int SLEEP_S = 60;

Adafruit_AHTX0 aht;

void setup() {
  Serial.begin(115200);
  Wire.begin(6, 7);
  aht.begin();

  SPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, CS_PIN);
  LoRa.setPins(CS_PIN, RST_PIN, DIO0_PIN);
  if (!LoRa.begin(433E6)) { Serial.println("LoRa not found"); esp_deep_sleep(10e6); }
  LoRa.setSpreadingFactor(9);
  LoRa.setTxPower(14);
  LoRa.enableCrc();

  sensors_event_t hum, temp;
  aht.getEvent(&hum, &temp);
  float vbat = analogReadMilliVolts(BATT_PIN) * 2 / 1000.0;

  char msg[48];
  snprintf(msg, sizeof msg, "T=%.1f,H=%.0f,B=%.2f", temp.temperature, hum.relative_humidity, vbat);
  LoRa.beginPacket();
  LoRa.print(msg);
  LoRa.endPacket();
  LoRa.sleep();
  Serial.println(msg);

  esp_deep_sleep((uint64_t)SLEEP_S * 1000000ULL);
}
void loop() {}

// ===================== RECEIVER (ET-M02, ESP32-S3) ===================
// Save this half as its own sketch.
/*
#include <SPI.h>
#include <LoRa.h>

void setup() {
  Serial.begin(115200);
  SPI.begin(12, 13, 11, 10);        // SCK, MISO, MOSI, CS
  LoRa.setPins(10, 4, 5);           // CS, RST, DIO0
  if (!LoRa.begin(433E6)) { Serial.println("LoRa not found"); while (1) delay(100); }
  LoRa.setSpreadingFactor(9);       // must match the sender
  LoRa.enableCrc();
  Serial.println("Listening on 433 MHz...");
}

void loop() {
  if (LoRa.parsePacket()) {
    String msg = LoRa.readString();
    Serial.printf("%s | RSSI %d dBm | SNR %.1f dB\n", msg.c_str(), LoRa.packetRssi(), LoRa.packetSnr());
  }
}
*/

Troubleshooting

Receiver hears nothing

Both ends must use the same frequency (433E6), spreading factor (9) and CRC setting. Check the antennas are fitted and the sender prints its message.

“LoRa not found”

SPI wiring. Check MISO and MOSI aren't swapped and that RST and CS go to the pins in the sketch.

Short range

Raise both antennas and keep them vertical and away from metal. Every metre of height helps more than higher power.

Take it further

  • Forward packets to Home Assistant or a web dashboard from the receiver over Wi-Fi
  • Add a water-level or soil sensor to the remote node
  • Use the ET-P19 timer to cut the sender's sleep current to nanoamps

Turning this into a product?

We design custom boards that combine these sensors on one PCB, with firmware and production.