Skip to content

Repository files navigation

Proyecto Sueña — ESP32 Environmental & Noise Sensor Node

Battery-powered ESP32 firmware that measures ambient light, temperature, calibrated sound level (dB) and battery charge, buffers readings to flash, and publishes them as JSON over MQTT.

Context — Proyecto Sueña (Red de Salud UC CHRISTUS). This firmware powers the sensor nodes of Proyecto Sueña, an initiative to monitor and improve the rest and sleep environment of hospitalized patients. Each node continuously measures the noise, light and temperature conditions at the bedside so that disruptive levels can be detected and acted upon — factors directly linked to patient sleep quality and recovery.

Platform Arduino MQTT Language License Version


What it is

Proyecto Sueña is the firmware for a small, self-contained IoT sensor node built around an ESP32. Each node samples its environment every couple of seconds, computes a true A/C-weighted sound pressure level in real time using an assembly-optimised IIR filter, stores the readings as JSON lines in on-board flash (SPIFFS), and periodically wakes Wi-Fi to push the buffered batch to an MQTT broker. Between publishes the radio is switched off to save power, making the design suitable for battery operation.

The node also subscribes to an NTP-over-MQTT topic so the broker can push wall-clock time into the ESP32's internal RTC, allowing every reading to carry a real epoch timestamp.

Features

  • Light level — lux measurement via a BH1750 ambient-light sensor (I²C), with a software calibration factor.
  • Temperature — read from a Bosch BME280 sensor (I²C, address 0x76).
  • Sound level (dB) — continuous Leq sound-pressure measurement from an INMP441 I²S MEMS microphone, with:
    • per-microphone equalisation IIR filter (flattens the INMP441 response),
    • selectable A-weighting / C-weighting frequency weighting,
    • a hand-written ESP32 assembly SOS-IIR kernel for low-overhead, real-time filtering on a dedicated FreeRTOS task,
    • 48 kHz sampling with overload / noise-floor clamping.
  • Battery gauge — battery percentage derived from an ADC pin through a voltage divider, mapped to 0–100 %.
  • Timestamping — RTC kept in sync via an NTP time string received over MQTT.
  • Store-and-forward — readings are appended to a SPIFFS file as JSON and flushed to MQTT in batches.
  • Power management — Wi-Fi is enabled only around a publish and CPU runs at 80 MHz.
  • Self-healing — watchdog-style restarts on Wi-Fi connect failures or an obviously invalid timestamp.

Hardware

Function Part / signal ESP32 pin Bus / notes
Microphone (sound) INMP441 I²S MEMS WS=19, SCK=18, SD=23 I²S peripheral I2S_NUM_0, 48 kHz, 24-bit, left channel
Light sensor BH1750 SDA/SCL (I²C) Default I²C address
Temp / humidity Bosch BME280 SDA/SCL (I²C) I²C address 0x76 (only temperature is read)
Battery sense Voltage divider GPIO36 (ADC1_CH0) analogRead mapped 2827–4350 → 0–100 %

Pins are defined in readNoise.h (I²S) and readSensors.h (battery). I²C uses the ESP32 default Wire pins (SDA=21, SCL=22). Adjust the #defines to match your board.

Architecture

flowchart LR
    subgraph Sensors
        MIC[INMP441 I2S mic]
        LUX[BH1750 lux]
        BME[BME280 temp]
        BAT[Battery ADC]
    end

    MIC -->|48 kHz I2S| DSP[SOS-IIR filter task<br/>EQ + A/C weighting]
    DSP -->|Leq dB| AGG
    LUX --> AGG[Reading aggregator]
    BME --> AGG
    BAT --> AGG

    AGG -->|JSON line| FS[(SPIFFS buffer)]
    FS -->|batch on timer| PUB[Publisher]
    PUB -->|enable Wi-Fi| WIFI[Wi-Fi STA]
    WIFI --> BROKER{{MQTT broker}}
    BROKER -->|ntp/time| RTC[ESP32 RTC]
    RTC --> AGG
Loading

Module breakdown

File Responsibility
V1.1.6.ino Main sketch: setup, timers, sensor read loop, JSON payload assembly and publish orchestration.
wireless.h Wi-Fi station bring-up/tear-down and broker constants (credentials pulled from secrets.h).
MQTTHandler.h PubSubClient setup, connect/reconnect, ntp/time subscription and the RTC time callback.
readSensors.h BH1750 lux, BME280 temperature and battery-percentage reads.
readNoise.h I²S microphone init, FreeRTOS reader task and Leq dB calculation.
sos_IRR_Filter.h ESP32 assembly Second-Order-Sections IIR filter engine (© Ivan Kostoski, GPLv3).
storageHandler.h SPIFFS helpers: init, start/append/clear and read-back of the JSON buffer file.
neoTimer.h Lightweight non-blocking millis() timer class used to schedule sampling and publishing.
SoftwareStack.h Small string helper utilities (split / Stringchar*).

Build & flash

This is an ESP32 project and depends on ESP32-only APIs (I²S driver, SPIFFS, FreeRTOS, inline Xtensa assembly), so it must be built for an ESP32 target.

1. Provide credentials first

cp secrets.h.example secrets.h
# edit secrets.h with your Wi-Fi SSID/password and MQTT broker details

2a. Arduino IDE

  1. Install the ESP32 board package (Espressif) via the Boards Manager.
  2. Select your ESP32 board and enable a SPIFFS-capable partition scheme.
  3. Install these libraries from the Library Manager:
    • PubSubClient (Nick O'Leary)
    • ESP32Time (fbiego)
    • BH1750 (Christopher Laws)
    • Adafruit BME280 + Adafruit Unified Sensor
  4. Open V1.1.6.ino and upload.

2b. PlatformIO

A minimal platformio.ini:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
lib_deps =
    knolleary/PubSubClient
    fbiego/ESP32Time
    claws/BH1750
    adafruit/Adafruit BME280 Library
    adafruit/Adafruit Unified Sensor

The SOS-IIR engine, Wi-Fi, I²S and SPIFFS are part of the Arduino-ESP32 core and need no extra dependency.

MQTT reference

Direction Topic Payload
Publish Sensores/7 JSON object(s) — one per reading, batched (see below).
Subscribe ntp/time Date-time string YYYY-MM-DD HH:MM:SS used to set the RTC.
  • Broker: host/port from secrets.h, TCP 1883.
  • Client ID: ESP32_clientID.
  • Publish topic is MQTT_PUB_ID in V1.1.6.ino (default Sensores/7, matching idSensor = "7").

Reading payload

Each reading is a compact JSON object:

{ "id": "7", "ts": "1716902400", "l": "120", "t": "23.40", "n": "47.2", "b": "86" }
Key Meaning Unit
id Sensor / node ID
ts Epoch timestamp seconds
l Light level lux
t Temperature °C
n Sound pressure level (Leq) dB
b Battery %

Configuration

Setting Where
Wi-Fi SSID / password secrets.h (WIFI_SSID, WIFI_PASSWORD)
MQTT broker / user / password secrets.h (MQTT_SERVER, MQTT_USER, MQTT_PASS)
Node ID & publish topic idSensor, MQTT_PUB_ID in V1.1.6.ino
Sample interval interval in V1.1.6.ino
Publish interval eventTime_2_mqttPub in V1.1.6.ino
Frequency weighting (A/C) WEIGHTING in readNoise.h
Microphone calibration MIC_* defines in readNoise.h
Lux calibration factor bh1750Factor in readSensors.h
Battery ADC mapping readBatt() in readSensors.h
I²S / I²C pins readNoise.h / Wire.begin()

Version

Current firmware: V1.1.6 (sketch V1.1.6.ino; FIRMWARE_VERSION = "1.1"). See the header comment block in the sketch for the change history of earlier revisions.

Acknowledgements

The real-time sound-level pipeline (the assembly SOS-IIR filter in sos_IRR_Filter.h, the INMP441 equaliser and the A/C-weighting coefficients) is based on Ivan Kostoski's ESP32 sound-level-meter work and is distributed under the GNU GPL v3 — see the header in sos_IRR_Filter.h.

License

The original code in this repository is released under the MIT License — see LICENSE. Note that sos_IRR_Filter.h is third-party code under GPLv3; if you redistribute the combined firmware, honour that license for that file.

About

Proyecto Sueña (UC CHRISTUS) — firmware ESP32 para nodos sensores que monitorean ruido, luz y temperatura del ambiente de descanso de pacientes hospitalizados; publica por MQTT.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages