Development · Data · AI

IoT Environmental Monitor with ESP32

Master-slave IoT station with ESP32 and environmental analytics in PySpark.

1 star2026role: team developmentstatus: active

01 Problem and context

Low-cost environmental instrumentation fails differently than standard software. Data originates from an inexpensive analog sensor, travels across an unreliable wireless link, and lands on a server that has no control over the exact measurement timestamp. The design hinges on the entire pipeline, not on any single link in isolation.

Low-cost environmental instrumentation fails differently from ordinary software. The reading is born in a cheap analog sensor, crosses a wireless link that drops, and lands on a server with no control over when the measurement was taken. The design is decided across the whole chain, from capture through transport and persistence to analysis, and not in any single link.

02 Solution

Two ESP32 nodes in a master-slave topology linked via ESP-NOW without relying on a local WiFi network, featuring channel hopping on the slave to reconnect to the master after a disconnection. Five signals with fixed identifiers ensure each reading's source is explicit in the database, telemetry transmits every 15 seconds without blocking the touch interface, and PySpark analytics benchmark local readings against external weather and air quality reference data.

  1. Topology definition: an ESP32 gateway with a touchscreen (DHT22 for temperature and humidity, MQ135 for gas) plus a remote node contributing gas and soil moisture.
  2. Board-to-board link over ESP-NOW, independent of local WiFi, with channel hopping across channels 1 to 13 on the slave so it can find the master again after a dropout.
  3. A standardised telemetry schema of five signals with fixed identifiers, so the origin of every reading is explicit in the database.
  4. Payload pushed every 15 seconds in the background without blocking the touch interface, to a REST API that persists into MySQL with the timezone pinned server-side.
  5. Network setup through a captive portal: the board raises its own access point to receive credentials instead of carrying them hardcoded in the firmware.
  6. A fix for the ESP32's native conflict between the ADC2 converter and an active WiFi antenna, which corrupted the gas reading.
  7. PySpark analytics over the stored series, joining the system's own API with external weather and air-quality sources.

03 Results

Verifiable figures in the repository and its documentation:

2ESP32 nodes in a master-slave network
5standardised environmental signals
15 scloud telemetry interval

04 How it's built

IoT environmental monitoring station built on a two-node ESP32 network: a master gateway with a touchscreen and a slave node that transmits gas and soil moisture readings via ESP-NOW. Every 15 seconds, the master sends five standardized signals (temperature, humidity, local/remote gas, and soil moisture) to a PHP REST API with PDO, persisting them to a remote MySQL database. It also includes a PySpark notebook for Google Colab that integrates four data sources (OpenMeteo, AQICN, the system API, and MongoDB) as a Big Data evaluation.

05 Ethical decisions

  • Network setup runs through a captive portal, so the user's router credentials are never written into the firmware.
  • The system measures a room's environmental variables, not people: no audio, no images, no identifiers of nearby devices.
  • MQ135 readings are shown as relative levels rather than as an air-quality measurement in certified units, because the sensor is not calibrated against a reference standard.

06 Highlights

  • Master-slave architecture with two ESP32s communicating via ESP-NOW, featuring channel hopping (channels 1-13) for slave node self-recovery.
  • Touchscreen gateway (Cheap Yellow Display) that sends the sensor payload every 15 seconds without blocking the UI, including a captive portal for WiFi configuration.
  • PHP backend with PDO for secure insertion into a remote MySQL database with the America/Santiago timezone.
  • Big Data pipeline in PySpark (Google Colab) integrating four sources: OpenMeteo, AQICN, the system's REST API, and MongoDB.
  • ADC2 reading workaround that resolves the native ESP32 conflict between the analog gas sensor and the active WiFi antenna.

07 Limitations

None of the sensors is calibrated against a reference instrument, and that governs everything these data can support. The MQ135 returns a resistance that also depends on temperature and humidity and that drifts over time, so its values are good for comparing a room against itself, not for reporting concentrations. Soil moisture is a raw analog reading with no conversion curve. The series comes from a single installation point, with no redundant sensors and no drift study, and link dropouts leave gaps: the real sampling is not strictly regular despite the nominal interval.