diff --git a/esphome/components/ms8607/ms8607.cpp b/esphome/components/ms8607/ms8607.cpp index 215131eb8e..88a3e6d7dc 100644 --- a/esphome/components/ms8607/ms8607.cpp +++ b/esphome/components/ms8607/ms8607.cpp @@ -72,53 +72,55 @@ void MS8607Component::setup() { // I do not know why the device sometimes NACKs the reset command, but // try 3 times in case it's a transitory issue on this boot - this->set_retry( - "reset", 5, 3, - [this](const uint8_t remaining_setup_attempts) { - ESP_LOGD(TAG, "Resetting both I2C addresses: 0x%02X, 0x%02X", this->address_, - this->humidity_device_->get_address()); - // I believe sending the reset command to both addresses is preferable to - // skipping humidity if PT fails for some reason. - // However, only consider the reset successful if they both ACK - bool const pt_successful = this->write_bytes(MS8607_PT_CMD_RESET, nullptr, 0); - bool const h_successful = this->humidity_device_->write_bytes(MS8607_CMD_H_RESET, nullptr, 0); + // Backoff: executes at now, +5ms, +30ms + this->reset_attempts_remaining_ = 3; + this->reset_interval_ = 5; + this->try_reset_(); +} - if (!(pt_successful && h_successful)) { - ESP_LOGE(TAG, "Resetting I2C devices failed"); - if (!pt_successful && !h_successful) { - this->error_code_ = ErrorCode::PTH_RESET_FAILED; - } else if (!pt_successful) { - this->error_code_ = ErrorCode::PT_RESET_FAILED; - } else { - this->error_code_ = ErrorCode::H_RESET_FAILED; - } +void MS8607Component::try_reset_() { + ESP_LOGD(TAG, "Resetting both I2C addresses: 0x%02X, 0x%02X", this->address_, this->humidity_device_->get_address()); + // I believe sending the reset command to both addresses is preferable to + // skipping humidity if PT fails for some reason. + // However, only consider the reset successful if they both ACK + bool const pt_successful = this->write_bytes(MS8607_PT_CMD_RESET, nullptr, 0); + bool const h_successful = this->humidity_device_->write_bytes(MS8607_CMD_H_RESET, nullptr, 0); - if (remaining_setup_attempts > 0) { - this->status_set_error(); - } else { - this->mark_failed(); - } - return RetryResult::RETRY; - } + if (!(pt_successful && h_successful)) { + ESP_LOGE(TAG, "Resetting I2C devices failed"); + if (!pt_successful && !h_successful) { + this->error_code_ = ErrorCode::PTH_RESET_FAILED; + } else if (!pt_successful) { + this->error_code_ = ErrorCode::PT_RESET_FAILED; + } else { + this->error_code_ = ErrorCode::H_RESET_FAILED; + } - this->setup_status_ = SetupStatus::NEEDS_PROM_READ; - this->error_code_ = ErrorCode::NONE; - this->status_clear_error(); + if (--this->reset_attempts_remaining_ > 0) { + uint32_t delay = this->reset_interval_; + this->reset_interval_ *= 5; + this->set_timeout("reset", delay, [this]() { this->try_reset_(); }); + this->status_set_error(); + } else { + this->mark_failed(); + } + return; + } - // 15ms delay matches datasheet, Adafruit_MS8607 & SparkFun_PHT_MS8607_Arduino_Library - this->set_timeout("prom-read", 15, [this]() { - if (this->read_calibration_values_from_prom_()) { - this->setup_status_ = SetupStatus::SUCCESSFUL; - this->status_clear_error(); - } else { - this->mark_failed(); - return; - } - }); + this->setup_status_ = SetupStatus::NEEDS_PROM_READ; + this->error_code_ = ErrorCode::NONE; + this->status_clear_error(); - return RetryResult::DONE; - }, - 5.0f); // executes at now, +5ms, +25ms + // 15ms delay matches datasheet, Adafruit_MS8607 & SparkFun_PHT_MS8607_Arduino_Library + this->set_timeout("prom-read", 15, [this]() { + if (this->read_calibration_values_from_prom_()) { + this->setup_status_ = SetupStatus::SUCCESSFUL; + this->status_clear_error(); + } else { + this->mark_failed(); + return; + } + }); } void MS8607Component::update() { diff --git a/esphome/components/ms8607/ms8607.h b/esphome/components/ms8607/ms8607.h index 67ce2817fa..ceb3dd22c8 100644 --- a/esphome/components/ms8607/ms8607.h +++ b/esphome/components/ms8607/ms8607.h @@ -44,6 +44,8 @@ class MS8607Component : public PollingComponent, public i2c::I2CDevice { void set_humidity_device(MS8607HumidityDevice *humidity_device) { humidity_device_ = humidity_device; } protected: + /// Attempt to reset both I2C devices, retrying with backoff on failure + void try_reset_(); /** Read and store the Pressure & Temperature calibration settings from the PROM. Intended to be called during setup(), this will set the `failure_reason_` @@ -102,6 +104,8 @@ class MS8607Component : public PollingComponent, public i2c::I2CDevice { enum class SetupStatus; /// Current step in the multi-step & possibly delayed setup() process SetupStatus setup_status_; + uint32_t reset_interval_{5}; + uint8_t reset_attempts_remaining_{0}; }; } // namespace ms8607