Indoor air quality is not just about CO₂. Volatile organic compounds (VOCs) from cleaning products, furniture, paints, cooking, and people can significantly affect comfort and health. The SGP40 is a modern VOC sensor designed specifically for indoor air quality applications, and when combined with an ESP32 and Home Assistant, it becomes a powerful monitoring tool.
This guide shows how to integrate the SGP40 VOC sensor with ESP32 and Home Assistant, using both ESPHome and MQTT.
1. What the SGP40 Measures
The SGP40 does not directly output “ppm” like CO₂ sensors. Instead, it produces a VOC index, typically in the range:
- 0–100: Excellent air quality
- 100–200: Normal indoor air
- >200: Polluted / stuffy / cooking / chemicals
The exact scale depends on the library or ESPHome implementation, but the general principle is the same: higher index = worse air quality.
2. Hardware Required
- ESP32 DevKit
- SGP40 VOC sensor breakout
- Jumper wires
- USB cable
- (Optional) Temperature/humidity sensor (e.g. SHT45) for compensated readings
- (Optional) Ventilated enclosure
3. Wiring the ESP32 to SGP40
The SGP40 uses I2C.
I2C Wiring
ESP32 → SGP40
3.3V → VIN
GND → GND
GPIO21 → SDA
GPIO22 → SCL
If another I2C sensor (BME280, SHT45, etc.) is already connected, the SGP40 can share the same SDA/SCL lines.
4. Method 1 – ESPHome Integration
ESPHome provides native support for SGP40 through the sgp4x platform in newer builds (check ESPHome docs for exact availability). A typical configuration exposes a VOC index sensor.
4.1 Basic ESPHome YAML for SGP40
esphome:
name: esp32-sgp40
platform: ESP32
board: esp32dev
wifi:
ssid: "YOUR_WIFI"
password: "YOUR_PASSWORD"
logger:
api:
ota:
i2c:
sda: 21
scl: 22
scan: true
sensor:
- platform: sgp4x
voc_index:
name: "SGP40 VOC Index"
update_interval: 10s
This configuration:
- Scans the I2C bus
- Reads the VOC index every 10 seconds
- Exposes a
sensor.sgp40_voc_indexentity in Home Assistant automatically
5. Method 2 – MQTT Integration
For setups that use MQTT for all ESP32 nodes, the SGP40 can be read via Arduino code and published as JSON to Home Assistant.
5.1 Home Assistant configuration.yaml – MQTT VOC Sensor
Add under the existing mqtt: section:
mqtt:
sensor:
- name: "Living Room VOC Index"
state_topic: "home/air/voc"
value_template: "{{ value_json.voc_index }}"
unit_of_measurement: "index"
Home Assistant will then read messages published as JSON on the topic home/air/voc.
6. ESP32 Arduino MQTT Code for SGP40
The following sketch:
- Connects the ESP32 to WiFi
- Reads SGP40 VOC index
- Publishes JSON to the MQTT broker
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include "SensirionI2CSgp40.h"
#define WIFI_SSID "YOUR_WIFI"
#define WIFI_PASS "YOUR_PASSWORD"
#define MQTT_SERVER "192.168.0.10"
WiFiClient espClient;
PubSubClient client(espClient);
SensirionI2CSgp40 sgp40;
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
sgp40.begin(Wire);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(500);
client.setServer(MQTT_SERVER, 1883);
}
void loop() {
if (!client.connected()) {
while (!client.connected()) client.connect("ESP32_SGP40");
}
uint16_t vocIndex = 0;
uint16_t srawVoc = 0; // raw value, if needed
// Simplified reading: some libs provide vocIndex directly,
// in others you calculate from srawVoc via algorithm.
// Example assuming direct vocIndex read:
sgp40.measureRawSignal(srawVoc);
// Here, a VOC algorithm would convert srawVoc → vocIndex.
// For illustration, assume vocIndex = srawVoc / 10:
vocIndex = srawVoc / 10;
String json = "{";
json += "\"voc_index\":" + String(vocIndex);
json += "}";
client.publish("home/air/voc", json.c_str());
client.loop();
delay(10000);
}
Note: Real-world implementations use Sensirion’s official VOC index algorithm on raw values (srawVoc). Library examples usually show how to compute this properly; the above is simplified for structure and MQTT integration.
7. Home Assistant Dashboard Example
A simple way to visualize the VOC index:
type: vertical-stack
cards:
- type: sensor
entity: sensor.living_room_voc_index
- type: history-graph
entities:
- sensor.living_room_voc_index
hours_to_show: 24
For a more intuitive display, thresholds can be added using custom cards (e.g. colored gauges).
8. Typical VOC Index Interpretation
While the precise mapping depends on implementation, a general guideline:
- 0–100 → Excellent
- 100–200 → Normal
- 200–400 → Poor
- >400 → Very poor
These levels can be used to drive automations.
9. Example Automations
9.1 Send a notification when VOC index is high
automation:
- alias: "High VOC Alert"
trigger:
- platform: numeric_state
entity_id: sensor.living_room_voc_index
above: 200
action:
- service: notify.mobile_app
data:
message: "VOC levels are high. Consider opening a window or reducing chemicals."
9.2 Automatically turn on ventilation fan
- alias: "Ventilation on High VOC"
trigger:
- platform: numeric_state
entity_id: sensor.living_room_voc_index
above: 250
action:
- service: fan.set_percentage
target:
entity_id: fan.cabinet_fan
data:
percentage: 100
9.3 Scale fan speed based on VOC index
- alias: "Dynamic Ventilation by VOC"
trigger:
- platform: state
entity_id: sensor.living_room_voc_index
action:
- choose:
- conditions: "{{ states('sensor.living_room_voc_index') | float > 350 }}"
sequence:
- service: fan.set_percentage
target:
entity_id: fan.cabinet_fan
data:
percentage: 100
- conditions: "{{ states('sensor.living_room_voc_index') | float > 250 }}"
sequence:
- service: fan.set_percentage
target:
entity_id: fan.cabinet_fan
data:
percentage: 70
- conditions: "{{ states('sensor.living_room_voc_index') | float > 150 }}"
sequence:
- service: fan.set_percentage
target:
entity_id: fan.cabinet_fan
data:
percentage: 40
default:
- service: fan.turn_off
target:
entity_id: fan.cabinet_fan
10. Combining VOC with Other Sensors
The SGP40 works best when combined with:
- Temperature sensor (e.g. SHT45)
- Humidity sensor
- CO₂ sensor (SCD30 / SCD41)
A complete air quality setup might include:
- CO₂ levels
- VOC index
- Temperature
- Humidity
These can be grouped on a single Home Assistant dashboard for a full indoor air quality overview.
11. Troubleshooting
Sensor not detected
- Check I2C wiring (SDA/SCL pins)
- Make sure 3.3V is used, not 5V
- Enable
scan: truein ESPHome’si2c:section
VOC index stuck or unnatural
- New sensors need burn-in time (several hours)
- Avoid enclosing the sensor in an airtight box
- Keep away from direct airflow from fans or windows
Values look noisy
- Use longer
update_interval(10–60 seconds) - Apply Home Assistant
statisticsorfiltersensors for smoothing
Keywords
esp32 sgp40
home assistant voc sensor
esphome sgp40
mqtt voc index esp32
indoor air quality esp32
sgp40 esp32 wiring
voc index home assistant
esp32 air quality monitoring