13 namespace ens160_base {
15 static const char *
const TAG =
"ens160";
17 static const uint8_t ENS160_BOOTING = 10;
19 static const uint16_t ENS160_PART_ID = 0x0160;
21 static const uint8_t ENS160_REG_PART_ID = 0x00;
22 static const uint8_t ENS160_REG_OPMODE = 0x10;
23 static const uint8_t ENS160_REG_CONFIG = 0x11;
24 static const uint8_t ENS160_REG_COMMAND = 0x12;
25 static const uint8_t ENS160_REG_TEMP_IN = 0x13;
26 static const uint8_t ENS160_REG_DATA_STATUS = 0x20;
27 static const uint8_t ENS160_REG_DATA_AQI = 0x21;
28 static const uint8_t ENS160_REG_DATA_TVOC = 0x22;
29 static const uint8_t ENS160_REG_DATA_ECO2 = 0x24;
31 static const uint8_t ENS160_REG_GPR_READ_0 = 0x48;
32 static const uint8_t ENS160_REG_GPR_READ_4 = ENS160_REG_GPR_READ_0 + 4;
34 static const uint8_t ENS160_COMMAND_NOP = 0x00;
35 static const uint8_t ENS160_COMMAND_CLRGPR = 0xCC;
36 static const uint8_t ENS160_COMMAND_GET_APPVER = 0x0E;
38 static const uint8_t ENS160_OPMODE_RESET = 0xF0;
39 static const uint8_t ENS160_OPMODE_IDLE = 0x01;
40 static const uint8_t ENS160_OPMODE_STD = 0x02;
42 static const uint8_t ENS160_DATA_STATUS_STATAS = 0x80;
43 static const uint8_t ENS160_DATA_STATUS_STATER = 0x40;
44 static const uint8_t ENS160_DATA_STATUS_VALIDITY = 0x0C;
45 static const uint8_t ENS160_DATA_STATUS_NEWDAT = 0x02;
46 static const uint8_t ENS160_DATA_STATUS_NEWGPR = 0x01;
49 static const uint8_t ENS160_DATA_AQI = 0x07;
52 ESP_LOGCONFIG(TAG,
"Setting up ENS160...");
56 if (!this->
read_bytes(ENS160_REG_PART_ID, reinterpret_cast<uint8_t *>(&part_id), 2)) {
61 if (part_id != ENS160_PART_ID) {
68 if (!this->
write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_RESET)) {
73 delay(ENS160_BOOTING);
77 if (!this->
read_byte(ENS160_REG_DATA_STATUS, &status_value)) {
91 if (!this->
write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_IDLE)) {
97 if (!this->
write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_NOP)) {
102 if (!this->
write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_CLRGPR)) {
109 if (!this->
write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_GET_APPVER)) {
114 uint8_t version_data[3];
115 if (!this->
read_bytes(ENS160_REG_GPR_READ_4, version_data, 3)) {
125 if (!this->
write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_STD)) {
133 if (!this->
read_byte(ENS160_REG_OPMODE, &op_mode)) {
139 if (op_mode != ENS160_OPMODE_STD) {
147 uint8_t status_value, data_ready;
149 if (!this->
read_byte(ENS160_REG_DATA_STATUS, &status_value)) {
150 ESP_LOGW(TAG,
"Error reading status register");
156 ESP_LOGV(TAG,
"Status: ENS160 STATAS bit 0x%x",
157 (ENS160_DATA_STATUS_STATAS & (status_value)) == ENS160_DATA_STATUS_STATAS);
158 ESP_LOGV(TAG,
"Status: ENS160 STATER bit 0x%x",
159 (ENS160_DATA_STATUS_STATER & (status_value)) == ENS160_DATA_STATUS_STATER);
160 ESP_LOGV(TAG,
"Status: ENS160 VALIDITY FLAG 0x%02x", (ENS160_DATA_STATUS_VALIDITY & status_value) >> 2);
161 ESP_LOGV(TAG,
"Status: ENS160 NEWDAT bit 0x%x",
162 (ENS160_DATA_STATUS_NEWDAT & (status_value)) == ENS160_DATA_STATUS_NEWDAT);
163 ESP_LOGV(TAG,
"Status: ENS160 NEWGPR bit 0x%x",
164 (ENS160_DATA_STATUS_NEWGPR & (status_value)) == ENS160_DATA_STATUS_NEWGPR);
166 data_ready = ENS160_DATA_STATUS_NEWDAT & status_value;
171 if (data_ready != ENS160_DATA_STATUS_NEWDAT) {
172 ESP_LOGD(TAG,
"ENS160 readings unavailable - Normal Operation but readings not ready");
179 ESP_LOGI(TAG,
"ENS160 readings unavailable - 1 hour startup required after first power on");
185 ESP_LOGI(TAG,
"ENS160 readings not available yet - Warming up requires 3 minutes");
190 ESP_LOGE(TAG,
"ENS160 Invalid Status - No Invalid Output");
197 if (!this->
read_bytes(ENS160_REG_DATA_ECO2, reinterpret_cast<uint8_t *>(&data_eco2), 2)) {
198 ESP_LOGW(TAG,
"Error reading eCO2 data register");
202 if (this->
co2_ !=
nullptr) {
207 if (!this->
read_bytes(ENS160_REG_DATA_TVOC, reinterpret_cast<uint8_t *>(&data_tvoc), 2)) {
208 ESP_LOGW(TAG,
"Error reading TVOC data register");
212 if (this->
tvoc_ !=
nullptr) {
217 if (!this->
read_byte(ENS160_REG_DATA_AQI, &data_aqi)) {
218 ESP_LOGW(TAG,
"Error reading AQI data register");
222 if (this->
aqi_ !=
nullptr) {
224 data_aqi = ENS160_DATA_AQI & data_aqi;
243 if (std::isnan(temperature) || temperature < -40.0f || temperature > 85.0f) {
244 ESP_LOGW(TAG,
"Invalid external temperature - compensation values not updated");
247 ESP_LOGV(TAG,
"External temperature compensation: %.1f°C", temperature);
250 float humidity = NAN;
254 if (std::isnan(humidity) || humidity < 0.0f || humidity > 100.0f) {
255 ESP_LOGW(TAG,
"Invalid external humidity - compensation values not updated");
258 ESP_LOGV(TAG,
"External humidity compensation: %.1f%%", humidity);
261 uint16_t t = (uint16_t) ((temperature + 273.15f) * 64.0f);
262 uint16_t
h = (uint16_t) (humidity * 512.0f);
266 data[1] = (t >> 8) & 0xff;
268 data[3] = (h >> 8) & 0xff;
270 if (!this->
write_bytes(ENS160_REG_TEMP_IN, data, 4)) {
271 ESP_LOGE(TAG,
"Error writing compensation values");
278 ESP_LOGCONFIG(TAG,
"ENS160:");
280 switch (this->error_code_) {
282 ESP_LOGE(TAG,
"Communication failed! Is the sensor connected?");
285 ESP_LOGE(TAG,
"Error reading from register");
288 ESP_LOGE(TAG,
"Error writing to register");
291 ESP_LOGE(TAG,
"Sensor reported an invalid ID. Is this a ENS160?");
294 ESP_LOGE(TAG,
"Invalid Device Status - No valid output");
297 ESP_LOGE(TAG,
"Device failed to achieve Standard Operating Mode");
300 ESP_LOGD(TAG,
"Setup successful");
306 LOG_UPDATE_INTERVAL(
this);
307 LOG_SENSOR(
" ",
"CO2 Sensor:", this->
co2_);
308 LOG_SENSOR(
" ",
"TVOC Sensor:", this->
tvoc_);
309 LOG_SENSOR(
" ",
"AQI Sensor:", this->
aqi_);
312 LOG_SENSOR(
" ",
" Temperature Compensation:", this->
temperature_);
313 LOG_SENSOR(
" ",
" Humidity Compensation:", this->
humidity_);
315 ESP_LOGCONFIG(TAG,
" Compensation: Not configured");
enum esphome::ens160_base::ENS160Component::ValidityFlag validity_flag_
void status_set_warning(const char *message="unspecified")
sensor::Sensor * temperature_
virtual bool write_bytes(uint8_t a_register, uint8_t *data, size_t len)=0
uint8_t firmware_ver_minor_
float state
This member variable stores the last state that has passed through all filters.
void status_clear_warning()
void publish_state(float state)
Publish a new state to the front-end.
sensor::Sensor * humidity_
uint8_t firmware_ver_major_
virtual bool read_byte(uint8_t a_register, uint8_t *data)=0
uint8_t firmware_ver_build_
virtual bool read_bytes(uint8_t a_register, uint8_t *data, size_t len)=0
virtual void mark_failed()
Mark this component as failed.
void dump_config() override
Implementation of SPI Controller mode.
virtual bool write_byte(uint8_t a_register, uint8_t data)=0
enum esphome::ens160_base::ENS160Component::ErrorCode NONE
void IRAM_ATTR HOT delay(uint32_t ms)