An ESP32-based plant monitoring and care system that monitors soil moisture and controls a grow light. The system features a web dashboard for real-time monitoring and control via MQTT.
- Real-time Soil Moisture Monitoring: Capacitive moisture sensor provides accurate soil moisture readings (0-100%)
- Smart Grow Light Control: PWM-controlled grow light with adjustable brightness
- Scheduled Lighting: Configurable time-based schedule for automatic grow light operation
- Web Dashboard: Modern, responsive web interface for monitoring and control
- MQTT Integration: Real-time communication using MQTT protocol
- WiFi Configuration: Easy WiFi setup via captive portal (WiFiManager)
- Multi-Device Support: Monitor and control multiple plant sensors from a single dashboard
- Time Synchronization: NTP-based time sync for accurate scheduling (US Eastern timezone)
- Manual Override: Temporarily override scheduled settings
- ESP32 development board (e.g., ESP32 DevKit V1)
- Capacitive soil moisture sensor (connected to GPIO 34)
- Grow light with PWM control (connected to GPIO 18)
- 5V power supply
- Raspberry Pi or any device running an MQTT broker (e.g., Mosquitto)
- Must be accessible at
raspberrypi.localon port 1883 - WebSocket support on port 9001 for web dashboard
The project consists of three main components:
- ESP32 Firmware (
esp_code/): PlatformIO-based Arduino firmware for the ESP32 - Web Dashboard (
esp_web/): HTML/JavaScript web interface for monitoring and control - Python MQTT Client (
esp_web/plant_sensor_back.py): Simple Python script for testing MQTT messages
- PlatformIO installed (VS Code extension or CLI)
cd esp_code
pio run --target upload- Power on the ESP32
- Connect to the WiFi network named
plant-sensor-XXXX(password:plants123) - Configure your WiFi credentials through the captive portal
- The device will connect to your WiFi and start operating
The firmware expects an MQTT broker at raspberrypi.local:1883. Update the following line in main.cpp if your broker is at a different address:
mqtt.setServer("raspberrypi.local", 1883);The moisture sensor is calibrated for specific air and water values. Adjust these in main.cpp if needed:
const int airVal = 2600; // Sensor reading in dry air
const int waterVal = 1150; // Sensor reading in waterInstall Mosquitto on your Raspberry Pi (or other device):
sudo apt-get update
sudo apt-get install mosquitto mosquitto-clientsEnable WebSocket support by editing /etc/mosquitto/mosquitto.conf:
listener 1883
protocol mqtt
listener 9001
protocol websockets
Restart Mosquitto:
sudo systemctl restart mosquittoThe web dashboard is a static HTML/JavaScript application that runs in your browser.
- Update the MQTT broker address in
esp_web/index.js:
const client = mqtt.connect("ws://raspberrypi:9001", {
reconnectPeriod: 2000,
keepalive: 60,
connectTimeout: 15000,
});- Serve the files using any web server:
cd esp_web
python3 -m http.server 8080- Open your browser to
http://localhost:8080
For testing and monitoring MQTT messages:
cd esp_web
pip install paho-mqtt
python plant_sensor_back.pyUpdate the broker address in the script if needed:
PI = "raspberrypi" # Change to your MQTT broker's hostname/IP- Real-time Updates: View current soil moisture levels and timestamps
- Grow Light Control:
- Toggle power on/off
- Adjust brightness (0-255)
- Set schedules for automatic operation
- Device Naming: Assign custom names to your plants
- Schedule Configuration: Set start and end times for automatic grow light operation
- Manual Override: Temporarily override scheduled settings
plants/{DEVICE_ID}
Payload example:
{
"moisture": 65,
"device_id": "000000000000",
"power": true,
"effective": true,
"brightness": 255,
"name": "Basil",
"schedule": {
"enabled": true,
"start": "07:30",
"end": "22:00"
},
"timestamp": "2026-02-18 12:30:45"
}plants/{DEVICE_ID}/cmd
Command examples:
{"action": "update"} // Request immediate status update
{"name": "Basil"} // Set device name
{"power": true} // Turn on/off
{"toggle": true} // Toggle power state
{"brightness": 128} // Set brightness (0-255)
{"brightness": 50, "asRaw255": false} // Set brightness as percentage (0-100)
{"schedule": {"enabled": true, "start": "07:30", "end": "22:00"}} // Configure schedule┌─────────────┐ WiFi ┌──────────────┐
│ ESP32 │◄────────────────►│ WiFi Router │
│ + Sensors │ └──────┬───────┘
└─────────────┘ │
│
┌─────────────┐ │
│ Grow Light │ │
│ (PWM) │ │
└─────────────┘ │
│
MQTT │
┌─────────────┐ (1883/9001) ┌──────┴───────┐
│ Web │◄────────────────►│ MQTT │
│ Dashboard │ │ Broker │
└─────────────┘ │(Raspberry Pi)│
└──────────────┘
┌─────────────┐ │
│ Python │◄────────────────────────┘
│ Client │
└─────────────┘
plant_sensor/
├── esp_code/ # ESP32 firmware (PlatformIO project)
│ ├── src/
│ │ └── main.cpp # Main ESP32 application
│ ├── include/ # Header files
│ ├── lib/ # Local libraries
│ ├── test/ # Unit tests
│ └── platformio.ini # PlatformIO configuration
│
└── esp_web/ # Web dashboard and tools
├── index.html # Main HTML page
├── index.js # JavaScript for MQTT and UI
├── styles.css # Custom styles
├── plant_sensor_back.py # Python MQTT test client
└── imgs/ # Images (plant emoji)
├── plant_emoji.svg
├── plant_emoji.pdf
└── plant_emoji.eps
- PlatformIO platform:
espressif32 - Framework: Arduino
- Libraries:
WiFiManager(v2.0.17) - WiFi configuration portalPubSubClient(v2.8) - MQTT clientArduinoJson(v6.21.3) - JSON parsing/serialization
- Bootstrap 5.3.8 - UI framework
- jQuery 3.7.1 - DOM manipulation
- MQTT.js - MQTT WebSocket client
paho-mqtt- MQTT client library
- Hold the reset button and check serial output for WiFi manager AP name
- Connect to the
plant-sensor-XXXXnetwork (password:plants123) - Configure WiFi through the captive portal
- If portal times out after 5 minutes, reset the device to try again
- Verify MQTT broker is running:
mosquitto -v - Test MQTT connectivity:
mosquitto_sub -h raspberrypi -t plants/# -v - Check that the ESP32 can reach the broker (ping test)
- Verify ports 1883 (MQTT) and 9001 (WebSocket) are open
- Check browser console for errors
- Verify WebSocket connection to MQTT broker
- Ensure MQTT broker has WebSocket support enabled on port 9001
- Check that you're subscribed to the correct topics (
plants/+)
- Calibrate sensor by updating
airValandwaterValinmain.cpp - Measure sensor output in dry air and in water
- Upload new calibration values to ESP32
This project is open source and available for personal and educational use.
Contributions are welcome! Please feel free to submit issues or pull requests.