This tutorial covers how to monitor indoor air quality using ESP32 and CCS811. In more detail, we want to monitor the air quality using two parameters:
- eCO2 = equivalent Carbon dioxide
- tVoC = total volatile organic compounds
We will measure them using the CCS811 sensor with the ESP32. Moreover, we will show the result using a color LCD display based on ST7755. This is an interesting project because it demonstrated how easy is to build a monitoring system.
Brief introduction to CCS811
The CCS811 sensor is a gas sensor that is able to detect several compounds in the air. It can measure the equivalent CO2 present in the air and the total volatile organic compounds named VOCs. These are a class of compounds that are considered pollutants and sensory irritants. They are produced by a variety of sources including people’s breath. Therefore, we can use the CCS811 with the ESP32 to monitor the air quality. Remember that before using this sensor you should run it for 48 hours and wait at least 20 minutes when you use the sensor.
How to connect the CCS811 to the ESP32 to monitor the air quality
Before using the CCS811 sensor, it is important to know how to connect it to the ESP32. The table below shows the connections:
ESP32 Pins | CCS811 Pins |
GND | GND |
3V3 | Vcc |
GPIO21 | SDA |
GPIO22 | CLK |
Wake | GND |
This device uses a I2C interface.
There are several libraries you can use to read values from CCS811. Anyway, this project uses this library. Now we can monitor the air quality using the ESP32 and CCS811 sensor.
Connecting the RGB display ST7735s to the ESP32
As said before, to display the readings from the CCS811, we use an LCD TFT display based on ST7735s. This device uses an SPI interface. The table below shows how to connect the ST7735s to the ESP32:
ESP32 Pin | TFT LCD ST7735 |
GND | GND |
3V3 | Vcc |
GPIO5 | CS |
GPIO18 | RST |
GPIO2 | RS |
GPIO23 | SDA |
GPIO18 | CLK |
To mange this device, this project uses the Adafruit Library.
More interesting resources:
How to use Tensorflow with ESP32
How to use Websocket with ESP32 to control pins
ESP32 with ESP-Now protocol
How to use ESP32-CAM with TFT display
Project source code with PlatformIO
This code can be used to monitor the quality air using CCS811 and ESP32 and to display the sensor reading to a TFT LCD based on ST7735s:
#include <Arduino.h>
#include <Wire.h> // I2C library
#include "ccs811.h" // CCS811 library
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
#define TFT_SCLK 18 // SPI clock
#define TFT_MOSI 23
#define TFT_CS 5
#define TFT_RST 4
#define TFT_DC 2
CCS811 ccs811(-1);
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
void setup() {
// Enable serial
Serial.begin(9600);
Serial.println("");
// Enable I2C
Wire.begin();
// Enable CCS811
ccs811.set_i2cdelay(50);
bool ok= ccs811.begin();
if( !ok ) Serial.println("setup: CCS811 begin FAILED");
// Start measuring
ok= ccs811.start(CCS811_MODE_1SEC);
if( !ok ) Serial.println("setup: CCS811 start FAILED");
tft.initR(INITR_BLACKTAB);
}
void displayValue(uint16_t eco2, uint16_t etvoc) {
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_GREEN);
tft.setTextSize(2);
tft.setCursor(1,15);
tft.print("CO2 " + String(eco2) + "ppm");
tft.setCursor(1,40);
tft.setTextColor(ST77XX_YELLOW);
tft.setTextSize(2);
tft.print("etVOC " + String(etvoc) + "ppb");
}
void loop() {
// Read
uint16_t eco2, etvoc, errstat, raw;
ccs811.read(&eco2,&etvoc,&errstat,&raw);
// Print measurement results based on status
if( errstat==CCS811_ERRSTAT_OK ) {
displayValue(eco2, etvoc);
} else if( errstat==CCS811_ERRSTAT_OK_NODATA ) {
Serial.println("CCS811: waiting for (new) data");
} else if( errstat & CCS811_ERRSTAT_I2CFAIL ) {
Serial.println("CCS811: I2C error");
} else {
Serial.print("CCS811: errstat="); Serial.print(errstat,HEX);
Serial.print("="); Serial.println( ccs811.errstat_str(errstat) );
}
// Wait
delay(1000);
}
Code language: C++ (cpp)
while the platformio.ini file should be like:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
upload_port = /dev/tty.SLAB_USBtoUART
lib_deps =
# RECOMMENDED
# Accept new functionality in a backwards compatible manner and patches
adafruit/Adafruit GFX Library @ ^1.10.5
adafruit/Adafruit ST7735 and ST7789 Library @ ^1.6.0
adafruit/Adafruit BusIO @ ^1.7.2
Code language: PHP (php)
How to read CO2 and tVoc using CCS811
This a brief explanation of the code above. The first thing is initiliazing the class that will handle the sensor:
CCS811 ccs811(-1);
Next, the code connect the ESP32 to th CCS811 sensor in the setup()
method:
// Enable CCS811
ccs811.set_i2cdelay(50);
bool ok= ccs811.begin();
if( !ok ) Serial.println("setup: CCS811 begin FAILED");
Code language: JavaScript (javascript)
and finally, it selects how often the sensor reads the data:
// Start measuring
ok= ccs811.start(CCS811_MODE_1SEC);
if( !ok ) Serial.println("setup: CCS811 start FAILED");
Code language: JavaScript (javascript)
while in the loop()
method, we read the CO2 and tVOC values:
uint16_t eco2, etvoc, errstat, raw;
ccs811.read(&eco2,&etvoc,&errstat,&raw);
Code language: CSS (css)
How to display the CO2 and tVoC using TFT LCD display ST7735
In this last step, we will visualize the CO2 and tVOC values using a TFT LCD display. To handle this display, the code uses the Adafruit library. Therefore, the code defines the pins used and the class that handles the display:
#define TFT_SCLK 18 // SPI clock
#define TFT_MOSI 23
#define TFT_CS 5
#define TFT_RST 4
#define TFT_DC 2
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
Code language: PHP (php)
next, in the setup() method the code initializes the display:
tft.initR(INITR_BLACKTAB);
Code language: CSS (css)
Finally, using this piece of code, we visualize the results:
void displayValue(uint16_t eco2, uint16_t etvoc) {
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_GREEN);
tft.setTextSize(2);
tft.setCursor(1,15);
tft.print("CO2 " + String(eco2) + "ppm");
tft.setCursor(1,40);
tft.setTextColor(ST77XX_YELLOW);
tft.setTextSize(2);
tft.print("etVOC " + String(etvoc) + "ppb");
}
Code language: C++ (cpp)
Below the final result:

Wrapping up
At the end of this post, we have covered how to monitor the air quality in your room using the ESP32 and a CCS811 sensor. Using this sensor, we measure the CO2 e tVOC values and we can recognize if this values are over the thresholds.