Close Menu
  • Articles
    • Learn Electronics
    • Product Review
    • Tech Articles
  • Electronics Circuits
    • 555 Timer Projects
    • Op-Amp Circuits
    • Power Electronics
  • Microcontrollers
    • Arduino Projects
    • STM32 Projects
    • AMB82-Mini IoT AI Camera
    • BLE Projects
  • IoT Projects
    • ESP8266 Projects
    • ESP32 Projects
    • ESP32 MicroPython
    • ESP32-CAM Projects
    • LoRa/LoRaWAN Projects
  • Raspberry Pi
    • Raspberry Pi Projects
    • Raspberry Pi Pico Projects
    • Raspberry Pi Pico W Projects
  • Electronics Calculator
Facebook X (Twitter) Instagram
  • About Us
  • Disclaimer
  • Privacy Policy
  • Contact Us
  • Advertise With Us
Facebook X (Twitter) Instagram Pinterest YouTube LinkedIn
How To Electronics
  • Articles
    • Learn Electronics
    • Product Review
    • Tech Articles
  • Electronics Circuits
    • 555 Timer Projects
    • Op-Amp Circuits
    • Power Electronics
  • Microcontrollers
    • Arduino Projects
    • STM32 Projects
    • AMB82-Mini IoT AI Camera
    • BLE Projects
  • IoT Projects
    • ESP8266 Projects
    • ESP32 Projects
    • ESP32 MicroPython
    • ESP32-CAM Projects
    • LoRa/LoRaWAN Projects
  • Raspberry Pi
    • Raspberry Pi Projects
    • Raspberry Pi Pico Projects
    • Raspberry Pi Pico W Projects
  • Electronics Calculator
How To Electronics
Home » Monitor CCS811 CO2 & TVOC on ESP8266/ESP32 Webserver
ESP32 Projects ESP8266 Projects IoT Projects

Monitor CCS811 CO2 & TVOC on ESP8266/ESP32 Webserver

Mamtaz AlamBy Mamtaz AlamUpdated:August 21, 20221 Comment4 Mins Read
Share Facebook Twitter LinkedIn Telegram Reddit WhatsApp
CCS811 ESP8266 ESP32
Share
Facebook Twitter LinkedIn Pinterest Email Reddit Telegram WhatsApp

Overview

In this project, we will interface CCS811 CO2 TVOC Sensor with ESP8266 or ESP32 and monitor the CO2/TVOC Data on Webserver. The CCS811 is a digital gas or Air Quality sensor capable of sensing a wide range of Total Volatile Organic Compounds (TVOC) & equivalent carbon dioxide (eCO2) with metal oxide (MOX) levels. The sensor can be used to determine the Air Quality Index.

Earlier, we used the sensor CCS811 sensor with Arduino to display the CO2 & TVOC value on OLED Display. But instead of OLED display, we will create our own webserver and monitor the air quality remotely from the computer or from Smartphone using any web browser. A web server is a system that runs a website or a webpage & does communication using intercommunication is done using Hypertext Transfer Protocol (HTTP). It’s a program that distributes web pages as they are requisitioned. The basic objective of the web server is to store, process & deliver web pages to the users.

The web server program for CCS811 is stored here in ESP8266 or ESP32 and delivered wirelessly when requested by some IP Address of ESP8266 or ESP32.




Bill of Materials

All the components required for this project can be easily purchased from Amazon. The components purchase link is given below.

S.N.Components NameQuantityPurchase Links
1NodeMCU ESP8266 Board1Amazon | AliExpress
2ESP32 WiFi Module1Amazon | AliExpress
3CCS811 CO2 TVOC Sensor1Amazon | AliExpress
4Connecting Wires10Amazon | AliExpress
5Breadboard1Amazon | AliExpress

CCS811 Air Quality Gas Sensor Module

The CCS811 Air Quality Sensor Breakout Board is a digital gas sensor that senses a wide range of Total Volatile Organic Compounds (TVOCs) along with equivalent carbon dioxide (eCO2) and metal oxide (MOX) levels. The sensor can be used for monitoring Indoor Air Quality. The system can be used with a microcontroller unit (MCU), which includes an Analog-to-Digital converter (ADC) & an I²C interface.

CCS811

The sensor operates between 1.8V to 3.6V hence it can be used with a 3.3V pin of Arduino/ESP8266/ESP32. The default I2C address of the CCS811 is 0x5A whereas some board has an address of 0X5B. Using the CCS811 sensor we can measure eCO2 from 400 to 8192ppm & TVOC from 0 to 1187ppb. To learn more about this sensor, you can follow the CCS811 Datasheet.



Interfacing CCS811 Air Quality Gas Sensor with ESP8266/ESP32

The CCS811 Sensor works on I2C Communication protocol. So let us interface the CCS811 Sensor with ESP8266 & ESP32. In case of NodeMCU ESP8266 Board, the SCL & SDA pin are D1 & D2 respectively. So the connection digaram between CCS811 & ESP8266 is given below.

CCS811 ESP8266

If you are using ESP32 WiFi Module, then the connection diagram is given below. The SCL & SDA pins of ESP32 are GPIO22 & GPIO21 respectively.

CCS811 ESP32

Do not power the sensor with 5V as the sensor can support a maximum of 3.6V only. Do not leave the WAKE pin empty as the controller won’t read the I2C Address. The WAKE pin should always be pulled down to GND.




ESP8266 CCS811 Code/Program

I used the CCS811 library from Maarten Pennings for interfacing CCS811 wiith ESP8266. The library can be downloaded from the following link.

Download: CCS811 Library

The complete source code for ESP8266 CCS811 Webserver is given below. Before uploading the code, make sure to change your WiFi SSID & Password.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <ESP8266WebServer.h>
#include <Wire.h>    // I2C library
#include "ccs811.h"  // CCS811 library
 
 
// Wiring for ESP8266 NodeMCU boards: VDD to 3V3, GND to GND, SDA to D2, SCL to D1, nWAKE to D3 (or GND)
CCS811 ccs811(D3); // nWAKE on D3
 
float val1, val2;
 
const char* ssid = "Alexahome";  // Enter SSID here
const char* password = "loranthus";  //Enter Password here
 
ESP8266WebServer server(80);
 
void setup()
{
  // Enable serial
  Serial.begin(115200);
  Serial.println("");
  Serial.println("setup: Starting CCS811 basic demo");
  Serial.print("setup: ccs811 lib  version: ");
  Serial.println(CCS811_VERSION);
 
  // Enable I2C
  Wire.begin();
 
  // Enable CCS811
  ccs811.set_i2cdelay(50); // Needed for ESP8266 because it doesn't handle I2C clock stretch correctly
  bool ok = ccs811.begin();
  if ( !ok ) Serial.println("setup: CCS811 begin FAILED");
 
  // Print CCS811 versions
  Serial.print("setup: hardware    version: "); Serial.println(ccs811.hardware_version(), HEX);
  Serial.print("setup: bootloader  version: "); Serial.println(ccs811.bootloader_version(), HEX);
  Serial.print("setup: application version: "); Serial.println(ccs811.application_version(), HEX);
 
  // Start measuring
  ok = ccs811.start(CCS811_MODE_1SEC);
  if ( !ok ) Serial.println("setup: CCS811 start FAILED");
 
  Serial.println("Connecting to ");
  Serial.println(ssid);
 
  //connect to your local wi-fi network
  WiFi.begin(ssid, password);
 
  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");
  Serial.println(WiFi.localIP());
 
  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);
 
  server.begin();
  Serial.println("HTTP server started");
}
 
 
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 )
  {
    val1 = eco2;
    val2 = etvoc;
 
    Serial.print("CCS811: ");
    Serial.print("eco2=");
    Serial.print(val1);
    Serial.print(" ppm  ");
 
    Serial.print("etvoc=");
    Serial.print(val2);
    Serial.print(" ppb  ");
    Serial.println();
  }
  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);
  server.handleClient();
}
 
void handle_OnConnect()
{
 
  server.send(200, "text/html", SendHTML(val1, val2));
}
 
void handle_NotFound()
{
  server.send(404, "text/plain", "Not found");
}
 
String SendHTML(float val1, float val2)
{
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<title>Measured Air Quality</title>\n";
  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
  ptr += "p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
  ptr += "</style>\n";
  ptr += "<script>\n";
  ptr += "setInterval(loadDoc,1000);\n";
  ptr += "function loadDoc() {\n";
  ptr += "var xhttp = new XMLHttpRequest();\n";
  ptr += "xhttp.onreadystatechange = function() {\n";
  ptr += "if (this.readyState == 4 && this.status == 200) {\n";
  ptr += "document.body.innerHTML =this.responseText}\n";
  ptr += "};\n";
  ptr += "xhttp.open(\"GET\", \"/\", true);\n";
  ptr += "xhttp.send();\n";
  ptr += "}\n";
  ptr += "</script>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";
  ptr += "<div id=\"webpage\">\n";
  ptr += "<h1>Measured Air Quality</h1>\n";
 
  ptr += "<p>CO2: ";
  ptr += val1;
  ptr += " ppm</p>";
 
  ptr += "<p>TVOC: ";
  ptr += val2;
  ptr += " ppb</p>";
 
  ptr += "</div>\n";
  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}




ESP32 CCS811 Code/Program

The complete source code for Interfacing CCS811 with ESP32 is given below. You can copy the code and upload it to the ESP32 Board. But before that make sure to change your WiFi SSID & Password.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <WebServer.h>
#include <Wire.h>    // I2C library
#include "ccs811.h"  // CCS811 library
 
 
// Wiring for ESP8266 NodeMCU boards: VDD to 3V3, GND to GND, SDA to D2, SCL to D1, nWAKE to D3 (or GND)
CCS811 ccs811(23); // nWAKE on D3
 
float val1, val2;
 
const char* ssid = "Alexahome";  // Enter SSID here
const char* password = "loranthus";  //Enter Password here
 
WebServer server(80);
 
void setup()
{
  // Enable serial
  Serial.begin(115200);
  Serial.println("");
  Serial.println("setup: Starting CCS811 basic demo");
  Serial.print("setup: ccs811 lib  version: ");
  Serial.println(CCS811_VERSION);
 
  // Enable I2C
  Wire.begin();
 
  // Enable CCS811
  ccs811.set_i2cdelay(50); // Needed for ESP8266 because it doesn't handle I2C clock stretch correctly
  bool ok = ccs811.begin();
  if ( !ok ) Serial.println("setup: CCS811 begin FAILED");
 
  // Print CCS811 versions
  Serial.print("setup: hardware    version: "); Serial.println(ccs811.hardware_version(), HEX);
  Serial.print("setup: bootloader  version: "); Serial.println(ccs811.bootloader_version(), HEX);
  Serial.print("setup: application version: "); Serial.println(ccs811.application_version(), HEX);
 
  // Start measuring
  ok = ccs811.start(CCS811_MODE_1SEC);
  if ( !ok ) Serial.println("setup: CCS811 start FAILED");
 
  Serial.println("Connecting to ");
  Serial.println(ssid);
 
  //connect to your local wi-fi network
  WiFi.begin(ssid, password);
 
  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");
  Serial.println(WiFi.localIP());
 
  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);
 
  server.begin();
  Serial.println("HTTP server started");
}
 
 
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 )
  {
    val1 = eco2;
    val2 = etvoc;
 
    Serial.print("CCS811: ");
    Serial.print("eco2=");
    Serial.print(val1);
    Serial.print(" ppm  ");
 
    Serial.print("etvoc=");
    Serial.print(val2);
    Serial.print(" ppb  ");
    Serial.println();
  }
  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);
  server.handleClient();
}
 
void handle_OnConnect()
{
 
  server.send(200, "text/html", SendHTML(val1, val2));
}
 
void handle_NotFound()
{
  server.send(404, "text/plain", "Not found");
}
 
String SendHTML(float val1, float val2)
{
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr += "<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr += "<title>Measured Air Quality</title>\n";
  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
  ptr += "p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
  ptr += "</style>\n";
  ptr += "<script>\n";
  ptr += "setInterval(loadDoc,1000);\n";
  ptr += "function loadDoc() {\n";
  ptr += "var xhttp = new XMLHttpRequest();\n";
  ptr += "xhttp.onreadystatechange = function() {\n";
  ptr += "if (this.readyState == 4 && this.status == 200) {\n";
  ptr += "document.body.innerHTML =this.responseText}\n";
  ptr += "};\n";
  ptr += "xhttp.open(\"GET\", \"/\", true);\n";
  ptr += "xhttp.send();\n";
  ptr += "}\n";
  ptr += "</script>\n";
  ptr += "</head>\n";
  ptr += "<body>\n";
  ptr += "<div id=\"webpage\">\n";
  ptr += "<h1>Measured Air Quality</h1>\n";
 
  ptr += "<p>CO2: ";
  ptr += val1;
  ptr += " ppm</p>";
 
  ptr += "<p>TVOC: ";
  ptr += val2;
  ptr += " ppb</p>";
 
  ptr += "</div>\n";
  ptr += "</body>\n";
  ptr += "</html>\n";
  return ptr;
}



Testing CCS811 ESP8266/ESP32 Webserver

Once you upload the code, the ESP8266/ESP32 Board will try connecting to the WiFi Network. You can open the Serial Monitor and you will see the sensor giving the reading on Serial Monitor.

You can now press the reset button on your ESP8266/ESP32 Board. The IP Address will be displayed on Serial Monitor. Using the same IP Address, paste it on the web browser and hit enter. A beautiful webpage will come with the value of CO2 & TVOC.

You don’t need to refresh the web page again and again to retrieve the sensor value. The code already has the AJAX (Asynchronous Javascript And Xml) script so that we can request data from the server asynchronously (in the background) without refreshing the page.

So this is how you can use CCS811 CO2 TVOC Sensor with ESP8266 or ESP32.

Share. Facebook Twitter Pinterest LinkedIn Tumblr Email Reddit Telegram WhatsApp
Previous ArticleDIY Soil Ph Meter using Soil Ph Sensor & Arduino
Next Article IoT ESP32 Based PM2.5 Monitoring with Air Freshener System

Related Posts

ESP32 Fingerprint Attendance System with Live Web Dashboard

ESP32 Fingerprint Attendance System with Live Web Dashboard

Updated:June 16, 2026
IoT Based PM & Air Quality Monitoring System using ESP32

IoT Based PM & Air Quality Monitoring System using ESP32

Updated:June 14, 2026
DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

Updated:May 10, 20262K
IoT Activity Tracker with ESP32 & Accelerometer Gyroscope

IoT Activity Tracker with ESP32 & Accelerometer/Gyroscope

Updated:May 2, 2026

ESP32 IoT Vehicle Motion Analyzer with MPU6050 & LIS3MDL

Updated:April 27, 20261K
High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

Updated:April 27, 20262K
View 1 Comment

1 Comment

  1. Sujesh G on May 29, 2021 5:02 PM

    how to add an old display to this project? (Monitor CCS811 CO2 & TVOC on ESP8266/ESP32 Webserver)

    Reply

CommentsCancel reply

Latest Posts
ESP32 Fingerprint Attendance System with Live Web Dashboard

ESP32 Fingerprint Attendance System with Live Web Dashboard

June 16, 2026
IoT Based PM & Air Quality Monitoring System using ESP32

IoT Based PM & Air Quality Monitoring System using ESP32

June 14, 2026
DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

May 10, 2026
IoT Activity Tracker with ESP32 & Accelerometer Gyroscope

IoT Activity Tracker with ESP32 & Accelerometer/Gyroscope

May 2, 2026
A Guide to Sourcing Obsolete ICs for Vintage Projects

Beyond AliExpress: A Guide to Sourcing Obsolete ICs for Vintage Projects

April 21, 2026

ESP32 IoT Vehicle Motion Analyzer with MPU6050 & LIS3MDL

April 27, 2026
Building a Smart Sensor Node with a BLE Microcontroller

Building a Smart Sensor Node with a BLE Microcontroller

February 26, 2026
High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

April 27, 2026
Top Posts & Pages
  • ESP32 Fingerprint Attendance System with Live Web Dashboard
    ESP32 Fingerprint Attendance System with Live Web Dashboard
  • IoT AC Energy Meter with PZEM-004T & ESP32 WebServer
    IoT AC Energy Meter with PZEM-004T & ESP32 WebServer
  • Buck Converter: Basics, Working, Design & Application
    Buck Converter: Basics, Working, Design & Application
  • 12V DC to 220V AC Inverter Circuit & PCB
    12V DC to 220V AC Inverter Circuit & PCB
  • IoT Based PM & Air Quality Monitoring System using ESP32
    IoT Based PM & Air Quality Monitoring System using ESP32
  • LD2410 Sensor with ESP32 - Human Presence Detection
    LD2410 Sensor with ESP32 - Human Presence Detection
  • Silicon Controlled Rectifier (SCR): Construction, Working & Applications
    Silicon Controlled Rectifier (SCR): Construction, Working & Applications
  • ECG Graph Monitoring with AD8232 ECG Sensor & Arduino
    ECG Graph Monitoring with AD8232 ECG Sensor & Arduino
Categories
  • Arduino Projects (197)
  • Articles (60)
    • Learn Electronics (19)
    • Product Review (15)
    • Tech Articles (28)
  • Electronics Circuits (46)
    • 555 Timer Projects (21)
    • Op-Amp Circuits (7)
    • Power Electronics (13)
  • IoT Projects (205)
    • ESP32 MicroPython (7)
    • ESP32 Projects (82)
    • ESP32-CAM Projects (15)
    • ESP8266 Projects (76)
    • LoRa/LoRaWAN Projects (22)
  • Microcontrollers (38)
    • AMB82-Mini IoT AI Camera (4)
    • BLE Projects (18)
    • STM32 Projects (19)
  • Raspberry Pi (93)
    • Raspberry Pi Pico Projects (57)
    • Raspberry Pi Pico W Projects (12)
    • Raspberry Pi Projects (24)
Follow Us
  • Facebook
  • Twitter
  • Pinterest
  • Instagram
  • YouTube
About Us

“‘How to Electronics’ is a vibrant community for electronics enthusiasts and professionals. We deliver latest insights in areas such as Embedded Systems, Power Electronics, AI, IoT, and Robotics. Our goal is to stimulate innovation and provide practical solutions for students, organizations, and industries. Join us to transform learning into a joyful journey of discovery and innovation.

Copyright © How To Electronics. All rights reserved.
  • About Us
  • Disclaimer
  • Privacy Policy
  • Contact Us
  • Advertise With Us

Type above and press Enter to search. Press Esc to cancel.

Ad Blocker Enabled!
Ad Blocker Enabled!
Looks like you're using an ad blocker. Please allow ads on our site. We rely on advertising to help fund our site.