All five LoRa mesh weather nodes

Overview

This was our senior capstone project (CECS 490B) at Cal State Long Beach. A team of five — Roy Mears, Jonathan Ramirez, Luis Arevalo, myself, and Raul Vargas — designed and built a distributed LoRa mesh network of battery-powered weather stations that collect environmental data and relay it across nodes without any existing wireless infrastructure.

Each node measures temperature, humidity, barometric pressure, and GPS location, then broadcasts that data over LoRa at 915 MHz. Neighboring nodes relay the packets using a TTL-limited flooding algorithm, allowing data to hop across the network until it reaches the base station — even if a node can’t reach it directly.

Single node closeup showing OLED display and antenna


How It Works

Mesh network topology diagram

The system uses a mesh topology instead of a traditional star network. Every node acts as both a data source and a relay. When a node collects sensor readings, it packages them into a LoRa packet and broadcasts it. Any neighboring node that receives a new packet will:

  1. Check if it has already seen the packet (duplicate suppression via packetId)
  2. If new, decrement the TTL and rebroadcast
  3. If TTL reaches zero, accept but don’t forward

This means data can travel multiple hops to reach the base station, and if one node goes down, packets automatically route through alternate paths. The network is self-healing — no manual reconfiguration needed.


Hardware

ESP32 LoRa 32 V3

Heltec ESP32 LoRa development boards

The brain of each node. It integrates a dual-core 240 MHz processor, WiFi, Bluetooth, and most importantly a Semtech SX1262 LoRa transceiver. The radio uses Chirp Spread Spectrum modulation at 915 MHz, encoding data as frequency-modulated chirps that are resistant to noise and environmental interference. The transceiver communicates with the ESP32 via SPI.

Sensors

SHT30 temperature and humidity sensor

Each node carries three sensors:

  • SHT30 — Digital temperature and humidity sensor over I2C. Factory-calibrated, 16-bit output, capacitive humidity measurement paired with band-gap temperature sensing.
  • BMP180 — Barometric pressure sensor over I2C. Piezoresistive element measures air pressure changes, with onboard calibration coefficients in non-volatile memory.
  • NEO-6M GPS — Provides geolocation and time synchronization via UART. Parses NMEA sentences for latitude, longitude, and UTC time. Updates once per second.

NEO-6M GPS module

Power

LiPo battery and buck converter

Each node runs on a 7.4V LiPo battery through a buck converter that steps down to a stable 5V for the ESP32 board, which then regulates to 3.3V internally. The layered power regulation ensures stable operation across the full battery discharge range. In testing, nodes ran for about 35 hours on a single charge, with the GPS being the primary power draw.

Enclosure

Custom 3D-printed enclosures (PLA) protect the hardware from outdoor conditions while maintaining airflow through honeycomb vents for accurate sensor readings. Internal mounting structures secure the electronics and position the antenna for optimal signal propagation.


Schematic

KiCad schematic for the CECS 490 final project

Designed in KiCad. The schematic shows the ESP32 LoRa 32 V3 as the central microcontroller, with the SHT30 and BMP180 on the I2C bus, NEO-6M GPS on UART, OLED display on I2C, LoRa transceiver on SPI, and the LiPo battery routed through the buck converter.


Firmware Architecture

Software architecture class diagram

The firmware was developed in PlatformIO using the Arduino framework. The code is divided into functional modules:

  • Main loop — Samples sensors at fixed intervals, processes incoming LoRa packets, manages the transmit queue, and updates the OLED display
  • Mesh layer — Handles TTL decrementing, duplicate packet suppression via a history buffer, and automatic retransmission
  • Sensor module — Communicates with SHT30 and BMP180 over I2C, samples at fixed intervals to minimize power consumption
  • LoRa communication — Configures the SX1262 radio parameters (frequency, spreading factor, bandwidth), serializes/deserializes packets, and provides RSSI readings
  • Serial command interface — Allows viewing neighbor tables, mesh stats, and sending test messages for debugging

Packet Structure

Each packet contains:

  • meshSourceId — Node that originally created the packet
  • meshSenderId — Node that most recently forwarded it
  • meshTtl — Time-to-live, limits hop count (default: 3)
  • packetId — Unique ID for duplicate detection
  • Sensor payload — Temperature, humidity, pressure, battery voltage

Dashboard

LoRa Mesh Dashboard showing 3 nodes online

The base station node connects to a PC via USB serial. A custom script decodes incoming packets and feeds them to a browser-based dashboard built with Leaflet.js. The dashboard displays:

  • Live map of all node positions from GPS data
  • Real-time sensor readings — temperature, humidity, pressure, altitude
  • Battery status and satellite count per node
  • Mesh routing paths reconstructed from meshSenderId fields
  • RSSI color-coded link quality showing signal strength between nodes
  • Hop counts derived from TTL metadata

Design Specs

Spec Requirement
Temperature Range -20C to +60C, +/-3C
Humidity Range 0-100% RH, +/-2% RH
Pressure Range 300-1100 hPa, +/-1 hPa
LoRa Frequency 915 MHz ISM
Transmission Range 1+ km line-of-sight, 2-5 km ideal
Max Hop Count 3
Delivery Success 95%+
Per-Hop Latency under 500 ms
Battery Life ~35 hours continuous
Supported Nodes 3-10

My Contributions

  • Hardware integration — Wiring sensors, power regulation, and antenna placement across all five nodes
  • Firmware architecture — Structured the modular codebase, implemented sensor sampling and packet assembly
  • Mesh packet structure — Designed the packet format with TTL, source/sender IDs, and duplicate suppression logic
  • Field testing — Range testing across 2+ km in multiple environments, validating mesh rerouting on node failure
  • Enclosure assembly — Final hardware installation into 3D-printed housings

What I Learned

This project was a crash course in everything from RF communication to distributed systems on constrained hardware. The biggest takeaways:

  • LoRa is incredibly capable for low-power, long-range scenarios — but packet size and duty cycle constraints force you to think carefully about what data you send
  • Mesh networking on microcontrollers requires keeping algorithms simple. TTL-limited flooding is less sophisticated than full routing protocols, but it is robust and fits in limited memory
  • Power budgeting matters — the GPS module dominated our power draw, and we had to balance sampling rates against battery life
  • Field conditions are unpredictable — what works on a bench does not always work across a park with trees, buildings, and interference