Fix MAX31865 edge case. (#882)

In a heavy EMI environment, reading the current config from the MAX31865 can
fail, such as switching from a 4-wire sensor to a 3-wire sensor. This causes
the temperature value to be off wildly, but still technically valid, so it
doesn't get reported as a sensor failure.

Since we know what configuration we want, rather than send it to the MAX31865
on setup and ask for it over and over (propagating any error as we write it
back), instead store the base configuration and work from that to change modes.
This not only avoids propagating any error, it also saves a lot of unnecessary
reads from the MAX31865.
This commit is contained in:
DAVe3283 2019-11-26 10:31:33 -07:00 committed by Otto Winter
parent fe89dcdc08
commit 36ffef083b
2 changed files with 19 additions and 11 deletions

View file

@ -37,7 +37,7 @@ void MAX31865Sensor::update() {
} }
// Run fault detection // Run fault detection
write_register_(CONFIGURATION_REG, 0b11101110, 0b10000110); this->write_config_(0b11101110, 0b10000110);
const uint32_t start_time = micros(); const uint32_t start_time = micros();
uint8_t config; uint8_t config;
uint32_t fault_detect_time; uint32_t fault_detect_time;
@ -55,7 +55,7 @@ void MAX31865Sensor::update() {
ESP_LOGV(TAG, "Fault detection completed in %uμs.", fault_detect_time); ESP_LOGV(TAG, "Fault detection completed in %uμs.", fault_detect_time);
// Start 1-shot conversion // Start 1-shot conversion
this->write_register_(CONFIGURATION_REG, 0b11100000, 0b10100000); this->write_config_(0b11100000, 0b10100000);
// Datasheet max conversion time is 55ms for 60Hz / 66ms for 50Hz // Datasheet max conversion time is 55ms for 60Hz / 66ms for 50Hz
auto f = std::bind(&MAX31865Sensor::read_data_, this); auto f = std::bind(&MAX31865Sensor::read_data_, this);
@ -66,13 +66,15 @@ void MAX31865Sensor::setup() {
ESP_LOGCONFIG(TAG, "Setting up MAX31865Sensor '%s'...", this->name_.c_str()); ESP_LOGCONFIG(TAG, "Setting up MAX31865Sensor '%s'...", this->name_.c_str());
this->spi_setup(); this->spi_setup();
// Build configuration // Build base configuration
uint8_t config = 0b00000010; base_config_ = 0b00000000;
config |= (filter_ & 1) << 0; base_config_ |= (filter_ & 1) << 0;
if (rtd_wires_ == 3) { if (rtd_wires_ == 3) {
config |= 1 << 4; base_config_ |= 1 << 4;
} }
this->write_register_(CONFIGURATION_REG, 0b11111111, config);
// Clear any existing faults & set base config
this->write_config_(0b00000010, 0b00000010);
} }
void MAX31865Sensor::dump_config() { void MAX31865Sensor::dump_config() {
@ -90,7 +92,7 @@ float MAX31865Sensor::get_setup_priority() const { return setup_priority::DATA;
void MAX31865Sensor::read_data_() { void MAX31865Sensor::read_data_() {
// Read temperature, disable V_BIAS (save power) // Read temperature, disable V_BIAS (save power)
const uint16_t rtd_resistance_register = this->read_register_16_(RTD_RESISTANCE_MSB_REG); const uint16_t rtd_resistance_register = this->read_register_16_(RTD_RESISTANCE_MSB_REG);
this->write_register_(CONFIGURATION_REG, 0b11000000, 0b00000000); this->write_config_(0b11000000, 0b00000000);
// Check faults // Check faults
const uint8_t faults = this->read_register_(FAULT_STATUS_REG); const uint8_t faults = this->read_register_(FAULT_STATUS_REG);
@ -137,12 +139,16 @@ void MAX31865Sensor::read_data_() {
this->publish_state(temperature); this->publish_state(temperature);
} }
void MAX31865Sensor::write_register_(uint8_t reg, uint8_t mask, uint8_t bits, uint8_t start_position) { void MAX31865Sensor::write_config_(uint8_t mask, uint8_t bits, uint8_t start_position) {
uint8_t value = this->read_register_(reg); uint8_t value = base_config_;
value &= (~mask); value &= (~mask);
value |= (bits << start_position); value |= (bits << start_position);
this->write_register_(CONFIGURATION_REG, value);
}
void MAX31865Sensor::write_register_(uint8_t reg, uint8_t value) {
this->enable(); this->enable();
this->write_byte(reg |= SPI_WRITE_M); this->write_byte(reg |= SPI_WRITE_M);
this->write_byte(value); this->write_byte(value);

View file

@ -43,10 +43,12 @@ class MAX31865Sensor : public sensor::Sensor,
float rtd_nominal_resistance_; float rtd_nominal_resistance_;
MAX31865ConfigFilter filter_; MAX31865ConfigFilter filter_;
uint8_t rtd_wires_; uint8_t rtd_wires_;
uint8_t base_config_;
bool has_fault_ = false; bool has_fault_ = false;
bool has_warn_ = false; bool has_warn_ = false;
void read_data_(); void read_data_();
void write_register_(uint8_t reg, uint8_t mask, uint8_t bits, uint8_t start_position = 0); void write_config_(uint8_t mask, uint8_t bits, uint8_t start_position = 0);
void write_register_(uint8_t reg, uint8_t value);
const uint8_t read_register_(uint8_t reg); const uint8_t read_register_(uint8_t reg);
const uint16_t read_register_16_(uint8_t reg); const uint16_t read_register_16_(uint8_t reg);
float calc_temperature_(const float& rtd_ratio); float calc_temperature_(const float& rtd_ratio);