ESP32 ENS160 Digital Metal-Oxide Multi-Gas Sensor
The ENS160 is a digital MOX gas sensor optimized for indoor air quality monitoring. It provides accurate measurements of TVOC and eCO₂ levels, along with AQIs, making it ideal for applications in building automation, HVAC systems, and air purifiers. The sensor supports both I²C and SPI interfaces, allowing for flexible integration into various microcontroller platforms.
Jump to Code Examples
Quick Links
ENS160 Price
About ENS160 Digital Metal-Oxide Multi-Gas Sensor
The ENS160 is a digital metal-oxide (MOX) multi-gas sensor designed for accurate detection of indoor air quality. It measures total volatile organic compounds (TVOC) and equivalent CO₂ (eCO₂) levels, providing comprehensive air quality indices (AQIs). Compared to the CCS811, the ENS160 offers enhanced selectivity and accuracy due to its four independent MOX sensor elements, each with its own hotplate control. This design allows for superior detection of a wide range of gases, including ethanol, toluene, hydrogen, and nitrogen dioxide.ENS160 Sensor Technical Specifications
Below you can see the ENS160 Digital Metal-Oxide Multi-Gas Sensor Technical Specifications. The sensor is compatible with the ESP32, operating within a voltage range suitable for microcontrollers. For precise details about its features, specifications, and usage, refer to the sensor’s datasheet.
- Protocol: I2C
- Measurement Parameters: TVOC, eCO₂, AQI
- Operating Voltage: 1.71V to 1.98V (VDD); 1.71V to 3.6V (VDDIO)
- Interface: I²C, SPI
- Operating Temperature: -40°C to 85°C
- Operating Humidity: 5% to 95% RH (non-condensing)
- Package: 3 x 3 x 0.9 mm LGA
ENS160 Sensor Pinout
Below you can see the pinout for the ENS160 Digital Metal-Oxide Multi-Gas Sensor. The VCC
pin is used to supply power to the sensor, and it typically requires 3.3V or 5V (refer to the datasheet for specific voltage requirements). The GND
pin is the ground connection and must be connected to the ground of your ESP32!
The ENS160 pinout is as follows:
- VIN: Power supply input (1.71V to 1.98V).
- GND: Ground connection.
- SDA: I²C data line.
- SCL: I²C clock line.
- INT: Interrupt output (optional).
- WAKE: Wake-up control input.
- ADDR: I²C address selection.
- CS: Chip select for SPI interface (tie to GND for I²C mode).
ENS160 Wiring with ESP32
Below you can see the wiring for the ENS160 Digital Metal-Oxide Multi-Gas Sensor with the ESP32. Connect the VCC pin of the sensor to the 3.3V pin on the ESP32 or external power supply for power and the GND pin of the sensor to the GND pin of the ESP32. Depending on the communication protocol of the sensor (e.g., I2C, SPI, UART, or analog), connect the appropriate data and clock or signal pins to compatible GPIO pins on the ESP32, as shown below in the wiring diagram.
VIN
to the 3.3V or 5V power supply (depending on the breakout board specifications), GND
to ground, SDA
to the microcontroller's SDA pin, and SCL
to the microcontroller's SCL pin. Ensure that appropriate pull-up resistors are present on the I²C lines if not already provided on the breakout board. For SPI communication, additional connections and configurations are required as per the sensor's datasheet.Code Examples
Below you can find code examples of ENS160 Digital Metal-Oxide Multi-Gas Sensor with ESP32 in several frameworks:
ESP32 ENS160 Arduino IDE Code Example
Fill in your main
Arduino IDE sketch file with the following code to use the ENS160 Digital Metal-Oxide Multi-Gas Sensor:
#include <Wire.h>
#include "ScioSense_ENS160.h"
ScioSense_ENS160 ens160(ENS160_I2CADDR_1); // I²C address 0x53
void setup() {
Serial.begin(115200);
Wire.begin();
if (!ens160.begin()) {
Serial.println("Failed to initialize ENS160 sensor!");
while (1);
}
}
void loop() {
ens160.readData();
Serial.print("eCO2: ");
Serial.print(ens160.geteCO2());
Serial.print(" ppm, TVOC: ");
Serial.print(ens160.getTVOC());
Serial.print(" ppb, AQI: ");
Serial.println(ens160.getAQI());
delay(1000);
}
This Arduino sketch interfaces with the ENS160 sensor over I²C. It initializes the sensor using the ScioSense_ENS160
library with the I²C address set to 0x53. In the setup()
function, the sensor is initialized, and an error message is displayed if initialization fails. The loop()
function reads eCO₂, TVOC, and AQI data from the sensor every second and prints the values to the Serial Monitor.
Connect your ESP32 to your computer via a USB cable, Ensure the correct Board and Port are selected under Tools, Click the "Upload" button in the Arduino IDE to compile and upload the code to your ESP32.
ESP32 ENS160 ESP-IDF Code ExampleExample in Espressif IoT Framework (ESP-IDF)
If you're using ESP-IDF to work with the ENS160 Digital Metal-Oxide Multi-Gas Sensor, here's how you can set it up and read data from the sensor. Fill in this code in the main
ESP-IDF file:
#include <stdio.h>
#include "driver/i2c.h"
#include "ens160.h"
#define I2C_MASTER_SCL_IO 22
#define I2C_MASTER_SDA_IO 21
#define I2C_MASTER_NUM I2C_NUM_0
#define I2C_MASTER_FREQ_HZ 100000
void app_main(void) {
i2c_config_t i2c_config = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ
};
i2c_param_config(I2C_MASTER_NUM, &i2c_config);
i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER, 0, 0, 0);
ens160_t sensor;
ens160_init(&sensor, I2C_MASTER_NUM, ENS160_I2C_ADDRESS_1);
printf("Initializing ENS160\n");
if (ens160_start(&sensor) != ENS160_OK) {
printf("Failed to start ENS160 sensor\n");
return;
}
while (1) {
uint16_t eco2, tvoc;
uint8_t aqi;
if (ens160_read_data(&sensor, &eco2, &tvoc, &aqi) == ENS160_OK) {
printf("eCO2: %d ppm, TVOC: %d ppb, AQI: %d\n", eco2, tvoc, aqi);
} else {
printf("Error reading data from ENS160\n");
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
This ESP-IDF example interfaces with the ENS160 sensor over I²C using SDA (GPIO21) and SCL (GPIO22). The I²C bus is initialized with the appropriate configuration, and the ENS160 is configured to start data acquisition. In the main loop, eCO₂, TVOC, and AQI values are read every second and printed to the console. Any errors during communication are handled with error messages.
Update the I2C pins (I2C_MASTER_SDA_IO
and I2C_MASTER_SCL_IO
) to match your ESP32 hardware setup, Use idf.py build to compile the project, Use idf.py flash to upload the code to your ESP32.
ESP32 ENS160 ESPHome Code Example
Fill in this configuration in your ESPHome YAML configuration file (example.yml
) to integrate the ENS160 Digital Metal-Oxide Multi-Gas Sensor
i2c:
sda: GPIO21
scl: GPIO22
sensor:
- platform: ens160
eco2:
name: "eCO2"
tvoc:
name: "TVOC"
aqi:
name: "Air Quality Index"
address: 0x53
update_interval: 1s
The ESPHome configuration sets up I²C communication with the ENS160 sensor using SDA (GPIO21) and SCL (GPIO22). The sensor
platform fetches eCO₂, TVOC, and AQI data at 1-second intervals. The data is displayed as named sensors: 'eCO2', 'TVOC', and 'Air Quality Index'. The I²C address is set to 0x53.
Upload this code to your ESP32 using the ESPHome dashboard or the esphome run
command.
ESP32 ENS160 PlatformIO Code Example
For PlatformIO, make sure to configure the platformio.ini
file with the appropriate environment and libraries, and then proceed with the code.
Configure platformio.ini
First, your platformio.ini
should look like below. You might need to include some libraries as shown. Make sure to change the board to your ESP32:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
ESP32 ENS160 PlatformIO Example Code
Write this code in your PlatformIO project under the src/main.cpp
file to use the ENS160 Digital Metal-Oxide Multi-Gas Sensor:
#include <Wire.h>
#include "ScioSense_ENS160.h"
ScioSense_ENS160 ens160(ENS160_I2CADDR_1); // I²C address 0x53
void setup() {
Serial.begin(115200);
Wire.begin(21, 22); // SDA: GPIO21, SCL: GPIO22
if (!ens160.begin()) {
Serial.println("Failed to initialize ENS160 sensor!");
while (1);
}
}
void loop() {
ens160.readData();
Serial.print("eCO2: ");
Serial.print(ens160.geteCO2());
Serial.print(" ppm, TVOC: ");
Serial.print(ens160.getTVOC());
Serial.print(" ppb, AQI: ");
Serial.println(ens160.getAQI());
delay(1000);
}
This PlatformIO example interfaces with the ENS160 sensor using SDA (GPIO21) and SCL (GPIO22). The sensor is initialized with the I²C address set to 0x53. eCO₂, TVOC, and AQI values are retrieved in the loop()
and printed to the Serial Monitor every second.
Upload the code to your ESP32 using the PlatformIO "Upload" button in your IDE or the pio run --target upload
command.
ESP32 ENS160 MicroPython Code Example
Fill in this script in your MicroPython main.py file (main.py
) to integrate the ENS160 Digital Metal-Oxide Multi-Gas Sensor with your ESP32.
from machine import I2C, Pin
import time
# ENS160 I2C address
ENS160_ADDR = 0x53
# Register addresses
DATA_ECO2 = 0x22
DATA_TVOC = 0x24
DATA_AQI = 0x26
# Initialize I2C
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
# Function to read 16-bit register
def read_register(addr, reg):
data = i2c.readfrom_mem(addr, reg, 2)
return (data[0] << 8) | data[1]
while True:
eco2 = read_register(ENS160_ADDR, DATA_ECO2)
tvoc = read_register(ENS160_ADDR, DATA_TVOC)
aqi = i2c.readfrom_mem(ENS160_ADDR, DATA_AQI, 1)[0]
print(f"eCO2: {eco2} ppm, TVOC: {tvoc} ppb, AQI: {aqi}")
time.sleep(1)
This MicroPython script interfaces with the ENS160 sensor over I²C using SDA (GPIO21) and SCL (GPIO22). It reads eCO₂, TVOC, and AQI data by accessing the corresponding registers. The read_register()
function retrieves 16-bit data from the sensor. The main loop continuously fetches and prints the sensor values every second.
Upload this code to your ESP32 using a MicroPython-compatible IDE, such as Thonny, uPyCraft, or tools like ampy
.
Conclusion
We went through technical specifications of ENS160 Digital Metal-Oxide Multi-Gas Sensor, its pinout, connection with ESP32 and ENS160 Digital Metal-Oxide Multi-Gas Sensor code examples with Arduino IDE, ESP-IDF, ESPHome and PlatformIO.