Temperature, humidity and air

ENS160 with ESP32

The CCS811 that many old tutorials use has been discontinued, and DFRobot and Adafruit both point to the ENS160 as the replacement. It reports an air quality index, TVOC and eCO2 over I2C. Adafruit's listing gives about 3 minutes of warm-up, and under an hour for full start-up.

The 'e' in eCO2 is the important letter. It stands for equivalent: the chip estimates a CO2 level from gases it senses, and it does not measure CO2 itself. An empty room with a solvent smell can show high eCO2, and a closed bedroom full of real CO2 may not. For a ventilation decision based on real CO2, use an SCD40. The ENS160 is good at showing that air has got worse, for example after cooking or painting.

Readings improve with temperature and humidity compensation, so pairing it with an AHT20 or SHT31 on the same bus is common. Adafruit notes that this needs an external humidity sensor. The address is 0x53 on Adafruit's board. Other boards may use 0x52, so scan the bus. Some modules have a regulator and others do not, so read the board's marking before connecting 5 V. The example writes the operating mode and reads the registers directly, with no library.

ENS160 wiring diagram for ESP32
Wiring diagram drawn by LCD Ultra Pro.

Specifications

OutputsAQI, TVOC, eCO2
Warm-upAbout 3 minutes, under 1 h start-up
InterfaceI2C
I2C address0x53, some boards 0x52
CompensationTakes temperature and humidity input

Power and logic levels

3.3 V: check your module first

SupplyChip VDD 1.71–1.98 V, I/O up to 3.6 V
Signal levelDepends on the board
On an ESP32Use a board with its own 1.8 V regulator. A bare chip must not get 3.3 V on VDD.

ESP32 pins, including those on a display board's connectors, work at 3.3 V and are not 5 V tolerant. Modules differ, so if in doubt, measure the signal before you connect it.

Wiring

ENS160Connect toNote
VIN / VCC3V3
GNDGND
SDAGPIO 8Any free pin, set in Wire.begin()
SCLGPIO 9Any free pin, set in Wire.begin()

Arduino code

#include <Wire.h>

const int SDA_PIN = 8, SCL_PIN = 9;
const uint8_t ADDR = 0x53;            // 0x52 on some boards

uint16_t read16(uint8_t reg) {        // low byte first
  Wire.beginTransmission(ADDR);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(ADDR, (uint8_t)2);
  uint16_t v = Wire.read();
  return v | (Wire.read() << 8);
}

void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_PIN, SCL_PIN);
  Serial.printf("Part ID 0x%04X\n", read16(0x00));   // expect 0x0160
  Wire.beginTransmission(ADDR);
  Wire.write(0x10); Wire.write(0x02); // standard gas sensing mode
  Wire.endTransmission();
}

void loop() {
  uint8_t aqi = read16(0x21) & 0x07;
  Serial.printf("AQI %d  TVOC %u ppb  eCO2 %u ppm\n", aqi, read16(0x22), read16(0x24));
  delay(2000);
}

No extra library needed. Compiled for ESP32-S3 with arduino-esp32 3.x. Not yet tested by us on a physical sensor. Change the pins to match your board.

On a display

Read the value in your sketch and pass it to a label, or send it over MQTT and show it with an MQTT value in the editor.

Design a display for ENS160

Boards with a ready connector

Only boards whose connectors we have surveyed. Others may still work on free GPIOs.

Elecrow CrowPanel ESP32 HMI 2.4"I2C port: SDA 22, SCL 21Not shared with the touch controller (it is on SPI) — free for sensors
Elecrow CrowPanel ESP32 HMI 2.8"I2C port: SDA 22, SCL 21Not shared with the touch controller (it is on SPI) — free for sensors
Elecrow CrowPanel ESP32 HMI 3.5"I2C port: SDA 22, SCL 21Not shared with the touch controller (it is on SPI) — free for sensors
Elecrow CrowPanel ESP32-S3 HMI 5.0"I2C port: SDA 19, SCL 20Same I2C bus as the GT911 touch (0x14 / 0x5D) and, on V3.0 boards, the PCA9557 touch-reset expander (0x18)
Elecrow CrowPanel ESP32-S3 HMI 7.0"I2C port: SDA 19, SCL 20Same I2C bus as the GT911 touch (0x14 / 0x5D) and, on V3.0 boards, the PCA9557 touch-reset expander (0x18)
LilyGO T-Display-S3-Pro 2.33"QWIIC RIGHT: SDA 5, SCL 6I2C only — same bus as the touch, the PMU (SY6970) and the light sensor
M5Stack AtomS3 0.85"Bottom I2C pins: SDA 38, SCL 39Same I2C bus as the built-in IMU (MPU6886, 0x68)
Makerfabs MaTouch ESP32-S3 Rotary IPS 2.1 RoundMabee I2C (J1): SDA 17, SCL 18Same I2C bus as the touch controller (CST826)
Makerfabs MaTouch ESP32-S3 Parallel TFT 4.3"Mabee I2C: SDA 17, SCL 18Same I2C bus as the touch controller (GT911)
Makerfabs MaTouch ESP32-S3 Parallel TFT with Touch 5.0"Mabee I2C: SDA 17, SCL 18Same I2C bus as the touch controller (GT911)
Makerfabs MaTouch ESP32-S3 Parallel TFT with Touch 7.0"Mabee I2C: SDA 17, SCL 18Same I2C bus as the touch controller (GT911)
Sunton ESP32-4827S043R/C 4.3"I2C header (P3): SDA 19, SCL 20Same I2C bus as the GT911 touch controller. P3 also carries GPIO 17 / 18.
Sunton ESP32-8048S043C 4.3"I2C header (P3): SDA 19, SCL 20Same I2C bus as the GT911 touch controller. P3 also carries GPIO 17 / 18.
Sunton ESP32-8048S050C 5.0"I2C header (P3): SDA 19, SCL 20Same I2C bus as the GT911 touch controller. P3 also carries GPIO 17 / 18.
Sunton ESP32-8048S070C 7.0"I2C header (P3): SDA 19, SCL 20Same I2C bus as the GT911 touch controller. P3 also carries GPIO 17 / 18.
Waveshare ESP32-S3 Touch LCD 2.1" roundI2C connector: SDA 15, SCL 7Same I2C bus as the touch controller, the IO expander, the RTC and the IMU (addresses 0x15/0x5D, 0x20, 0x51, 0x6B, 0x7E taken)
Waveshare ESP32-S3 Touch LCD 2.8"I2C connector: SDA 11, SCL 10Same I2C bus as the RTC and the IMU (0x51, 0x6B, 0x7E taken) — the touch has its own bus
Waveshare ESP32-S3 Touch LCD 2.8" Type BI2C connector: SDA 15, SCL 7Same I2C bus as the touch controller, the IO expander, the RTC and the IMU (addresses 0x15/0x5D, 0x20, 0x51, 0x6B, 0x7E taken)
Waveshare ESP32-S3-Touch-LCD-2.8CI2C connector: SDA 15, SCL 7Same I2C bus as the touch controller, the IO expander, the RTC and the IMU (addresses 0x15/0x5D, 0x20, 0x51, 0x6B, 0x7E taken)
Waveshare ESP32-S3-LCD-7BI2C connector (H1): SDA 8, SCL 9Same I2C bus as the touch controller (GT911) and the IO expander (CH422G)

Good to know

  • eCO2 is an estimate, not real CO2.
  • Allow warm-up time.
  • Add a humidity sensor for compensation.
  • Check the address and supply on your module.

What it is good for

  • Air quality trend displays
  • Kitchen and workshop monitors
  • Replacing a CCS811

FAQ

Does the ENS160 measure real CO2?

No. eCO2 is calculated. Use an SCD40 for real CO2.

Is the ENS160 a CCS811 replacement?

Yes, vendors list it as the replacement, but code and registers differ.

Why are the first values wrong?

The sensor needs a warm-up period.

Sources

Related parts

Use this information at your own risk. It is for general guidance only: the example code compiles, but it has not been tested on every part, and modules differ between sellers. Check the manufacturer's data before you build. Product names belong to their owners, and LCD Ultra Pro is not affiliated with them. See our Terms.