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:
@@ -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() {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user