mirror of
https://github.com/esphome/esphome.git
synced 2026-05-10 05:37:55 +08:00
[gdk101] Retry reset on interval for slow-booting sensor MCU (#11750)
Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io>
This commit is contained in:
@@ -6,9 +6,15 @@ namespace esphome {
|
||||
namespace gdk101 {
|
||||
|
||||
static const char *const TAG = "gdk101";
|
||||
static const uint8_t NUMBER_OF_READ_RETRIES = 5;
|
||||
static constexpr uint8_t NUMBER_OF_READ_RETRIES = 5;
|
||||
static constexpr uint8_t NUMBER_OF_RESET_RETRIES = 10;
|
||||
static constexpr uint32_t RESET_INTERVAL_ID = 0;
|
||||
static constexpr uint32_t RESET_INTERVAL_MS = 1000;
|
||||
|
||||
void GDK101Component::update() {
|
||||
if (!this->reset_complete_)
|
||||
return;
|
||||
|
||||
uint8_t data[2];
|
||||
if (!this->read_dose_1m_(data)) {
|
||||
this->status_set_warning(LOG_STR("Failed to read dose 1m"));
|
||||
@@ -33,26 +39,45 @@ void GDK101Component::update() {
|
||||
}
|
||||
|
||||
void GDK101Component::setup() {
|
||||
uint8_t data[2];
|
||||
// first, reset the sensor
|
||||
if (!this->reset_sensor_(data)) {
|
||||
this->status_set_error(LOG_STR("Reset failed!"));
|
||||
this->mark_failed();
|
||||
return;
|
||||
if (!this->try_reset_()) {
|
||||
// Sensor MCU boots slowly after power cycle — retry on a short interval
|
||||
this->reset_retries_remaining_ = NUMBER_OF_RESET_RETRIES;
|
||||
this->set_interval(RESET_INTERVAL_ID, RESET_INTERVAL_MS, [this]() {
|
||||
if (this->try_reset_()) {
|
||||
if (this->reset_complete_) {
|
||||
this->update();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (--this->reset_retries_remaining_ == 0) {
|
||||
this->cancel_interval(RESET_INTERVAL_ID);
|
||||
this->mark_failed(LOG_STR("Reset failed after retries"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempt to reset the sensor and read firmware version. Returns true on success or hard failure.
|
||||
bool GDK101Component::try_reset_() {
|
||||
uint8_t data[2] = {0};
|
||||
if (!this->reset_sensor_(data)) {
|
||||
this->status_set_warning(LOG_STR("Sensor not answering reset, will retry"));
|
||||
return false;
|
||||
}
|
||||
// sensor should acknowledge success of the reset procedure
|
||||
if (data[0] != 1) {
|
||||
this->status_set_error(LOG_STR("Reset not acknowledged!"));
|
||||
this->mark_failed();
|
||||
return;
|
||||
this->status_set_warning(LOG_STR("Reset not acknowledged, will retry"));
|
||||
return false;
|
||||
}
|
||||
delay(10);
|
||||
// read firmware version
|
||||
if (!this->read_fw_version_(data)) {
|
||||
this->status_set_error(LOG_STR("Failed to read firmware version"));
|
||||
this->mark_failed();
|
||||
return;
|
||||
this->cancel_interval(RESET_INTERVAL_ID);
|
||||
this->mark_failed(LOG_STR("Failed to read firmware version"));
|
||||
return true;
|
||||
}
|
||||
this->reset_complete_ = true;
|
||||
this->status_clear_warning();
|
||||
this->cancel_interval(RESET_INTERVAL_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GDK101Component::dump_config() {
|
||||
@@ -92,12 +117,7 @@ bool GDK101Component::reset_sensor_(uint8_t *data) {
|
||||
// After sending reset command it looks that sensor start performing reset and is unresponsible during read
|
||||
// after a while we can send another reset command and read "0x01" as confirmation
|
||||
// Documentation not going in to such details unfortunately
|
||||
if (!this->read_bytes_with_retry_(GDK101_REG_RESET, data, 2)) {
|
||||
ESP_LOGE(TAG, "Updating GDK101 failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return this->read_bytes_with_retry_(GDK101_REG_RESET, data, 2);
|
||||
}
|
||||
|
||||
bool GDK101Component::read_dose_1m_(uint8_t *data) {
|
||||
|
||||
@@ -44,12 +44,15 @@ class GDK101Component : public PollingComponent, public i2c::I2CDevice {
|
||||
|
||||
protected:
|
||||
bool read_bytes_with_retry_(uint8_t a_register, uint8_t *data, uint8_t len);
|
||||
bool try_reset_();
|
||||
bool reset_sensor_(uint8_t *data);
|
||||
bool read_dose_1m_(uint8_t *data);
|
||||
bool read_dose_10m_(uint8_t *data);
|
||||
bool read_status_(uint8_t *data);
|
||||
bool read_fw_version_(uint8_t *data);
|
||||
bool read_measurement_duration_(uint8_t *data);
|
||||
bool reset_complete_{false};
|
||||
uint8_t reset_retries_remaining_{0};
|
||||
};
|
||||
|
||||
} // namespace gdk101
|
||||
|
||||
Reference in New Issue
Block a user