ESPHome 2026.5.1
Loading...
Searching...
No Matches
htu31d.cpp
Go to the documentation of this file.
1/*
2 * This file contains source code derived from Adafruit_HTU31D which is under
3 * the BSD license:
4 * Written by Limor Fried/Ladyada for Adafruit Industries.
5 * BSD license, all text above must be included in any redistribution.
6 *
7 * Modifications made by Mark Spicer.
8 */
9
10#include "htu31d.h"
11#include "esphome/core/hal.h"
13#include "esphome/core/log.h"
14
15#include <cinttypes>
16
17namespace esphome::htu31d {
18
20static const char *const TAG = "htu31d";
21
23static const uint8_t HTU31D_DEFAULT_I2CADDR = 0x40;
24
26static const uint8_t HTU31D_READTEMPHUM = 0x00;
27
29static const uint8_t HTU31D_CONVERSION = 0x40;
30
32static const uint8_t HTU31D_READSERIAL = 0x0A;
33
35static const uint8_t HTU31D_HEATERON = 0x04;
36
38static const uint8_t HTU31D_HEATEROFF = 0x02;
39
41static const uint8_t HTU31D_RESET = 0x1E;
42
44static const uint8_t HTU31D_DIAGNOSTICS = 0x08;
45
51 if (!this->reset_()) {
52 this->mark_failed();
53 return;
54 }
55
56 if (this->read_serial_num_() == 0) {
57 this->mark_failed();
58 return;
59 }
60}
61
67 ESP_LOGD(TAG, "Checking temperature and humidty values");
68
69 // Trigger a conversion. From the spec sheet: The conversion command triggers
70 // a single temperature and humidity conversion.
71 if (this->write_register(HTU31D_CONVERSION, nullptr, 0) != i2c::ERROR_OK) {
72 this->status_set_warning();
73 ESP_LOGE(TAG, "Received errror writing conversion register");
74 return;
75 }
76
77 // Wait conversion time.
78 this->set_timeout(20, [this]() {
79 uint8_t thdata[6];
80 if (this->read_register(HTU31D_READTEMPHUM, thdata, 6) != i2c::ERROR_OK) {
81 this->status_set_warning();
82 ESP_LOGE(TAG, "Error reading temperature/humidty register");
83 return;
84 }
85
86 // Calculate temperature value.
87 uint16_t raw_temp = encode_uint16(thdata[0], thdata[1]);
88
89 uint8_t crc = crc8(thdata, 2, 0, 0x31, true);
90 if (crc != thdata[2]) {
91 this->status_set_warning();
92 ESP_LOGE(TAG, "Error validating temperature CRC");
93 return;
94 }
95
96 float temperature = raw_temp;
97 temperature /= 65535.0f;
98 temperature *= 165;
99 temperature -= 40;
100
101 if (this->temperature_ != nullptr) {
102 this->temperature_->publish_state(temperature);
103 }
104
105 // Calculate humidty value.
106 uint16_t raw_hum = encode_uint16(thdata[3], thdata[4]);
107
108 crc = crc8(thdata + 3, 2, 0, 0x31, true);
109 if (crc != thdata[5]) {
110 this->status_set_warning();
111 ESP_LOGE(TAG, "Error validating humidty CRC");
112 return;
113 }
114
115 float humidity = raw_hum;
116 humidity /= 65535.0f;
117 humidity *= 100;
118
119 if (this->humidity_ != nullptr) {
120 this->humidity_->publish_state(humidity);
121 }
122
123 ESP_LOGD(TAG, "Got Temperature=%.1f°C Humidity=%.1f%%", temperature, humidity);
124 this->status_clear_warning();
125 });
126}
127
132 ESP_LOGCONFIG(TAG, "HTU31D:");
133 LOG_I2C_DEVICE(this);
134 if (this->is_failed()) {
135 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
136 }
137 LOG_UPDATE_INTERVAL(this);
138 LOG_SENSOR(" ", "Temperature", this->temperature_);
139 LOG_SENSOR(" ", "Humidity", this->humidity_);
140}
141
148 if (this->write_register(HTU31D_RESET, nullptr, 0) != i2c::ERROR_OK) {
149 return false;
150 }
151
152 delay(15);
153 return true;
154}
155
162 uint8_t reply[4];
163 uint32_t serial = 0;
164 uint8_t padding = 0;
165
166 // Verify we can read the device serial.
167 if (this->read_register(HTU31D_READSERIAL, reply, 4) != i2c::ERROR_OK) {
168 ESP_LOGE(TAG, "Error reading device serial");
169 return 0;
170 }
171
172 serial = encode_uint32(reply[0], reply[1], reply[2], padding);
173
174 uint8_t crc = crc8(reply, 3, 0, 0x31, true);
175 if (crc != reply[3]) {
176 ESP_LOGE(TAG, "Error validating serial CRC");
177 return 0;
178 }
179
180 ESP_LOGD(TAG, "Found serial: 0x%" PRIX32, serial);
181
182 return serial;
183}
184
192 uint8_t reply[1];
193 uint8_t heater_enabled_position = 0;
194 uint8_t mask = 1 << heater_enabled_position;
195 uint8_t diagnostics = 0;
196
197 if (this->read_register(HTU31D_DIAGNOSTICS, reply, 1) != i2c::ERROR_OK) {
198 ESP_LOGE(TAG, "Error reading device serial");
199 return false;
200 }
201
202 diagnostics = reply[0];
203 return (diagnostics & mask) != 0;
204}
205
212 bool current = this->is_heater_enabled();
213
214 // If the current state matches the desired state, there is nothing to do.
215 if (current == desired) {
216 return;
217 }
218
219 // Update heater state.
221 if (desired) {
222 err = this->write_register(HTU31D_HEATERON, nullptr, 0);
223 } else {
224 err = this->write_register(HTU31D_HEATEROFF, nullptr, 0);
225 }
226
227 // Record any error.
228 if (err != i2c::ERROR_OK) {
229 this->status_set_warning();
230 ESP_LOGE(TAG, "Received error updating heater state");
231 return;
232 }
233}
234
235} // namespace esphome::htu31d
void mark_failed()
Mark this component as failed.
bool is_failed() const
Definition component.h:284
ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std voi set_timeout)(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
Definition component.h:510
void status_clear_warning()
Definition component.h:306
void update() override
Setup (reset) the sensor and check connection.
Definition htu31d.cpp:66
uint32_t read_serial_num_()
Reads the serial number from the device and checks the CRC.
Definition htu31d.cpp:161
sensor::Sensor * temperature_
Definition htu31d.h:26
void setup() override
Resets the sensor and ensures that the devices serial number can be read over I2C.
Definition htu31d.cpp:50
sensor::Sensor * humidity_
Definition htu31d.h:27
bool is_heater_enabled()
Checks the diagnostics register to determine if the heater is currently enabled.
Definition htu31d.cpp:191
void set_heater_state(bool desired)
Sets the heater state on or off.
Definition htu31d.cpp:211
bool reset_()
Sends a 'reset' request to the HTU31D, followed by a 15ms delay.
Definition htu31d.cpp:147
void dump_config() override
Update the sensor values (temperature+humidity).
Definition htu31d.cpp:131
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len) const
writes an array of bytes to a specific register in the I²C device
Definition i2c.cpp:34
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len)
reads an array of bytes from a specific register in the I²C device
Definition i2c.cpp:25
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68
u_int8_t raw_temp
ErrorCode
Error codes returned by I2CBus and I2CDevice methods.
Definition i2c_bus.h:12
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:14
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
Definition helpers.h:867
uint8_t crc8(const uint8_t *data, uint8_t len, uint8_t crc, uint8_t poly, bool msb_first)
Calculate a CRC-8 checksum of data with size len.
Definition helpers.cpp:59
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition helpers.h:859
void HOT delay(uint32_t ms)
Definition hal.cpp:85
static void uint32_t
uint16_t temperature
Definition sun_gtil2.cpp:12