Skip to content

Repository files navigation

GrowControl — ESP32 Smart Grow-Tent Controller

A feature-rich ESP32-based controller for managing grow-tent environments, including fan speed control, lighting automation, sensor monitoring, and real-time web dashboard.


Overview

GrowControl uses an ESP32 microcontroller to monitor environmental conditions (temperature, humidity, pressure, CO₂) and automatically control ventilation fans and grow lights via a DFRobot GP8403 I²C DAC. A responsive Angular web interface provides real-time charts, device configuration, and OTA firmware/file-system updates.


Hardware Requirements

ComponentDescription
ESP321x (any ESP32-WROOM module)
I²C DACGravity 2-Channel I2C DAC Module (DFRobot GP8403) — converts I²C to 0–10V PWM signals for fans/lights
SD Card ReaderFor environmental data logging (optional)
SensorBME280 (temperature, humidity, pressure) orENS160 + AHT21 (temperature, humidity, CO₂, TVOC, air quality)
Power12V → 5V step-down regulator for the ESP32

Pin Mapping

SignalGPIO
I²C SDA21
I²C SCL22
SD Card CS5
SD Card MOSI23
SD Card SCK18
SD Card MISO19

DAC Module Wiring Notes

  • Devices sharing the same power source as the ESP32 need only the PWM signal wire (no GND connection).
  • Externally powered devices (e.g., 12V lamp, 24V fan) require a GND connection to the DAC.

Features

Fan Control

  • Control 2 exhaust/blow fans (in/out) independently via 0–10V PWM signals
  • Auto-mode: Fans adjust speed based on temperature and humidity setpoints
  • Speed differential: Fine-tune fan balance to maintain negative pressure in the tent
  • Night mode: Schedule reduced fan speeds during specific time ranges
  • Configurable min/max speed ranges and voltage limits per fan

Light Control

  • Automatic on/off scheduling with configurable sunrise/sunset ramps
  • Manual PWM control (0–255) for direct light intensity adjustment
  • Cloud simulation mode: Simulates natural light variation with configurable min/max intensity and cycle duration
  • Voltage-based calibration for different light types

Sensor Monitoring

  • BME280: Temperature, humidity, pressure with averaging
  • ENS160 + AHT21: Temperature, humidity, CO₂ (eCO₂), Air Quality Index (AQI), TVOC
  • VPD (Vapor Pressure Deficit): Calculated from sensor data for optimal growing conditions
  • Govee BTH5179 (optional): Bluetooth temperature/humidity/battery readings

Data Logging

  • SD-card logging (when enabled): Creates /year/month/day/hour.csv files
  • Stores values every second: time, temperature, humidity, CO₂, light level, VPD
  • Download historical CSV data via web interface

Web Interface

  • Real-time dashboard with live charts (Chart.js)
  • WebSocket-based push updates (~1 Hz when clients connected)
  • Fan configuration panel (speed, voltage limits, auto-mode, night mode)
  • Light configuration panel (schedule, sunrise/sunset, cloud sim)
  • Sensor data display (temperature, humidity, pressure, CO₂, AQI, TVOC)
  • System info (uptime, heap memory, WiFi status, chip info)
  • OTA firmware update via browser
  • SPIFFS filesystem update via browser
  • WiFi configuration page (SSID, password, AP fallback settings)
  • Timezone configuration for accurate sunrise/sunset calculations

Dashboard

Fan Control

Light Control

Sensors

System Settings


Project Structure

GrowControl/
├── src/ # ESP32 firmware (C++)
│ ├── main.cpp # Entry point, setup/loop
│ ├── FanController.cpp/h # Fan speed & auto-control logic
│ ├── LightController.cpp/h # Light scheduling & PWM control
│ ├── MyWebServer.cpp/h # Async web server + WebSocket handlers
│ ├── WiFiManager.cpp/h # WiFi connection + AP fallback + NVS storage
│ ├── MyPreferences.cpp/h # NVS preferences (timezone, etc.)
│ ├── FileController.cpp/h # SD card file I/O
│ ├── Bme280.cpp/h # BME280 sensor driver
│ ├── Ens160Aht2x.cpp/h # ENS160 + AHT21 sensor driver
│ ├── GoveeBTh5179.cpp/h # Govee BTH5179 Bluetooth client
│ ├── Voltage.h # Voltage measurement utility
│ ├── MyTime.h # Time utility
│ └── MyPreferences.h # NVS preferences interface
├── growui/ # Angular frontend
│ ├── src/app/
│ │ ├── api.service.ts # HTTP API client
│ │ ├── websocket.service.ts # WebSocket client (rxjs)
│ │ ├── dashboard.service.ts # Central state management
│ │ ├── types.ts # TypeScript interfaces
│ │ ├── chart/ # Chart.js configuration
│ │ ├── features/
│ │ │ ├── dashboard/ # Main dashboard component
│ │ │ ├── fans/ # Fan control panel
│ │ │ ├── lights/ # Light control panel
│ │ │ ├── sensors/ # Sensor data display
│ │ │ └── system/ # System settings & OTA
│ │ └── shared/
│ │ ├── sidebar/ # Navigation sidebar
│ │ └── topbar/ # Top navigation bar
│ └── package.json # Angular 21 + PrimeNG 21
├── platformio.ini # Build configuration
├── custom_partition.csv # Flash partition layout
├── data/ # Static web assets served by ESP
└── README.md

Build & Flash

Prerequisites

Build Firmware

pio run -e esp32dev

This compiles the firmware and all library dependencies.

Flash to ESP32

pio run --target upload -e esp32dev -f /dev/ttyUSB0 # Linux
pio run --target upload -e esp32dev -f COM5 # Windows

Or use the PlatformIO VS Code extension: PlatformIO: BuildUpload.

Upload SPIFFS Image (optional)

pio run --target uploadfs -e esp32dev

Or via curl:

curl.exe -X POST http://<ESP_IP>/flashspiffs -F "file=@spiffs.bin"

Build Flags & Configuration

All flags are defined in platformio.ini under build_flags. Uncomment by removing the leading semicolon (;).

FlagPurpose
USE_SDCARD=1Enable SD-card logging (/year/month/day/hour.csv)
SENSOR_BME280=1Use BME280 sensor (temperature, humidity, pressure)
SENSOR_ENS160AHT21=1Use ENS160/AHT21 sensor (temperature, humidity, CO₂, AQI, TVOC)
BME_I2C_ADD=119I²C address of BME280 (decimal)
i2c_aht_addr=56I²C address of AHT21 (decimal)
i2c_ens_add=83I²C address of ENS160 (decimal)
I2C_SDA=21I²C SDA GPIO pin
I2C_SCL=22I²C SCL GPIO pin
i2c_pwn_addr=95I²C address of fan PWM controller (DFRobot GP8403)
i2c_light_addr=94I²C address of light PWM controller (DFRobot GP8403)
time_zone_hour_utc_offset=1UTC offset in hours for sunrise/sunset
MYSSID=""Hardcoded WiFi SSID (fallback)
PW=""Hardcoded WiFi password (fallback)
http_port=80HTTP server port
GOVEE_BTH5179=1Enable Govee BTH5179 Bluetooth sensor support
FIRMWARE_VERSION="1.0.0"Firmware version string

Sensor Selection

Only one sensor type should be enabled at a time:

; Option 1: BME280 (recommended for most setups)
-DSENSOR_BME280=1
-DBME_I2C_ADD=119
; Option 2: ENS160 + AHT21 (for CO₂ monitoring)
-DSENSOR_ENS160AHT21=1
-Di2c_ens_add=83
-Di2c_aht_addr=56

Frontend Development

The Angular web interface (growui/) runs as a separate dev server and proxies API requests to the ESP32.

Setup

cd growui
npm install

Configure API Base URL

Edit growui/src/environments/environment.ts:

exportconstenvironment={production: false,apiBaseUrl: 'http://<ESP_IP>',apiPort: 80,};

Run Dev Server

npm start # serves on http://localhost:4200

Build for Production

npm run build

The built files should be placed in the data/ directory and uploaded as SPIFFS.


ESP32 Web API

HTTP Endpoints

EndpointMethodDescription
/settingsGETGet all device configuration and state
/cmdGETExecute command (query params: var, id, val, etc.)
/dataGETGet logged CSV data (params: year, month, day, hour)
/wsWebSocketReal-time push updates (~1 Hz)
/flashfirmwarePOSTOTA firmware update (multipart form)
/flashspiffsPOSTOTA SPIFFS filesystem update (multipart form)
/wifi-configPOSTUpdate WiFi credentials

Command Variables (/cmd?var=...)

varParametersDescription
speedid (0/1), val (0–100)Set fan speed percentage
lightvalval (0–255)Set light PWM value
voltageid, min, maxSet fan voltage calibration limits
autospeedmin, maxSet auto-mode min/max fan speed
autovalstemp, hum, speeddifSet target temperature, humidity, filter compensation
temphumdiftemp, humSet temperature/humidity differential
autocontrolval (0/1)Enable/disable fan auto-control
fannightmodeonh, onm, offh, offm, mspeedSet night mode schedule
fannightmodeactiveval (0/1)Enable/disable night mode
lightautomodeenable (0/1)Enable/disable light auto mode
lightsettimeonh, onmin, offh, offmin, riseh, risemin, seth, setmin, riseenable, setenableSet light schedule
lightvoltagemin, maxSet light voltage limits
lightlimitspmin, maxSet light percentage limits
cloudsimcloudduration, min, maxConfigure cloud simulation
cloudsimactiveval (0/1)Enable/disable cloud simulation
readgoveeval (0/1)Enable/disable Govee sensor reading
timezoneaction=get/set, offsetGet/set timezone offset

WebSocket Message Format

The server pushes JSON messages every second when clients are connected:

{
"bme280": {
"temperatur": "21.72",
"humidity": "33.12",
"atemperatur": "21.75",
"ahumidity": "33.15",
"pressure": "952.54",
"apressure": "952.56",
"vpd": "1.74"
},
"voltage0": 573,
"voltage1": 671,
"nightmode": false,
"time": "14:08:45",
"lightvalP": 0,
"lightvalmv": 0,
"lightstate": 0,
"vpdair": "1.74",
"autocontrolspeed": 50
}

System Architecture

┌──────────────────────────────────────────────────────────────┐
│ ESP32 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │WiFiMgr │ │WebServer │ │ WS │ │Preferences │ │
│ │(NVS) │ │(Async) │ │ (Push) │ │(NVS) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └─────┬──────┘ │
│ │ │ │ │ │
│ ┌────┴──────────────┴─────────────┴───────────────┴──────┐ │
│ │ MyWebServer │ │
│ └────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │FanCtrl │ │LightCtrl │ │Sensors │ │
│ │(GP8403) │ │(PWM) │ │(BME280/ │ │
│ └─────┬────┘ └─────┬────┘ │ENS160) │ │
│ │ │ └──────────┘ │
│ │ │ │
│ ┌─────┴──────────────┴──────────────┐ │
│ │ DFRobot GP8403 DAC │ │
│ │ Channel 0 → Fan 0 (0-10V) │ │
│ │ Channel 1 → Fan 1 (0-10V) │ │
│ │ Channel 2 → Light (0-10V) │ │
│ └───────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
│
│ HTTP + WebSocket
▼
┌──────────────────────────────────────┐
│ Angular Web Dashboard (Browser) │
│ ┌─────────┐ ┌──────┐ ┌──────────┐ │
│ │Dashboard│ │Fans │ │Lights │ │
│ │+Charts │ │Ctrl │ │Ctrl │ │
│ └─────────┘ └──────┘ └──────────┘ │
└──────────────────────────────────────┘

Firmware Version

Current version: 1.0.0 (configurable via FIRMWARE_VERSION build flag)


License

This project is provided as-is for personal use in grow-tent automation.

Releases

Packages

Contributors

Languages