Projects / LoRa
LoRa Long-Range Sensor Link
Send temperature and humidity kilometres away — no Wi-Fi, no SIM card.
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
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
| From | To | Note |
|---|---|---|
| VSYS | VIN | USB 5 V or battery; the radio has its own 3.3 V regulator |
| GND | GND | |
| IO4 | SCK | |
| IO5 | MISO | |
| IO3 | MOSI | |
| IO1 | CS | |
| IO20 | RST | |
| IO21 | DIO0 |
Sender: sensor
| From | To | Note |
|---|---|---|
| ET-M09 Qwiic | ET-S61 Qwiic |
Receiver: ET-C15 → ET-M02
| From | To | Note |
|---|---|---|
| VBUS | VIN | |
| GND | GND | |
| IO12 | SCK | |
| IO13 | MISO | |
| IO11 | MOSI | |
| IO10 | CS | |
| IO4 | RST | |
| IO5 | DIO0 |
Build it
- 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.
- 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).
- 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.
- 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.
- 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.
- 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
// ===================== 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.