Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ESP32 Low-Power Environmental Sensor Node

Battery-operated ESP32 node that samples temperature, pressure and humidity (BME280), buffers readings across deep-sleep cycles in RTC RAM, and uploads them in batches over Wi-Fi as JSON. Written from scratch — no external libraries: the BME280 driver is implemented directly from the Bosch datasheet, the ring buffer and uplink are plain C/C++ on top of the ESP32 Arduino core.

        ┌───────────── wake (RTC timer, every 5 min) ─────────────┐
        │                                                          │
  deep sleep ──► read BME280 ──► push to RTC-RAM ring buffer ──► batch full?
   ~10 µA        (forced mode,     (CRC-guarded, survives      │no        │yes
                  ~10 ms)           sleep & brownout)          ▼          ▼
                                                          deep sleep   Wi-Fi on,
                                                                       POST JSON,
                                                                       Wi-Fi off

Why it's built this way

Decision Reason
Forced-mode BME280, 1× oversampling Sensor sleeps at ~0.1 µA between wakes; never free-runs. One conversion costs ~10 ms.
Batch uploads (12 samples ≈ 1/hour) Radio dominates the energy budget: ~100 mA while Wi-Fi is up vs. ~40 mA sampling. Batching cuts average current by roughly 10×.
Ring buffer in RTC slow memory Survives deep sleep without flash wear. CRC-16 over the payload detects brownout corruption — on mismatch the node resets the buffer instead of uploading garbage.
Overwrite-oldest on overflow If the server is down for hours, the node keeps acquiring and retains the freshest 16 samples instead of stalling.
Exponential upload backoff (1→2→4 batches, capped) A dead endpoint must not cost a 15 s Wi-Fi timeout every hour. Backoff caps the damage while the ring buffer preserves data.
No external libraries Every register access is reviewable against the datasheet. Nothing hides in a vendor HAL.

Power budget (estimated)

Assumptions: bare ESP32 module (no dev-board USB bridge/LEDs), low-quiescent LDO (~5 µA), 5-minute sampling, hourly upload.

State Current Duration Charge per hour
Deep sleep ~15 µA ~3595 s ~15 µAh
Sample wake (12×) ~45 mA ~0.5 s each ~75 µAh
Upload wake (1×) ~120 mA avg ~5 s ~167 µAh
Total ~257 µAh/h ≈ 0.26 mA avg

A 2500 mAh 18650 cell ≈ 13 months on paper. Real numbers depend on your board: a typical dev board idles at 10–20 mA because of the USB bridge and power LED — for real battery life use a bare module or cut those loads, and measure with a meter (e.g. a µCurrent or a Nordic PPK2) rather than trusting this table.

Building

pip install platformio
pio run                    # compile for ESP32
pio test -e native         # run unit tests on your PC, no hardware needed
pio run -t upload && pio device monitor   # flash + watch logs

Edit src/config.h first: Wi-Fi credentials, endpoint, and pins. Don't commit real credentials.

Wiring

BME280 ESP32
VIN 3V3
GND GND
SDA GPIO 21
SCL GPIO 22

Payload format

{
  "device": "node-01",
  "boot": 42,
  "samples": [
    {"t": 12300, "temp_c": 25.31, "press_pa": 101325, "rh": 46.333}
  ]
}

t is seconds since first boot (monotonic across sleeps). Any HTTP endpoint that accepts a JSON POST works as a collector.

Testing

The ring buffer is pure C and unit-tested on the host (pio test -e native): CRC corruption detection, order preservation, overflow behavior, cold-boot recovery. CI builds the firmware and runs the tests on every push.

License

MIT

About

Low-power ESP32 sensor node — from-scratch BME280 driver, CRC-protected RTC ring buffer, deep sleep telemetry. PlatformIO + CI.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages