esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 36 forks source link

SHT4x: heater implementation issues #4263

Open stas-sl opened 1 year ago

stas-sl commented 1 year ago

The problem

There are 2 issues with SHT4x heater implementation currently:

  1. One is simple to fix. From the code below you can see that heater_command_ is actually a command not an index, so accessing MEASURECOMMANDS[heater_command_] will result in out of bounds error.
static const uint8_t MEASURECOMMANDS[] = {0xFD, 0xF6, 0xE0};

void SHT4XComponent::start_heater_() {
  uint8_t cmd[] = {MEASURECOMMANDS[this->heater_command_]};

  ESP_LOGD(TAG, "Heater turning on");
  this->write(cmd, 1);
}

void SHT4XComponent::setup() {
  ESP_LOGCONFIG(TAG, "Setting up sht4x...");

  if (this->duty_cycle_ > 0.0) {
    uint32_t heater_interval = (uint32_t)(this->heater_time_ / this->duty_cycle_);
    ESP_LOGD(TAG, "Heater interval: %i", heater_interval);

    if (this->heater_power_ == SHT4X_HEATERPOWER_HIGH) {
      if (this->heater_time_ == SHT4X_HEATERTIME_LONG) {
        this->heater_command_ = 0x39;
      } else {
        this->heater_command_ = 0x32;
      }
    } else if (this->heater_power_ == SHT4X_HEATERPOWER_MED) {
      if (this->heater_time_ == SHT4X_HEATERTIME_LONG) {
        this->heater_command_ = 0x2F;
      } else {
        this->heater_command_ = 0x24;
      }
    } else {
      if (this->heater_time_ == SHT4X_HEATERTIME_LONG) {
        this->heater_command_ = 0x1E;
      } else {
        this->heater_command_ = 0x15;
      }
    }
    ESP_LOGD(TAG, "Heater command: %x", this->heater_command_);

    this->set_interval(heater_interval, std::bind(&SHT4XComponent::start_heater_, this));
  }
}
  1. Another one is more difficult. As heater naturally causes temperature increase, if update_interval and heater_interval are not synced to each other in a way that guarantees maximal distance between heater turning off and next measurement, then temperature measurements will be affected. You can see spikes in the plot, when I turned on heater at around 22:00. I used heater_max_duty: 0.01 and heater_time: Short (110ms), which resulted in turning heater on every 11 seconds for 110ms. As update_interval (e.g. 60s) is independent of heater_interval, some of them will inevitable co-occur in time.
image

TBH I'm not sure what would be the best way how to solve the latter issue in general case as it depends on update_interval/max_duty/heater_time/heater_power.

Which version of ESPHome has the issue?

2023.2.0

What type of installation are you using?

pip

Which version of Home Assistant has the issue?

No response

What platform are you using?

ESP32

Board

No response

Component causing the issue

sht4x

Example YAML snippet

sensor:
  - platform: sht4x
    temperature:
      name: "SHT41 Temperature"
      id: sht41_temp
    humidity:
      name: "SHT41 Humidity"
      id: sht41_humid
    precision: High
    heater_max_duty: 0.01
    heater_power: High
    heater_time: Short

Anything in the logs that might be useful for us?

No response

Additional information

No response

stas-sl commented 1 year ago

The simplest solution would be probably to run heater at the end of update() after measurements being read on every (or every N) update_interval. Thus we'll have max possible cool off time till next measurement. For example for update_interval=60s and Long(1s) heater duration effective heater duty will be 1/60=~1.7%.

As a workaround until this is implemented you can do it manually in config:

sensor:
  - platform: sht4x
    id: sht41
    update_interval: 60s
    temperature:
      name: "SHT41 Temperature"
      id: sht41_temp
      on_value:
        then:
          - lambda: |-
              id(sht41)->write_command((uint8_t)0x2F);  // run heater: medium power, long duration (1s)
github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.