Remove retry. API update

This commit is contained in:
Anton Sergunov 2024-05-07 10:33:31 +06:00
parent b2c5c5ef3b
commit e63e1212c9
2 changed files with 106 additions and 107 deletions

View file

@ -28,17 +28,31 @@ static const char *const TAG = "mlx90614";
void MLX90614Component::setup() {
ESP_LOGCONFIG(TAG, "Setting up MLX90614...");
if (!this->write_emissivity_()) {
this->emissivity_write_ec_ = this->write_emissivity_();
if(this->emissivity_write_ec_ != i2c::ERROR_OK) {
ESP_LOGE(TAG, "Communication with MLX90614 failed!");
this->mark_failed();
return;
}
}
bool MLX90614Component::write_emissivity_() {
if (std::isnan(this->emissivity_))
return true;
return this->write_register_(MLX90614_EMISSIVITY, this->emissivity_ * 0xFFFF);
i2c::ErrorCode MLX90614Component::write_emissivity_() {
if (std::isnan(this->emissivity_)) {
return i2c::ERROR_OK;
}
uint16_t read_emissivity;
const auto ec = read_register_(MLX90614_EMISSIVITY, read_emissivity);
if (i2c::ERROR_OK != ec) {
return ec;
}
const auto desired_emissivity = uint16_t(this->emissivity_ * 0xFFFF);
if (read_emissivity == desired_emissivity) {
return ec;
}
return this->write_register_(MLX90614_EMISSIVITY, desired_emissivity);
}
uint8_t MLX90614Component::crc8_pec_(const uint8_t *data, uint8_t len) {
@ -56,95 +70,82 @@ uint8_t MLX90614Component::crc8_pec_(const uint8_t *data, uint8_t len) {
return crc;
}
i2c::ErrorCode MLX90614Component::write_register_(uint8_t reg, uint16_t data, uint8_t max_try) {
i2c::ErrorCode MLX90614Component::write_register_(uint8_t reg, uint16_t data) {
uint8_t buf[5];
i2c::ErrorCode ec = i2c::ERROR_UNKNOWN;
auto init_buffer = [&]() {
buf[0] = this->address_ << 1;
buf[1] = reg;
};
// See 8.3.3.1. ERPROM write sequence
// 1. Power up the device
const uint8_t delay_ms = 10;
for (uint8_t i_try = 0; i_try < max_try; ++i_try) {
init_buffer();
buf[0] = this->address_ << 1;
buf[1] = reg;
// 2. Write 0x0000 into the cell of interest (effectively erasing the cell)
buf[2] = buf[3] = 0;
// 2. Write 0x0000 into the cell of interest (effectively erasing the cell)
buf[2] = buf[3] = 0;
buf[4] = this->crc8_pec_(buf, 4);
ec = this->write_register(reg, buf + 2, 3);
if (i2c::ERROR_OK != ec)) {
ESP_LOGW(TAG, "Can't clean register %x, error %d", reg, ec);
return ec;
}
// 3. Wait at least 5ms (10ms to be on the safe side)
delay(delay_ms);
// 4. Write the new value
if (data != 0) {
buf[2] = data & 0xFF;
buf[3] = data >> 8;
buf[4] = this->crc8_pec_(buf, 4);
if (!this->write_bytes(reg, buf + 2, 3)) {
ESP_LOGW(TAG, "Try %d: Can't clean register %x", i_try, reg);
ec = i2c::ERROR_UNKNOWN;
continue;
ec = this->write_register(reg, buf + 2, 3);
if (i2c::ERROR_OK != ec) {
ESP_LOGW(TAG, "Can't write register %x, error %d", reg, ec);
return ec;
}
// 3. Wait at least 5ms (10ms to be on the safe side)
// 5. Wait at least 5ms (10ms to be on the safe side)
delay(delay_ms);
// 4. Write the new value
if (data != 0) {
buf[2] = data & 0xFF;
buf[3] = data >> 8;
buf[4] = this->crc8_pec_(buf, 4);
if (!this->write_bytes(reg, buf + 2, 3)) {
ESP_LOGW(TAG, "Try %d: Can't write register %x", i_try, reg);
ec = i2c::ERROR_UNKNOWN;
continue;
}
// 5. Wait at least 5ms (10ms to be on the safe side)
delay(delay_ms);
}
uint8_t read_buf[3];
// 6. Read back and compare if the write was successful
ec = this->read_register(reg, read_buf, 3, false);
if (ec != i2c::ERROR_OK) {
ESP_LOGW(TAG, "Try %d: Can't check register value %x", i_try, reg);
continue;
}
if (read_buf[0] != buf[2] || read_buf[1] != buf[3] || read_buf[2] != buf[4]) {
ESP_LOGW(TAG, "Try %d: Read back value is not the same. Expected %x%x%x. Actual %x%x%x", i_try, buf[2], buf[3],
buf[4], read_buf[0], read_buf[1], read_buf[2]);
ec = i2c::ERROR_CRC;
continue;
}
return i2c::ERROR_OK;
}
ESP_LOGE(TAG, "Out of tries");
return ec;
uint8_t read_buf[3];
// 6. Read back and compare if the write was successful
ec = this->read_register(reg, read_buf, 3, false);
if (i2c::ERROR_OK != ec) {
ESP_LOGW(TAG, "Can't check register %x value", reg);
return ec;
}
if (read_buf[0] != buf[2] || read_buf[1] != buf[3] || read_buf[2] != buf[4]) {
ESP_LOGW(TAG, "Read back value is not the same. Expected %x%x%x. Actual %x%x%x", buf[2], buf[3], buf[4],
read_buf[0], read_buf[1], read_buf[2]);
return i2c::ERROR_CRC;
}
return i2c::ERROR_OK;
}
uint16_t MLX90614Component::read_register_(uint8_t reg, i2c::ErrorCode &ec, uint8_t max_try) {
uint8_t buf[6] = {
uint8_t(this->address_ << 1),
reg,
uint8_t(0x01 | (this->address_ << 1)),
};
for (uint8_t i_try = 0; i_try < max_try; ++i_try) {
ec = this->read_register(reg, buf + 3, 3, false);
i2c::ErrorCode MLX90614Component::read_register_(uint8_t reg, uint16_t &data) {
uint8_t buf[6];
// master write
buf[0] = this->address_ << 1;
buf[1] = reg;
// master read
buf[2] = (this->address_ << 1) | 0x01;
if (ec != i2c::ERROR_OK) {
ESP_LOGW(TAG, "Try %d: i2c read error %d", i_try, ec);
continue;
}
const auto ec = this->read_register(reg, buf + 3, 3, false);
const auto expected_pec = this->crc8_pec_(buf, 5);
if (buf[5] != expected_pec) {
ESP_LOGW(TAG, "Try %d: i2c CRC error. Expected %x. Actual %x", i_try, expected_pec, buf[4]);
ec = i2c::ERROR_CRC;
continue;
}
ec = i2c::ERROR_OK;
return encode_uint16(buf[4], buf[3]);
if (i2c::ERROR_OK != ec) {
ESP_LOGW(TAG, "Try %d: i2c read error %d", i_try, ec);
return ec;
}
return 0;
const auto expected_pec = this->crc8_pec_(buf, 5);
if (buf[5] != expected_pec) {
ESP_LOGW(TAG, "Try %d: i2c CRC error. Expected %x. Actual %x", i_try, expected_pec, buf[4]);
return i2c::ERROR_CRC;
}
data = encode_uint16(buf[4], buf[3]);
return i2c::ERROR_OK;
}
void MLX90614Component::dump_config() {
@ -153,6 +154,19 @@ void MLX90614Component::dump_config() {
if (this->is_failed()) {
ESP_LOGE(TAG, "Communication with MLX90614 failed!");
}
if(i2c::ERROR_OK != this->emissivity_write_ec_) {
ESP_LOGE(TAG, "Emissivity update error %d", this->emissivity_write_ec_);
}
if(i2c::ERROR_OK != this->object_read_ec_) {
ESP_LOGE(TAG, "Object temperature read error %d", this->object_read_ec_);
}
if(i2c::ERROR_OK != this->ambient_read_ec_) {
ESP_LOGE(TAG, "Ambient temperature read error %d", this->ambient_read_ec_);
}
LOG_UPDATE_INTERVAL(this);
LOG_SENSOR(" ", "Ambient", this->ambient_sensor_);
LOG_SENSOR(" ", "Object", this->object_sensor_);
@ -161,42 +175,24 @@ void MLX90614Component::dump_config() {
float MLX90614Component::get_setup_priority() const { return setup_priority::DATA; }
void MLX90614Component::update() {
bool write_emissivity_status = true;
if (!std::isnan(this->emissivity_)) {
i2c::ErrorCode ec = i2c::ERROR_OK;
const auto read_emissivity = read_register_(MLX90614_EMISSIVITY, ec);
if (ec == i2c::ERROR_OK) {
const auto desired_emissivity = uint16_t(this->emissivity_ * 0xFFFF);
if (read_emissivity != desired_emissivity) {
if (i2c::ERROR_OK != this->write_register_(MLX90614_EMISSIVITY, desired_emissivity)) {
write_emissivity_status = false;
}
}
} else {
write_emissivity_status = false;
}
}
this->emissivity_write_ec_ = this->write_emissivity_();
auto publish_sensor = [&](sensor::Sensor *sensor, uint8_t reg) {
if (nullptr == sensor) {
return true;
return i2c::ERROR_OK;
}
i2c::ErrorCode ec = i2c::ERROR_OK;
const auto raw = read_register_(reg, ec);
if (ec != i2c::ERROR_OK) {
sensor->publish_state(NAN);
return false;
}
float value = raw & 0x8000 ? NAN : raw * 0.02f - 273.15f;
sensor->publish_state(value);
return true;
uint16_t raw;
const auto ec = read_register_(reg, raw);
sensor->publish_state(ec != i2c::ERROR_OK || (raw & 0x8000) ? NAN : float(raw) * 0.02f - 273.15f);
return ec;
};
const auto object_updated = publish_sensor(this->object_sensor_, MLX90614_TEMPERATURE_OBJECT_1);
const auto ambient_updated = publish_sensor(this->ambient_sensor_, MLX90614_TEMPERATURE_AMBIENT);
this->object_read_ec_ = publish_sensor(this->object_sensor_, MLX90614_TEMPERATURE_OBJECT_1);
this->ambient_read_ec_ = publish_sensor(this->ambient_sensor_, MLX90614_TEMPERATURE_AMBIENT);
if (object_updated && ambient_updated && write_emissivity_status) {
if (this->ambient_read_ec_ == Зi2c::ERROR_OK && this->object_read_ec_ == i2c::ERROR_OK &&
this->emissivity_write_ec_ == i2c::ERROR_OK) {
this->status_clear_warning();
} else {
this->status_set_warning();

View file

@ -20,16 +20,19 @@ class MLX90614Component : public PollingComponent, public i2c::I2CDevice {
void set_emissivity(float emissivity) { emissivity_ = emissivity; }
protected:
bool write_emissivity_();
i2c::ErrorCode write_emissivity_();
uint8_t crc8_pec_(const uint8_t *data, uint8_t len);
i2c::ErrorCode write_register_(uint8_t reg, uint16_t data, uint8_t max_try = 2);
uint16_t read_register_(uint8_t reg, i2c::ErrorCode &ec, uint8_t max_try = 2);
i2c::ErrorCode write_register_(uint8_t reg, uint16_t data);
i2c::ErrorCode read_register_(uint8_t reg, uint16_t &data);
sensor::Sensor *ambient_sensor_{nullptr};
sensor::Sensor *object_sensor_{nullptr};
float emissivity_{NAN};
i2c::ErrorCode emissivity_write_ec_{i2c::ERROR_OK};
i2c::ErrorCode object_read_ec_{i2c::ERROR_OK};
i2c::ErrorCode ambient_read_ec_{i2c::ERROR_OK}З;
};
} // namespace mlx90614
} // namespace esphome