Hi all,
I wanted to share a custom text sensor I made for the CCS811 sensor using ESPHome.
The CCS811 Air Quality Breakout is a digital gas sensor solution that senses a wide range of Total Volatile Organic Compounds (TVOCs) and CO2. You can also buy versions which also include a HDC1080 temperature and humidity sensor. Temperature and humidity can also be used to improve the CCS811’s internal calculations.
While having these measurements is great and all, I wanted a more human friendly approach in knowing the overall indoor air quality without having to study multiple graphs and look up threshold values. Other sensors such as the BME680 report such a value based on the multiple readings. So I decided to create my own using ESPHome templating.
The idea is based on this PDF http://www.iaquk.org.uk/ESW/Files/IAQ_Rating_Index.pdf for indoor air quality (IAQ) values. In my implementation it gives points (1-5) for certain thresholds of the TVOC, CO2 and Humidity values. Points combined from these sensors are then in its turn transformed to human readable text.
You need to start by setting up a basic node in ESPHome. If you do not know how to do that, please read this page first: https://esphome.io/guides/getting_started_hassio.html.
Then you can connect the CCS811 breakout module to your I2C bus. You also need a temperature and humidity sensor. If you are not using the CCS811 HDC1080 combo module, you probably need to change the code.
No temperature and humidity sensor connected to your node?
With ESPHome it is even possible to import the state of other temperature / humidity sensors from Home Assistant! https://esphome.io/components/sensor/homeassistant.html
Important: you also need to change the baseline
value of the CCS811 sensor. Check the documentation on how to calibrate your own baseline https://esphome.io/components/sensor/ccs811.html#calibrating-baseline. If you just connected the CCS811 sensor it is also advised to take a 48 hour “burn-in” period before you read out the baseline and start using the sensor.
i2c:
sda: 21
scl: 22
scan: True
globals:
- id: iaq_index
type: int
restore_value: no
initial_value: '0'
sensor:
- platform: hdc1080
temperature:
name: "Livingroom Temperature"
id: temp
humidity:
name: "Livingroom Humidity"
id: humi
address: 0x40
update_interval: 60s
- platform: ccs811
eco2:
name: "Livingroom eCO2"
id: eco2
tvoc:
name: "Livingroom TVOC"
id: tvoc
temperature: temp
humidity: humi
baseline: 0xD3BE
address: 0x5A
update_interval: 60s
text_sensor:
- platform: template
name: "Livingroom IAQ"
icon: "mdi:air-filter"
lambda: |-
id(iaq_index) = 0;
/*
* Transform indoor humidity values to IAQ points according to Indoor Air Quality UK:
* http://www.iaquk.org.uk/
*/
if (id(humi).state < 10 or id(humi).state > 90) {
id(iaq_index) += 1;
}
else if (id(humi).state < 20 or id(humi).state > 80) {
id(iaq_index) += 2;
}
else if (id(humi).state < 30 or id(humi).state > 70) {
id(iaq_index) += 3;
}
else if (id(humi).state < 40 or id(humi).state > 60) {
id(iaq_index) += 4;
}
else if (id(humi).state >= 40 and id(humi).state <= 60) {
id(iaq_index) += 5;
}
/*
* Transform eCO2 values to IAQ points according to Indoor Air Quality UK:
* http://www.iaquk.org.uk/
*/
if (id(eco2).state <= 600) {
id(iaq_index) += 5;
}
else if (id(eco2).state <= 800) {
id(iaq_index) += 4;
}
else if (id(eco2).state <= 1500) {
id(iaq_index) += 3;
}
else if (id(eco2).state <= 1800) {
id(iaq_index) += 2;
}
else if (id(eco2).state > 1800) {
id(iaq_index) += 1;
}
/*
* Transform TVOC values to IAQ points according to German environmental guidelines:
* https://www.repcomsrl.com/wp-content/uploads/2017/06/Environmental_Sensing_VOC_Product_Brochure_EN.pdf
*/
if (id(tvoc).state <= 65) {
id(iaq_index) += 5;
}
else if (id(tvoc).state <= 220) {
id(iaq_index) += 4;
}
else if (id(tvoc).state <= 660) {
id(iaq_index) += 3;
}
else if (id(tvoc).state <= 2200) {
id(iaq_index) += 2;
}
else if (id(tvoc).state > 2200) {
id(iaq_index) += 1;
}
/*
* Transform IAQ index to human readable text according to Indoor Air Quality UK:
* http://www.iaquk.org.uk/
*/
ESP_LOGD("main", "Current IAQ index %d", id(iaq_index));
if (id(iaq_index) <= 6) {
return {"Unhealty"};
}
else if (id(iaq_index) <= 9) {
return {"Poor"};
}
else if (id(iaq_index) <= 12) {
return {"Moderate"};
}
else if (id(iaq_index) <= 14) {
return {"Good"};
}
else if (id(iaq_index) > 14) {
return {"Excellent"};
}
return {};
update_interval: 60s