Advanced
5 hours
ESP32 Indoor Air Quality Monitor (CO2, PM2.5, VOC)
Indoor air quality has a significant impact on cognitive performance and health, yet most people have no visibility into CO2 levels, particulate matter, or volatile organic compounds in their homes. This monitor provides all three measurements with a colour-coded Air Quality Index display: green (good), yellow (moderate), orange (poor), red (hazardous). Push notifications via MQTT alert you to open a window when CO2 exceeds 1000 ppm.
What You’ll Need
- ESP32 DevKit
- Sensirion SCD30 CO2 + temperature/humidity sensor (I2C)
- Plantower PMS5003 PM2.5 particulate sensor (UART)
- Sensirion SGP30 TVOC / eCO2 sensor (I2C)
- 2.4″ ILI9341 colour TFT display (SPI)
- Active buzzer for alerts
- 5 V / 2 A power supply
Step-by-Step Instructions
- Install libraries: SparkFun SCD30, Adafruit SGP30, PMS library by Mariusz Kacki, Adafruit ILI9341.
- Wire I2C bus: SCD30 and SGP30 share I2C (SDA=21, SCL=22). SCD30 VCC = 3.3 V. SGP30 VCC = 3.3 V.
- Wire PMS5003: PMS5003 TX → ESP32 GPIO 16 (RX2). VCC = 5 V (PMS5003 needs 5 V). Set pin to SLEEP mode between readings to extend sensor life.
- Wire TFT: Standard SPI pins. Screen shows four panels: CO2 (ppm), PM2.5 (µg/m³), TVOC (ppb), and a large composite AQI score. Colour transitions from green to red based on thresholds.
- AQI calculation: Implement US EPA AQI formula for PM2.5. For CO2, use custom thresholds: <800 ppm=good, 800–1200=moderate, >1200=poor, >2000=hazardous.
- MQTT alerts: Connect to WiFi and MQTT broker. Publish readings every 60 s. If CO2 > 1200 ppm, publish to alert topic which triggers a Home Assistant notification to phone.
- SGP30 baseline: SGP30 needs a 12-hour burn-in for accurate readings and you should save its baseline values to NVS (Preferences) every hour and restore on startup.
Safety Notes
- High CO2 (above 5000 ppm) indicates dangerously poor ventilation — this is a genuine health hazard, not just a comfort issue. Take the alerts seriously.
- PMS5003 contains a laser — do not open the sensor casing or look into the sensing chamber.
Tips & Troubleshooting
- SCD30 readings stabilise after 30–60 seconds — show a “warming up” message on display during this period.
- If PM2.5 reads zero constantly, check the UART baud rate is 9600 and the TX/RX wires are not crossed.
- Place the sensor away from cooking areas, printers, and direct sunlight for representative background readings.