ESP32 ENS160 Digital Metal-Oxide Multi-Gas Sensor
Overview
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.
About ENS160 Digital Metal-Oxide Multi-Gas Sensor
The ENS160 is a high-precision metal-oxide (MOX) multi-gas sensor designed for indoor air quality monitoring. It detects total volatile organic compounds (TVOC) and equivalent CO₂ (eCO₂) levels, providing real-time air quality indices (AQIs).
⚡ Key Features
- Multi-Gas Detection – Measures TVOC, eCO₂, and gases like ethanol, toluene, hydrogen, and nitrogen dioxide.
- Four Independent MOX Sensor Elements – Each with its own hotplate control for enhanced selectivity and accuracy.
- Superior Air Quality Monitoring – More precise than standard sensors like the CCS811, with improved gas selectivity.
- I²C Communication – Seamless integration with ESP32, Arduino, and other microcontrollers.
With its advanced detection capabilities, the ENS160 is ideal for HVAC systems, smart home air monitoring, and industrial applications. 🚀
The ENS160 features on-chip algorithms for humidity and temperature compensation, baseline management, and calculation of AQIs, reducing the need for external processing. It supports both I²C and SPI interfaces, facilitating easy integration into various applications such as building automation, smart home systems, HVAC, and air purifiers.
Where to Buy
Prices are subject to change. We earn from qualifying purchases as an Amazon Associate.
Technical Specifications
Pinout Configuration
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).
Wiring with ESP32
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.Troubleshooting Guide
Common Issues
💻 Compilation Error: 'TwoWire::begin(uint8_t&, uint8_t&)'
Issue: When compiling code for the ENS160 sensor, the following error occurs: no matching function for call to 'TwoWire::begin(uint8_t&, uint8_t&)'
.
Possible causes include the sensor library attempting to call a non-standard Wire.begin()
function with two arguments, which is not supported by all platforms.
Solution: Modify the library code to use the standard Wire.begin()
function without arguments. Specifically, in the ScioSense_ENS160.cpp
file, locate the _i2c_init()
function and replace its contents with a single call to Wire.begin();
. This change ensures compatibility across different platforms.
❌ ENS160 Readings Unavailable in ESPHome
Issue: The ENS160 sensor intermittently reports unavailable readings in ESPHome, with log messages indicating: ENS160 readings unavailable - Normal Operation but readings not ready
.
Possible causes include insufficient power supply stability, especially when the sensor is combined with other components like the AHT21.
Solution: Enhance the power supply stability by adding a supplemental capacitor to the sensor's power lines. This addition helps prevent voltage dropouts and ensures consistent sensor operation.
⚠️ ENS160 Fails to Initialize with WiFi Enabled on ESP32
Issue: When using the ENS160 sensor with an ESP32, enabling WiFi causes the sensor to report zero or no data on all channels.
Possible causes include resource conflicts or timing issues between the WiFi module and the I2C communication used by the sensor.
Solution: Investigate potential conflicts between the WiFi and I2C peripherals on the ESP32. Ensure that the I2C bus is properly configured and consider adjusting the I2C clock speed. Additionally, test the setup with WiFi disabled to confirm that the issue is related to WiFi interference.
❌ ENS160 Not Detected on I2C Bus
Issue: The ENS160 sensor is not recognized on the I2C bus, leading to initialization failures.
Possible causes include incorrect I2C address configuration or improper wiring.
Solution: Verify the sensor's I2C address, which can be either 0x52 or 0x53, depending on the state of the address selection pin (ASW). Ensure that the ASW pin is set correctly to match the expected address in your code. Additionally, check all wiring connections for correctness and secure contact.
Debugging Tips
🔍 Serial Monitor
Use the Serial Monitor to check for error messages and verify the sensor's output. Add debug prints in your code to track the sensor's state.
⚡ Voltage Checks
Use a multimeter to verify voltage levels and check for continuity in your connections. Ensure the power supply is stable and within the sensor's requirements.
Additional Resources
Code Examples
Arduino Example
#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);
}
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.ESP-IDF Example
#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));
}
}
ESPHome Example
i2c:
sda: GPIO21
scl: GPIO22
sensor:
- platform: ens160
eco2:
name: "eCO2"
tvoc:
name: "TVOC"
aqi:
name: "Air Quality Index"
address: 0x53
update_interval: 1s
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.PlatformIO Example
platformio.ini
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
PlatformIO Example Code
#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);
}
loop()
and printed to the Serial Monitor every second.MicroPython Example
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)
read_register()
function retrieves 16-bit data from the sensor. The main loop continuously fetches and prints the sensor values every second.Conclusion
The ESP32 ENS160 Digital Metal-Oxide Multi-Gas Sensor is a powerful Air Quality sensor that offers excellent performance and reliability. With support for multiple development platforms including Arduino, ESP-IDF, ESPHome, PlatformIO, and MicroPython, it's a versatile choice for your IoT projects.
For optimal performance, ensure proper wiring and follow the recommended configuration for your chosen development platform.
Always verify power supply requirements and pin connections before powering up your project to avoid potential damage.