1
0
mirror of https://github.com/esphome/esphome.git synced 2026-02-08 00:31:58 +00:00

[ms8607] Replace set_retry with set_timeout chain to avoid heap allocation

set_retry internally does a std::make_shared<RetryArgs>() heap allocation
on every invocation. Replace with a try_reset_() method that chains
set_timeout calls with manual backoff, preserving the same timing
(immediate, +5ms, +25ms).
This commit is contained in:
J. Nick Koston
2026-02-07 14:17:06 -06:00
parent 9de91539e6
commit 60298f67b8
2 changed files with 48 additions and 42 deletions

View File

@@ -72,53 +72,55 @@ void MS8607Component::setup() {
// I do not know why the device sometimes NACKs the reset command, but // 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 // try 3 times in case it's a transitory issue on this boot
this->set_retry( // Backoff: executes at now, +5ms, +30ms
"reset", 5, 3, this->reset_attempts_remaining_ = 3;
[this](const uint8_t remaining_setup_attempts) { this->reset_interval_ = 5;
ESP_LOGD(TAG, "Resetting both I2C addresses: 0x%02X, 0x%02X", this->address_, this->try_reset_();
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 (!(pt_successful && h_successful)) { void MS8607Component::try_reset_() {
ESP_LOGE(TAG, "Resetting I2C devices failed"); ESP_LOGD(TAG, "Resetting both I2C addresses: 0x%02X, 0x%02X", this->address_, this->humidity_device_->get_address());
if (!pt_successful && !h_successful) { // I believe sending the reset command to both addresses is preferable to
this->error_code_ = ErrorCode::PTH_RESET_FAILED; // skipping humidity if PT fails for some reason.
} else if (!pt_successful) { // However, only consider the reset successful if they both ACK
this->error_code_ = ErrorCode::PT_RESET_FAILED; bool const pt_successful = this->write_bytes(MS8607_PT_CMD_RESET, nullptr, 0);
} else { bool const h_successful = this->humidity_device_->write_bytes(MS8607_CMD_H_RESET, nullptr, 0);
this->error_code_ = ErrorCode::H_RESET_FAILED;
}
if (remaining_setup_attempts > 0) { if (!(pt_successful && h_successful)) {
this->status_set_error(); ESP_LOGE(TAG, "Resetting I2C devices failed");
} else { if (!pt_successful && !h_successful) {
this->mark_failed(); this->error_code_ = ErrorCode::PTH_RESET_FAILED;
} } else if (!pt_successful) {
return RetryResult::RETRY; this->error_code_ = ErrorCode::PT_RESET_FAILED;
} } else {
this->error_code_ = ErrorCode::H_RESET_FAILED;
}
this->setup_status_ = SetupStatus::NEEDS_PROM_READ; if (--this->reset_attempts_remaining_ > 0) {
this->error_code_ = ErrorCode::NONE; uint32_t delay = this->reset_interval_;
this->status_clear_error(); 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->setup_status_ = SetupStatus::NEEDS_PROM_READ;
this->set_timeout("prom-read", 15, [this]() { this->error_code_ = ErrorCode::NONE;
if (this->read_calibration_values_from_prom_()) { this->status_clear_error();
this->setup_status_ = SetupStatus::SUCCESSFUL;
this->status_clear_error();
} else {
this->mark_failed();
return;
}
});
return RetryResult::DONE; // 15ms delay matches datasheet, Adafruit_MS8607 & SparkFun_PHT_MS8607_Arduino_Library
}, this->set_timeout("prom-read", 15, [this]() {
5.0f); // executes at now, +5ms, +25ms if (this->read_calibration_values_from_prom_()) {
this->setup_status_ = SetupStatus::SUCCESSFUL;
this->status_clear_error();
} else {
this->mark_failed();
return;
}
});
} }
void MS8607Component::update() { void MS8607Component::update() {

View File

@@ -44,6 +44,8 @@ class MS8607Component : public PollingComponent, public i2c::I2CDevice {
void set_humidity_device(MS8607HumidityDevice *humidity_device) { humidity_device_ = humidity_device; } void set_humidity_device(MS8607HumidityDevice *humidity_device) { humidity_device_ = humidity_device; }
protected: 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. Read and store the Pressure & Temperature calibration settings from the PROM.
Intended to be called during setup(), this will set the `failure_reason_` 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; enum class SetupStatus;
/// Current step in the multi-step & possibly delayed setup() process /// Current step in the multi-step & possibly delayed setup() process
SetupStatus setup_status_; SetupStatus setup_status_;
uint32_t reset_interval_{5};
uint8_t reset_attempts_remaining_{0};
}; };
} // namespace ms8607 } // namespace ms8607