23static const char *
const TAG =
"ens160";
27static const uint8_t ENS160_BOOTING = 11;
29static const uint16_t ENS160_PART_ID = 0x0160;
31static const uint8_t ENS160_REG_PART_ID = 0x00;
32static const uint8_t ENS160_REG_OPMODE = 0x10;
33static const uint8_t ENS160_REG_CONFIG = 0x11;
34static const uint8_t ENS160_REG_COMMAND = 0x12;
35static const uint8_t ENS160_REG_TEMP_IN = 0x13;
36static const uint8_t ENS160_REG_DATA_STATUS = 0x20;
37static const uint8_t ENS160_REG_DATA_AQI = 0x21;
38static const uint8_t ENS160_REG_DATA_TVOC = 0x22;
39static const uint8_t ENS160_REG_DATA_ECO2 = 0x24;
41static const uint8_t ENS160_REG_GPR_READ_0 = 0x48;
42static const uint8_t ENS160_REG_GPR_READ_4 = ENS160_REG_GPR_READ_0 + 4;
44static const uint8_t ENS160_COMMAND_NOP = 0x00;
45static const uint8_t ENS160_COMMAND_CLRGPR = 0xCC;
46static const uint8_t ENS160_COMMAND_GET_APPVER = 0x0E;
48static const uint8_t ENS160_OPMODE_RESET = 0xF0;
49static const uint8_t ENS160_OPMODE_IDLE = 0x01;
50static const uint8_t ENS160_OPMODE_STD = 0x02;
52static const uint8_t ENS160_DATA_STATUS_STATAS = 0x80;
53static const uint8_t ENS160_DATA_STATUS_STATER = 0x40;
54static const uint8_t ENS160_DATA_STATUS_VALIDITY = 0x0C;
55static const uint8_t ENS160_DATA_STATUS_NEWDAT = 0x02;
56static const uint8_t ENS160_DATA_STATUS_NEWGPR = 0x01;
59static const uint8_t ENS160_DATA_AQI = 0x07;
64 if (!this->
read_bytes(ENS160_REG_PART_ID,
reinterpret_cast<uint8_t *
>(&part_id), 2)) {
69 if (part_id != ENS160_PART_ID) {
76 if (!this->
write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_RESET)) {
81 delay(ENS160_BOOTING);
85 if (!this->
read_byte(ENS160_REG_DATA_STATUS, &status_value)) {
99 if (!this->
write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_IDLE)) {
104 delay(ENS160_BOOTING);
107 if (!this->
write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_NOP)) {
112 if (!this->
write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_CLRGPR)) {
117 delay(ENS160_BOOTING);
120 if (!this->
write_byte(ENS160_REG_COMMAND, ENS160_COMMAND_GET_APPVER)) {
125 delay(ENS160_BOOTING);
127 uint8_t version_data[3];
128 if (!this->
read_bytes(ENS160_REG_GPR_READ_4, version_data, 3)) {
138 if (!this->
write_byte(ENS160_REG_OPMODE, ENS160_OPMODE_STD)) {
146 if (!this->
read_byte(ENS160_REG_OPMODE, &op_mode)) {
152 if (op_mode != ENS160_OPMODE_STD) {
160 uint8_t status_value, data_ready;
162 if (!this->
read_byte(ENS160_REG_DATA_STATUS, &status_value)) {
163 ESP_LOGW(TAG,
"Error reading status register");
170 "ENS160 Status Register: 0x%02x\n"
173 " VALIDITY FLAG 0x%02x\n"
176 status_value, (ENS160_DATA_STATUS_STATAS & (status_value)) == ENS160_DATA_STATUS_STATAS,
177 (ENS160_DATA_STATUS_STATER & (status_value)) == ENS160_DATA_STATUS_STATER,
178 (ENS160_DATA_STATUS_VALIDITY & status_value) >> 2,
179 (ENS160_DATA_STATUS_NEWDAT & (status_value)) == ENS160_DATA_STATUS_NEWDAT,
180 (ENS160_DATA_STATUS_NEWGPR & (status_value)) == ENS160_DATA_STATUS_NEWGPR);
182 data_ready = ENS160_DATA_STATUS_NEWDAT & status_value;
187 if (data_ready != ENS160_DATA_STATUS_NEWDAT) {
188 ESP_LOGD(TAG,
"ENS160 readings unavailable - Normal Operation but readings not ready");
195 ESP_LOGI(TAG,
"ENS160 readings unavailable - 1 hour startup required after first power on");
201 ESP_LOGI(TAG,
"ENS160 readings not available yet - Warming up requires 3 minutes");
206 ESP_LOGE(TAG,
"ENS160 Invalid Status - No valid output");
213 if (!this->
read_bytes(ENS160_REG_DATA_ECO2,
reinterpret_cast<uint8_t *
>(&data_eco2), 2)) {
214 ESP_LOGW(TAG,
"Error reading eCO2 data register");
218 if (this->
co2_ !=
nullptr) {
223 if (!this->
read_bytes(ENS160_REG_DATA_TVOC,
reinterpret_cast<uint8_t *
>(&data_tvoc), 2)) {
224 ESP_LOGW(TAG,
"Error reading TVOC data register");
228 if (this->
tvoc_ !=
nullptr) {
233 if (!this->
read_byte(ENS160_REG_DATA_AQI, &data_aqi)) {
234 ESP_LOGW(TAG,
"Error reading AQI data register");
238 if (this->
aqi_ !=
nullptr) {
240 data_aqi = ENS160_DATA_AQI & data_aqi;
259 ESP_LOGW(TAG,
"Invalid external temperature - compensation values not updated");
262 ESP_LOGV(TAG,
"External temperature compensation: %.1f°C",
temperature);
265 float humidity = NAN;
269 if (std::isnan(humidity) || humidity < 0.0f || humidity > 100.0f) {
270 ESP_LOGW(TAG,
"Invalid external humidity - compensation values not updated");
273 ESP_LOGV(TAG,
"External humidity compensation: %.1f%%", humidity);
276 uint16_t t = (uint16_t) ((
temperature + 273.15f) * 64.0f);
277 uint16_t
h = (uint16_t) (humidity * 512.0f);
281 data[1] = (t >> 8) & 0xff;
283 data[3] = (
h >> 8) & 0xff;
285 if (!this->
write_bytes(ENS160_REG_TEMP_IN, data, 4)) {
286 ESP_LOGE(TAG,
"Error writing compensation values");
293 ESP_LOGCONFIG(TAG,
"ENS160:");
295 switch (this->error_code_) {
297 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
300 ESP_LOGE(TAG,
"Error reading from register");
303 ESP_LOGE(TAG,
"Error writing to register");
306 ESP_LOGE(TAG,
"Sensor reported an invalid ID. Is this a ENS160?");
309 ESP_LOGE(TAG,
"Invalid Device Status - No valid output");
312 ESP_LOGE(TAG,
"Device failed to achieve Standard Operating Mode");
315 ESP_LOGD(TAG,
"Setup successful");
321 LOG_UPDATE_INTERVAL(
this);
322 LOG_SENSOR(
" ",
"CO2 Sensor:", this->
co2_);
323 LOG_SENSOR(
" ",
"TVOC Sensor:", this->
tvoc_);
324 LOG_SENSOR(
" ",
"AQI Sensor:", this->
aqi_);
327 LOG_SENSOR(
" ",
" Temperature Compensation:", this->
temperature_);
328 LOG_SENSOR(
" ",
" Humidity Compensation:", this->
humidity_);
330 ESP_LOGCONFIG(TAG,
" Compensation: Not configured");