An ESP32-C6 environmental monitoring system that measures temperature, humidity, pressure, and air quality (VOC), with OLED display, web interface, Home Assistant integration, and OTA updates.
- Multi-sensor support: Primary BME680 sensor with automatic DHT11/DHT22 fallback
- Real-time display: SSD1306 OLED showing temperature, humidity, and VOC readings
- Web API: JSON endpoint with CORS support for remote monitoring
- Home Assistant: MQTT auto-discovery for seamless integration
- OTA updates: Wireless firmware updates after initial flash
- Captive portal: Easy WiFi and MQTT provisioning without hardcoded credentials
- Visual status: NeoPixel RGB LED for at-a-glance system status
- Robust error handling: Auto-reconnection and fallback mechanisms
- Board: Seeed XIAO ESP32-C6
- Sensors (one of):
- BME680 environmental sensor (I2C address 0x77) - recommended
- DHT11 or DHT22 temperature/humidity sensor
- Display: SSD1306 OLED (128x64, I2C address 0x3C)
- LED: WS2812B NeoPixel RGB LED
| Component | GPIO Pin | Notes |
|---|---|---|
| I2C SDA | GPIO 22 | Custom pin assignment |
| I2C SCL | GPIO 23 | Custom pin assignment |
| DHT Data | GPIO 17 | Only if using DHT sensor |
| NeoPixel | GPIO 19 | Some ESP32-C6 boards have them built in |
- PlatformIO installed
- USB cable for initial firmware flash
- WiFi network credentials
- Clone the repository:
git clone <repository-url>
cd leviathan- Build the firmware:
pio run- Connect your ESP32-C6 via USB and upload:
pio run -t upload- Monitor serial output (optional):
pio device monitor- On first boot, the device will create a WiFi access point (SSID shown on OLED)
- Connect to the AP and configure:
- WiFi credentials
- Device name and ID
- MQTT settings (optional)
- OTA password (recommended)
- Device will restart and connect to your WiFi network
Access sensor data via HTTP:
curl http://kahuna.local/Response format:
{
"t": 21.50,
"h": 50.00,
"p": 101325.00,
"voc": 1200.00
}Fields: t (temperature °C), h (humidity %), p (pressure Pa), voc (gas resistance Ω)
After enabling OTA in the provisioning portal, update wirelessly:
pio run -t upload --upload-port kahuna.localSecurity Note: Always set a strong OTA password to prevent unauthorized firmware updates.
If MQTT is configured, the device automatically appears in Home Assistant with sensors for:
- Temperature (°C)
- Humidity (%)
- Pressure (Pa) - BME680 only
- VOC/Gas Resistance (Ω) - BME680 only
MQTT topics:
- State:
envmon/{device_id}/state - Availability:
envmon/{device_id}/availability - Discovery:
homeassistant/sensor/{device_id}/{sensor}/config
| Color | Status |
|---|---|
| 🔴 Red | Initializing |
| 🟡 Yellow | WiFi disconnected |
| 🟢 Green | Normal operation |
| 🔵 Blue | Sensor error |
| 🟣 Magenta | OTA update in progress |
Shows device name, IP address, or error messages like "WiFi Error" or "Sensor Error"
src/
main.cpp - Main application logic
MqttPublisher.cpp - MQTT and Home Assistant discovery
ProvisioningPortal.cpp - Captive portal and NVS storage
OtaManager.cpp - OTA firmware management
include/
DisplayManager.h - Display abstraction
SensorManager.h - Unified sensor interface
DisplayFormatter.h - Display formatting utilities
RuntimeUtils.h - Status and JSON utilities
MqttPublisher.h - MQTT interface
ProvisioningPortal.h - Provisioning interface
OtaManager.h - OTA interface
test/ - Unit tests (Unity framework)
platformio.ini - PlatformIO configuration
Build only:
pio runUpload via USB:
pio run -t uploadClean build:
pio run -t cleanRun tests:
pio testRun specific test:
pio test -f test_runtime_utils- DHT sensor library for ESPx
- Adafruit BME680 Library
- ESPAsyncWebServer
- Adafruit SSD1306
- Adafruit NeoPixel
- PubSubClient (MQTT)
- ArduinoOTA
All dependencies are managed via PlatformIO and automatically installed.
All settings are stored in NVS (non-volatile storage) and configured via the captive portal:
- WiFi: SSID and password
- Device: Name and unique ID
- MQTT: Host, port, credentials, and topic prefix
- OTA: Enable/disable and password protection
To reconfigure, clear NVS or force provisioning mode (future: physical button).
- Measures: Temperature, humidity, pressure, VOC
- Configuration:
- Temperature oversampling: 8x
- Humidity oversampling: 2x
- Pressure oversampling: 4x
- IIR filter: Size 3
- Gas heater: 320°C for 150ms
- Sample rate: 1 second
- Measures: Temperature, humidity
- Auto-selected if BME680 not detected
- Sample rate: DHT-specific minimum
Device won't connect to WiFi:
- Check credentials in provisioning portal
- Verify WiFi signal strength
- Device shows "WiFi Error" after 15 seconds
Sensor Error displayed:
- Check sensor wiring (I2C on GPIO 22/23)
- Verify I2C addresses (BME680: 0x77, DHT: GPIO 17)
- Error shown after 15 seconds of failed reads
MQTT not working:
- Verify broker is reachable
- Check MQTT credentials
- Monitor serial output for connection errors
OTA upload fails:
- Verify OTA is enabled in settings
- Check OTA password matches
- Ensure device is on network and reachable
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
MIT License - see LICENSE file for details
Built with:
Project Status: Active development - OTA updates feature recently added