ESPHome 2026.5.0-dev
Loading...
Searching...
No Matches
sht4x.cpp
Go to the documentation of this file.
1#include "sht4x.h"
2#include "esphome/core/hal.h"
3#include "esphome/core/log.h"
4
5namespace esphome {
6namespace sht4x {
7
8static const char *const TAG = "sht4x";
9
10static const uint8_t MEASURECOMMANDS[] = {0xFD, 0xF6, 0xE0};
11static const uint8_t SERIAL_NUMBER_COMMAND = 0x89;
12
13// Conversion constants from SHT4x datasheet
14static constexpr float TEMPERATURE_OFFSET = -45.0f;
15static constexpr float TEMPERATURE_SPAN = 175.0f;
16static constexpr float HUMIDITY_OFFSET = -6.0f;
17static constexpr float HUMIDITY_SPAN = 125.0f;
18static constexpr float RAW_MAX = 65535.0f;
19
21 uint16_t buffer[2];
22 if (!this->get_8bit_register(SERIAL_NUMBER_COMMAND, buffer, 2, 1)) {
23 ESP_LOGE(TAG, "Get serial number failed");
24 this->serial_number_ = 0;
25 return;
26 }
27 this->serial_number_ = (uint32_t(buffer[0]) << 16) | (uint32_t(buffer[1]));
28 ESP_LOGD(TAG, "Serial number: %08" PRIx32, this->serial_number_);
29}
30
32 auto err = this->write(nullptr, 0);
33 if (err != i2c::ERROR_OK) {
34 this->mark_failed();
35 return;
36 }
37
38 this->read_serial_number_();
39
40 if (std::isfinite(this->duty_cycle_) && this->duty_cycle_ > 0.0f) {
41 this->heater_interval_ = static_cast<uint32_t>(static_cast<uint16_t>(this->heater_time_) / this->duty_cycle_);
42 ESP_LOGD(TAG, "Heater interval: %" PRIu32, this->heater_interval_);
43
46 this->heater_command_ = 0x39;
47 } else {
48 this->heater_command_ = 0x32;
49 }
50 } else if (this->heater_power_ == SHT4X_HEATERPOWER_MED) {
52 this->heater_command_ = 0x2F;
53 } else {
54 this->heater_command_ = 0x24;
55 }
56 } else {
58 this->heater_command_ = 0x1E;
59 } else {
60 this->heater_command_ = 0x15;
61 }
62 }
63 ESP_LOGD(TAG, "Heater command: %x", this->heater_command_);
64 }
65}
66
68 ESP_LOGCONFIG(TAG,
69 "SHT4x:\n"
70 " Serial number: %08" PRIx32,
71 this->serial_number_);
72
73 LOG_I2C_DEVICE(this);
74 if (this->is_failed()) {
75 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
76 }
77 if (this->serial_number_ == 0) {
78 ESP_LOGW(TAG, "Get serial number failed");
79 }
80}
81
83 // Send command
84 if (!this->write_command(MEASURECOMMANDS[this->precision_])) {
85 // Warning will be printed only if warning status is not set yet
86 this->status_set_warning(LOG_STR("Failed to send measurement command"));
87 return;
88 }
89
90 this->set_timeout(10, [this]() {
91 uint16_t buffer[2];
92
93 // Read measurement
94 if (!this->read_data(buffer, 2)) {
95 // Using ESP_LOGW to force the warning to be printed
96 ESP_LOGW(TAG, "Sensor read failed");
97 this->status_set_warning();
98 return;
99 }
100
101 this->status_clear_warning();
102
103 // Evaluate and publish measurements
104 if (this->temp_sensor_ != nullptr) {
105 // Temp is contained in the first result word
106 float temp = TEMPERATURE_OFFSET + TEMPERATURE_SPAN * static_cast<float>(buffer[0]) / RAW_MAX;
107 this->temp_sensor_->publish_state(temp);
108 }
109
110 if (this->humidity_sensor_ != nullptr) {
111 // Relative humidity is in the second result word
112 float rh = HUMIDITY_OFFSET + HUMIDITY_SPAN * static_cast<float>(buffer[1]) / RAW_MAX;
114 }
115
116 // Fire heater after measurement to maximize cooldown time before the next reading.
117 // The heater command produces a measurement that we don't need (datasheet 4.9).
118 if (this->heater_interval_ > 0) {
119 uint32_t now = millis();
120 if (now - this->last_heater_millis_ >= this->heater_interval_) {
121 ESP_LOGD(TAG, "Heater turning on");
122 if (this->write_command(this->heater_command_)) {
123 this->last_heater_millis_ = now;
124 }
125 }
126 }
127 });
128}
129
130} // namespace sht4x
131} // namespace esphome
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
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
Definition i2c.h:183
bool get_8bit_register(uint8_t i2c_register, uint16_t *data, uint8_t len, uint8_t delay=0)
get data words from I2C register.
bool write_command(T i2c_register)
Write a command to the I2C device.
bool read_data(uint16_t *data, uint8_t len)
Read data words from I2C device.
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68
SHT4XPRECISION precision_
Definition sht4x.h:33
SHT4XHEATERPOWER heater_power_
Definition sht4x.h:34
sensor::Sensor * humidity_sensor_
Definition sht4x.h:45
sensor::Sensor * temp_sensor_
Definition sht4x.h:44
void dump_config() override
Definition sht4x.cpp:67
SHT4XHEATERTIME heater_time_
Definition sht4x.h:35
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:14
@ SHT4X_HEATERPOWER_HIGH
Definition sht4x.h:14
@ SHT4X_HEATERPOWER_MED
Definition sht4x.h:14
@ SHT4X_HEATERTIME_LONG
Definition sht4x.h:16
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:26
static void uint32_t