ESPHome  2024.12.2
htu21d.cpp
Go to the documentation of this file.
1 #include "htu21d.h"
2 #include "esphome/core/log.h"
3 #include "esphome/core/hal.h"
4 
5 namespace esphome {
6 namespace htu21d {
7 
8 static const char *const TAG = "htu21d";
9 
10 static const uint8_t HTU21D_ADDRESS = 0x40;
11 static const uint8_t HTU21D_REGISTER_RESET = 0xFE;
12 static const uint8_t HTU21D_REGISTER_TEMPERATURE = 0xF3;
13 static const uint8_t HTU21D_REGISTER_HUMIDITY = 0xF5;
14 static const uint8_t HTU21D_WRITERHT_REG_CMD = 0xE6;
15 static const uint8_t HTU21D_REGISTER_STATUS = 0xE7;
16 static const uint8_t HTU21D_WRITEHEATER_REG_CMD = 0x51;
17 static const uint8_t HTU21D_READHEATER_REG_CMD = 0x11;
18 static const uint8_t HTU21D_REG_HTRE_BIT = 0x02;
21  ESP_LOGCONFIG(TAG, "Setting up HTU21D...");
22 
23  if (!this->write_bytes(HTU21D_REGISTER_RESET, nullptr, 0)) {
24  this->mark_failed();
25  return;
26  }
27 
28  // Wait for software reset to complete
29  delay(15);
30 }
32  ESP_LOGCONFIG(TAG, "HTU21D:");
33  LOG_I2C_DEVICE(this);
34  if (this->is_failed()) {
35  ESP_LOGE(TAG, "Communication with HTU21D failed!");
36  }
37  LOG_UPDATE_INTERVAL(this);
38  LOG_SENSOR(" ", "Temperature", this->temperature_);
39  LOG_SENSOR(" ", "Humidity", this->humidity_);
40 }
42  if (this->write(&HTU21D_REGISTER_TEMPERATURE, 1) != i2c::ERROR_OK) {
43  this->status_set_warning();
44  return;
45  }
46 
47  // According to the datasheet sht21 temperature readings can take up to 85ms
48  this->set_timeout(85, [this]() {
49  uint16_t raw_temperature;
50  if (this->read(reinterpret_cast<uint8_t *>(&raw_temperature), 2) != i2c::ERROR_OK) {
51  this->status_set_warning();
52  return;
53  }
54  raw_temperature = i2c::i2ctohs(raw_temperature);
55 
56  float temperature = (float(raw_temperature & 0xFFFC)) * 175.72f / 65536.0f - 46.85f;
57 
58  ESP_LOGD(TAG, "Got Temperature=%.1f°C", temperature);
59 
60  if (this->temperature_ != nullptr)
61  this->temperature_->publish_state(temperature);
62  this->status_clear_warning();
63 
64  if (this->write(&HTU21D_REGISTER_HUMIDITY, 1) != i2c::ERROR_OK) {
65  this->status_set_warning();
66  return;
67  }
68 
69  this->set_timeout(50, [this]() {
70  uint16_t raw_humidity;
71  if (this->read(reinterpret_cast<uint8_t *>(&raw_humidity), 2) != i2c::ERROR_OK) {
72  this->status_set_warning();
73  return;
74  }
75  raw_humidity = i2c::i2ctohs(raw_humidity);
76 
77  float humidity = (float(raw_humidity & 0xFFFC)) * 125.0f / 65536.0f - 6.0f;
78 
79  ESP_LOGD(TAG, "Got Humidity=%.1f%%", humidity);
80 
81  if (this->humidity_ != nullptr)
82  this->humidity_->publish_state(humidity);
83 
84  int8_t heater_level;
85 
86  // HTU21D does have a heater module but does not have heater level
87  // Setting heater level to 1 in case the heater is ON
89  if (this->is_heater_enabled()) {
90  heater_level = 1;
91  } else {
92  heater_level = 0;
93  }
94  } else {
95  heater_level = this->get_heater_level();
96  }
97 
98  ESP_LOGD(TAG, "Heater Level=%d", heater_level);
99 
100  if (this->heater_ != nullptr)
101  this->heater_->publish_state(heater_level);
102  this->status_clear_warning();
103  });
104  });
105 }
106 
108  uint8_t raw_heater;
109  if (this->read_register(HTU21D_REGISTER_STATUS, reinterpret_cast<uint8_t *>(&raw_heater), 2) != i2c::ERROR_OK) {
110  this->status_set_warning();
111  return false;
112  }
113  raw_heater = i2c::i2ctohs(raw_heater);
114  return (bool) (((raw_heater) >> (HTU21D_REG_HTRE_BIT)) & 0x01);
115 }
116 
118  uint8_t raw_heater;
119  if (this->read_register(HTU21D_REGISTER_STATUS, reinterpret_cast<uint8_t *>(&raw_heater), 2) != i2c::ERROR_OK) {
120  this->status_set_warning();
121  return;
122  }
123  raw_heater = i2c::i2ctohs(raw_heater);
124  if (status) {
125  raw_heater |= (1 << (HTU21D_REG_HTRE_BIT));
126  } else {
127  raw_heater &= ~(1 << (HTU21D_REG_HTRE_BIT));
128  }
129 
130  if (this->write_register(HTU21D_WRITERHT_REG_CMD, &raw_heater, 1) != i2c::ERROR_OK) {
131  this->status_set_warning();
132  return;
133  }
134 }
135 
137  if (this->write_register(HTU21D_WRITEHEATER_REG_CMD, &level, 1) != i2c::ERROR_OK) {
138  this->status_set_warning();
139  return;
140  }
141 }
142 
144  int8_t raw_heater;
145  if (this->read_register(HTU21D_READHEATER_REG_CMD, reinterpret_cast<uint8_t *>(&raw_heater), 2) != i2c::ERROR_OK) {
146  this->status_set_warning();
147  return 0;
148  }
149  raw_heater = i2c::i2ctohs(raw_heater);
150  return raw_heater;
151 }
152 
154 
155 } // namespace htu21d
156 } // namespace esphome
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
uint16_t i2ctohs(uint16_t i2cshort)
Definition: i2c.h:128
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len, bool stop=true)
reads an array of bytes from a specific register in the I²C device
Definition: i2c.cpp:10
sensor::Sensor * humidity_
Definition: htu21d.h:35
void status_set_warning(const char *message="unspecified")
Definition: component.cpp:151
bool is_failed() const
Definition: component.cpp:143
ErrorCode read(uint8_t *data, size_t len)
reads an array of bytes from the device using an I2CBus
Definition: i2c.h:160
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition: component.cpp:69
sensor::Sensor * heater_
Definition: htu21d.h:36
void setup() override
Setup (reset) the sensor and check connection.
Definition: htu21d.cpp:20
ErrorCode write(const uint8_t *data, size_t len, bool stop=true)
writes an array of bytes to a device using an I2CBus
Definition: i2c.h:186
void update() override
Update the sensor values (temperature+humidity).
Definition: htu21d.cpp:41
float get_setup_priority() const override
Definition: htu21d.cpp:153
sensor::Sensor * temperature_
Definition: htu21d.h:34
void dump_config() override
Definition: htu21d.cpp:31
No error found during execution of method.
Definition: i2c_bus.h:13
void status_clear_warning()
Definition: component.cpp:166
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
uint16_t temperature
Definition: sun_gtil2.cpp:26
void set_heater(sensor::Sensor *heater)
Definition: htu21d.h:17
uint8_t status
Definition: bl0942.h:74
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
void set_heater_level(uint8_t level)
Definition: htu21d.cpp:136
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len, bool stop=true)
writes an array of bytes to a specific register in the I²C device
Definition: i2c.cpp:25
HTU21DSensorModels sensor_model_
Definition: htu21d.h:37
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26
bool write_bytes(uint8_t a_register, const uint8_t *data, uint8_t len, bool stop=true)
Definition: i2c.h:248