From 464d3331428a94499ae5075a3708cad495fe446c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 20 Mar 2026 14:08:36 -1000 Subject: [PATCH] [sht4x] Fire heater after measurement instead of skipping cycles Per swoboda1337's suggestion, run the heater after the measurement read instead of before. This maximizes cooldown time before the next reading and avoids skipping any measurement cycles. --- esphome/components/sht4x/sht4x.cpp | 75 +++++++++++------------------- esphome/components/sht4x/sht4x.h | 1 - 2 files changed, 28 insertions(+), 48 deletions(-) diff --git a/esphome/components/sht4x/sht4x.cpp b/esphome/components/sht4x/sht4x.cpp index e8e84f535d0..d9d6a716307 100644 --- a/esphome/components/sht4x/sht4x.cpp +++ b/esphome/components/sht4x/sht4x.cpp @@ -79,63 +79,44 @@ void SHT4XComponent::dump_config() { } void SHT4XComponent::update() { - bool use_heater = false; - - // Check if heater is due during this measurement cycle - if (this->heater_interval_ > 0) { - uint32_t now = millis(); - if (now - this->last_heater_millis_ >= this->heater_interval_) { - use_heater = true; - } - } - - if (use_heater) { - // Heater command heats the sensor to remove condensation (datasheet 4.9). - // The measurement it produces is taken while hot and does not reflect - // ambient conditions, so we skip this cycle. The next update() will - // take a regular reading after the sensor has cooled. - ESP_LOGD(TAG, "Heater turning on"); - if (!this->write_command(this->heater_command_)) { - this->status_set_warning(LOG_STR("Failed to send heater command")); - return; - } - // Only update timestamp after successful command. Ensure at least one - // normal measurement between heater cycles by pushing the next eligible - // heater time forward by at least one update interval. - uint32_t now = millis(); - uint32_t interval = std::max(this->heater_interval_, this->get_update_interval()); - this->last_heater_millis_ = now - this->heater_interval_ + interval; - return; - } - if (!this->write_command(MEASURECOMMANDS[this->precision_])) { this->status_set_warning(LOG_STR("Failed to send measurement command")); return; } - this->set_timeout(10, [this]() { this->read_and_publish_(); }); -} + this->set_timeout(10, [this]() { + uint16_t buffer[2]; -void SHT4XComponent::read_and_publish_() { - uint16_t buffer[2]; + if (!this->read_data(buffer, 2)) { + ESP_LOGW(TAG, "Sensor read failed"); + this->status_set_warning(); + return; + } - if (!this->read_data(buffer, 2)) { - ESP_LOGW(TAG, "Sensor read failed"); - this->status_set_warning(); - return; - } + this->status_clear_warning(); - this->status_clear_warning(); + if (this->temp_sensor_ != nullptr) { + float temp = TEMPERATURE_OFFSET + TEMPERATURE_SPAN * static_cast(buffer[0]) / RAW_MAX; + this->temp_sensor_->publish_state(temp); + } - if (this->temp_sensor_ != nullptr) { - float temp = TEMPERATURE_OFFSET + TEMPERATURE_SPAN * static_cast(buffer[0]) / RAW_MAX; - this->temp_sensor_->publish_state(temp); - } + if (this->humidity_sensor_ != nullptr) { + float rh = HUMIDITY_OFFSET + HUMIDITY_SPAN * static_cast(buffer[1]) / RAW_MAX; + this->humidity_sensor_->publish_state(rh); + } - if (this->humidity_sensor_ != nullptr) { - float rh = HUMIDITY_OFFSET + HUMIDITY_SPAN * static_cast(buffer[1]) / RAW_MAX; - this->humidity_sensor_->publish_state(rh); - } + // Fire heater after measurement to maximize cooldown time before the next reading. + // The heater command produces a measurement that we don't need (datasheet 4.9). + if (this->heater_interval_ > 0) { + uint32_t now = millis(); + if (now - this->last_heater_millis_ >= this->heater_interval_) { + ESP_LOGD(TAG, "Heater turning on"); + if (this->write_command(this->heater_command_)) { + this->last_heater_millis_ = now; + } + } + } + }); } } // namespace sht4x diff --git a/esphome/components/sht4x/sht4x.h b/esphome/components/sht4x/sht4x.h index d8ff0280bf0..51f473fe3f2 100644 --- a/esphome/components/sht4x/sht4x.h +++ b/esphome/components/sht4x/sht4x.h @@ -36,7 +36,6 @@ class SHT4XComponent : public PollingComponent, public sensirion_common::Sensiri float duty_cycle_; void read_serial_number_(); - void read_and_publish_(); uint8_t heater_command_; uint32_t heater_interval_{0}; uint32_t last_heater_millis_{0};