System Summary

The greenhouse continuously measures temperature, humidity, and light intensity and streams telemetry remotely. It also receives configuration commands (setpoints, ranges, hysteresis, persistence) and applies them safely to local control logic.

  • Sensors: SHT31 (temperature/humidity), BH1750 (lux) via I²C
  • Local UI: OLED status + menu navigation using rotary encoder
  • Remote monitoring: MQTT → Node-RED → InfluxDB → Grafana
  • Remote control: Bidirectional configuration updates via MQTT
Prototype device photo

Software + System Architecture

The embedded firmware is split into FreeRTOS tasks (sensing, UI, logic, networking). A queue-based design keeps interfaces clean and reduces coupling during team development and integration.

  • Queue-first communication: structured messages instead of shared globals
  • Deterministic behavior: sampling / UI refresh / publish periods kept predictable
  • Remote pipeline: MQTT topics map cleanly to dashboard + control variables
High-level data flow
  • Sensors Task → Environment Queue → Display Task + Logic Task
  • MQTT Task → Config Queue → Logic Task (+ UI updates)
  • MQTT → Node-RED → InfluxDB → Grafana
Architecture diagram

Firmware Architecture (FreeRTOS Tasks)

The firmware is structured as independent tasks rather than a single loop. Each task owns its timing and responsibility, while queues provide safe, testable interfaces between modules.

  • Sensors Task: reads I²C sensors; publishes environment payloads
  • Display/UI Task: OLED rendering + rotary encoder menus
  • Logic Task: applies setpoints / hysteresis / persistence; controls actuators
  • MQTT Task: publishes telemetry and receives config commands

Remote Monitoring & Control

Telemetry is published to MQTT topics and processed in Node-RED for routing and transformation. InfluxDB stores time-series data, and Grafana visualizes dashboards. Configuration commands are sent back through MQTT to update control parameters on the device.

  • MQTT topics: telemetry + config (bidirectional)
  • Node-RED: parsing, routing, and control flows
  • InfluxDB: time-series storage
  • Grafana: dashboards, trends, thresholds
Grafana dashboard screenshot

Integration Challenges & Lessons

The biggest engineering work was integration: combining independently-developed modules and making the system stable end-to-end. The most common real issues were I²C conflicts (shared bus between display and sensors), task timing interactions, and interface mismatches during merges.

  • I²C integration: display + sensors working alone but conflicting together (addressing, init order, bus speed)
  • Timing: sampling vs UI refresh vs MQTT publish rate trade-offs
  • Merging: resolving conflicts by enforcing clean module boundaries + message schemas
What worked well: queue-based interfaces + clear “who owns what data” rules made debugging and integration much faster.

Tech Stack

Embedded

ESP32-S3 (Heltec WiFi LoRa 32 V3), C/C++, FreeRTOS, GPIO, I²C

Sensors & UI

SHT31, BH1750, OLED display, rotary encoder

Cloud & Monitoring

MQTT, Node-RED, InfluxDB, Grafana dashboards