From 799407c6be8636e0b31cd8ba6662fced7fdf680d Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 5 May 2026 23:29:56 +0200 Subject: [PATCH] Trying to recover from spurious ADC resets. Not successful. TODO: implement polling method instead of interrupts with setting up of ADC on each poll. If it is too lengthy to execute, then will try only setting up on detection of resets. --- ads131m08/__init__.py | 10 +-- ads131m08/ads131m08.cpp | 151 +++++++++++++++++++++------------------- 2 files changed, 84 insertions(+), 77 deletions(-) diff --git a/ads131m08/__init__.py b/ads131m08/__init__.py index ac8563d..5b7f33b 100644 --- a/ads131m08/__init__.py +++ b/ads131m08/__init__.py @@ -18,7 +18,7 @@ ads131m08_ns = cg.esphome_ns.namespace("ads131m08") ADS131M08Hub = ads131m08_ns.class_("ADS131M08Hub", cg.Component, spi.SPIDevice) OSR = ads131m08_ns.enum("ADS131M08_OVERSAMPLING_RATIO") -ALLOWED_OSRS = { +OSRS = { 128: OSR.OSR_128, 256: OSR.OSR_256, 512: OSR.OSR_512, @@ -29,7 +29,7 @@ ALLOWED_OSRS = { 16256: OSR.OSR_16256, } -ALLOWED_CLOCK_FREQUENCIES = { +CLOCK_FREQUENCIES = { 2048000: 2048000, 4096000: 4096000, 8192000: 8192000, @@ -48,10 +48,10 @@ CONFIG_SCHEMA = ( cv.Required(CONF_DRDY_PIN): pins.internal_gpio_input_pin_schema, cv.Optional(CONF_SYNC_RESET_PIN): pins.internal_gpio_input_pin_schema, cv.Optional(CONF_CLOCK_FREQUENCY, default="8192kHz"): cv.All( - cv.frequency, cv.one_of(*ALLOWED_CLOCK_FREQUENCIES.keys()) + cv.frequency, cv.one_of(*CLOCK_FREQUENCIES.keys()) ), cv.Optional(CONF_OVERSAMPLING_RATIO, default=1024): cv.enum( - ALLOWED_OSRS, int=True + OSRS, int=True ), cv.Optional(CONF_REFERENCE_VOLTAGE, default=1.2): cv.float_range( min=1.1, max=1.3 @@ -71,7 +71,7 @@ async def to_code(config): if CONF_SYNC_RESET_PIN in config: sync_reset = await cg.gpio_pin_expression(config[CONF_SYNC_RESET_PIN]) cg.add(var.set_sync_reset_pin(sync_reset)) - clock_frequency = ALLOWED_CLOCK_FREQUENCIES[config[CONF_CLOCK_FREQUENCY]] + clock_frequency = CLOCK_FREQUENCIES[config[CONF_CLOCK_FREQUENCY]] cg.add(var.set_clock_frequency(clock_frequency)) osr = config[CONF_OVERSAMPLING_RATIO] cg.add(var.set_osr(osr)) diff --git a/ads131m08/ads131m08.cpp b/ads131m08/ads131m08.cpp index 14d8006..05b49dc 100644 --- a/ads131m08/ads131m08.cpp +++ b/ads131m08/ads131m08.cpp @@ -9,6 +9,8 @@ #include "esp_system.h" #include "spi_flash_mmap.h" +# include "driver/spi_master.h" + // using namespace esphome::spi; /* @@ -226,6 +228,9 @@ bool ADS131M08Hub::adc_restore_registers() { int j = 0; int store_nwords = sizeof(settings.data) / sizeof(settings.data[0]); success = adc_register_write(j + REG_MODE, settings.data[j], __LINE__, false); + if(!success) { + ESP_LOGD(TAG, "restoring %s reg: %04X failed", reg_addr_to_string(j + REG_MODE).c_str(), settings.data[j]); + } j++; while(success && (j < store_nwords)) { int i = 0; @@ -322,6 +327,14 @@ void ADS131M08Hub::loop() uint64_t start = micros(); ///this->txf_init(); // implementing datasheet recommended TXF init this->adc_sync(); + int freq = 0; + //if(delegate_ != nullptr){ + // esp_err_t ret = spi_device_get_actual_freq((SPIDelegateHw)delegate_->handle_, &freq); + // if (ret != ESP_OK) { + // ESP_LOGE(TAG, "SPI get actual frequency failed!"); + // } + // ESP_LOGD(TAG, "spi_freq: %u", freq); + //} if (rms_calc_req_) { float_str result = read_multi(); num_samples = result[0]; @@ -797,51 +810,68 @@ float_str ADS131M08Hub::read_multi() { //ESP_LOGD(TAG, "frame_word%d: %s", 0, frame_words_to_string(rx_frame, 0, 1).c_str()); status = get_unsigned_frame_word(rx_frame, 0, true); update_adc_word_length(status); - crc_ok = check_crc(rx_frame); - if (crc_ok) { - if(status & MASK_STATUS_RESET) { - if(adc_reset_retry()) { - if(adc_restore_registers()) { - ESP_LOGW(TAG, "Mid data-read reset detected; restored registers"); - return result; - } - } - ESP_LOGE(TAG, "ADC reset detected. Unable to recover"); - this->mark_failed(LOG_STR("ADC reset detected. Recovery failed")); + if(status & MASK_STATUS_RESET) { + ESP_LOGI(TAG,"Reset frame: %s", frame_to_string(rx_frame).c_str()); + ESP_LOGW(TAG, "ADC reset detected. Trying recover"); + if (!adc_register_write(REG_MODE, MODE_MASK_RESET_HAPPENED & reg_mode_cfg32, __LINE__)) { + ESP_LOGE(TAG, "MODE register write / read to set word size to 32bits failed"); return result; } - else { - if(status & MASK_STATUS_RESYNC) { - settling_end_time = elapsed_time + get_filter_settling_time() + 50; // add 50us for good measure + this->set_timeout("reset detected", 250, [this, result]() { + ESP_LOGE(TAG, "ADC reset detected. Trying to restore registers"); + if(this->adc_restore_registers()) { + ESP_LOGW(TAG, "Mid data-read reset detected; restored registers"); + //delay_microseconds_safe(get_filter_settling_time() + 50); + txf_init(); + return result; } - if(elapsed_time > settling_end_time) { - if ((status & MASK_STATUS_RESYNC) == 0) { - drdy_status = status & MASK_STATUS_DRDY; - // sample channels - if(drdy_status == 0){ - result[3]++; - } - for (i = 0; i < ADC_CHANNELS && drdy_status != 0; i++) { - data_ready = drdy_status & 1; - drdy_status = drdy_status >> 1; - if (data_ready) { - this->sampled_values_[i] = value; - ac_sensor_exist = this->sensors_ac[i] != nullptr; - dc_sensor_exist = this->sensors_dc[i] != nullptr; - if (ac_sensor_exist || dc_sensor_exist) { - raw = get_sign_ext_frame_word(rx_frame, i + 1); - value = this->conversion_factor_ * raw; - if (this->rms_enabled_[i]) { - (this->num_samples_[i])++; - (this->sample_sum_[i]) += value; - (this->sample_squared_sum_[i]) += value * value; - } else { - if(ac_sensor_exist) - this->sensors_ac[i]->publish_state(value); - if(dc_sensor_exist) - this->sensors_dc[i]->publish_state(value); - //update_averages(i, value, value); - } + ESP_LOGE(TAG, "ADC reset detected. Unable to recover"); + //this->mark_failed(LOG_STR("ADC reset detected. Recovery failed")); + return result; + }); + //if(adc_reset_retry()) { + // if(adc_restore_registers()) { + // ESP_LOGW(TAG, "Mid data-read reset detected; restored registers"); + // return result; + // } + //} + //ESP_LOGE(TAG, "ADC reset detected. Unable to recover"); + //this->mark_failed(LOG_STR("ADC reset detected. Recovery failed")); + //ESP_LOGE(TAG, "ADC reset detected"); + return result; + } + crc_ok = check_crc(rx_frame); + if (crc_ok) { + if(status & MASK_STATUS_RESYNC) { + settling_end_time = elapsed_time + get_filter_settling_time() + 50; // add 50us for good measure + } + if(elapsed_time > settling_end_time) { + if ((status & MASK_STATUS_RESYNC) == 0) { + drdy_status = status & MASK_STATUS_DRDY; + // sample channels + if(drdy_status == 0){ + result[3]++; + } + for (i = 0; i < ADC_CHANNELS && drdy_status != 0; i++) { + data_ready = drdy_status & 1; + drdy_status = drdy_status >> 1; + if (data_ready) { + this->sampled_values_[i] = value; + ac_sensor_exist = this->sensors_ac[i] != nullptr; + dc_sensor_exist = this->sensors_dc[i] != nullptr; + if (ac_sensor_exist || dc_sensor_exist) { + raw = get_sign_ext_frame_word(rx_frame, i + 1); + value = this->conversion_factor_ * raw; + if (this->rms_enabled_[i]) { + (this->num_samples_[i])++; + (this->sample_sum_[i]) += value; + (this->sample_squared_sum_[i]) += value * value; + } else { + if(ac_sensor_exist) + this->sensors_ac[i]->publish_state(value); + if(dc_sensor_exist) + this->sensors_dc[i]->publish_state(value); + //update_averages(i, value, value); } } } @@ -1021,16 +1051,14 @@ bool ADS131M08Hub::adc_register_write_masked(uint8_t address, uint16_t value, ui // reg_contents[0],address, value,mask, line ); auto new_value = (reg_contents[0] & ~mask) | (value & mask); if(new_value == reg_contents[0]) { - ESP_LOGW(TAG, "1: No update needed. reg: %02X data: %04X / %04X Line: %d", address, value, new_value, line); + //ESP_LOGW(TAG, "No updt: %-13s: newv %04X old regval %04X mskd %04X Line: %d", reg_addr_to_string(address).c_str(), value, reg_contents[0], new_value, line); int bup_index = address - REG_MODE; - ESP_LOGW(TAG, "Storing: %-13s: data %04X stored val: %04X Line: %d", reg_addr_to_string(bup_index + REG_MODE).c_str(), value, settings.data[bup_index], line); + //ESP_LOGW(TAG, "Storing: %-13s: data %04X stored val %04X Line %d", reg_addr_to_string(address).c_str(), value, settings.data[bup_index], line); // we backup data irrespective settings.data[bup_index] = value; return true; // no need for an adc reg update } reg_contents[0] = new_value; - //ESP_LOGW(TAG, "After applying mask - reg contents: 0x%04X, caller: %d", reg_contents[0], line ); - //ESP_LOGD(TAG, "adc_register_write_masked: address: %02X value: %04X reg_contents: %04X mask: %04X new value: %04X Line:%d", address, value, reg_contents[0], mask, new_value, line); return adc_register_write(address, reg_contents, line); } /// @brief @@ -1063,7 +1091,6 @@ bool ADS131M08Hub::adc_register_write_masked(uint8_t start_address, const uint16 if(reg_contents[i] != new_value) update_required = true; reg_contents[i] = new_value; - //ESP_LOGW(TAG, "After applying mask - reg contents: 0x%04X, caller: %d", reg_contents[i], line); } if(!update_required) { //ESP_LOGW(TAG, "2: No update needed. start reg: %02X first data: %04X Line: %d", start_address, values[0], line); @@ -1092,8 +1119,8 @@ bool ADS131M08Hub::adc_register_write(uint16_t start_address, const uint16_str & if(backup_data) { int bup_index = start_address - REG_MODE; for(auto i = data.begin(); i != data.end(); i++) { - ESP_LOGW(TAG, "Storing: %-13s: data %04X stored val: %04X Line: %d", reg_addr_to_string(bup_index + REG_MODE).c_str(), *i, settings.data[bup_index], line); - settings.data[bup_index++] = *i; + //ESP_LOGW(TAG, "Storing: %-13s: data %04X stored val: %04X Line: %d", reg_addr_to_string(bup_index + REG_MODE).c_str(), *i, settings.data[bup_index], line); + settings.data[bup_index++] = *i; } } else { @@ -1120,7 +1147,7 @@ bool ADS131M08Hub::adc_register_write(uint16_t start_address, const uint16_str & set_frame_word(rx_frame, i + 1, data[i]); } add_crc(rx_frame); - //ESP_LOGD(TAG, "%s\n", rwreg_command_frame_to_string(rx_frame).c_str()); + ESP_LOGD(TAG, "%s\n", rwreg_command_frame_to_string(rx_frame).c_str()); //ESP_LOGD(TAG, "Send Frame: %s", frame_to_string(rx_frame).c_str()); transfer_array(rx_frame); // WREG } @@ -1135,7 +1162,7 @@ bool ADS131M08Hub::adc_register_write(uint16_t start_address, const uint16_str & if (!verified) { ESP_LOGE(TAG, "Write \'%s\' register failed: tx data: 0x%04X, rx data: 0x%04X", reg_addr_to_string(start_address + i).c_str(), data[i], rxdata[i]); // ESP_LOGE(TAG, "Write: %s", reg_data_to_string(start_address + i, data[i]).c_str()); -// ESP_LOGE(TAG, "Ack : %s", reg_data_to_string(start_address + i, rxdata[i]).c_str()); + ESP_LOGE(TAG, "Ack : %s", reg_data_to_string(start_address + i, rxdata[i]).c_str()); } } delay_microseconds_safe(T_REGACQ); @@ -1191,7 +1218,6 @@ uint16_str ADS131M08Hub::adc_register_read(uint8_t address, uint8_t nregs) { offset = 1; rreg_ack = get_unsigned_frame_word(rx_frame, 0, true); } - // uint16_t rreg_ack = (nregs == 1) ? rreg_addr_opcode : get_unsigned_frame_word(rx_frame, 0, true); nregs = (rreg_ack & MASK_CMD_RW_REG_COUNT) + 1; uint16_t start_addr = (rreg_ack & MASK_CMD_RW_REG_ADDRESS) >> 7; @@ -1206,9 +1232,6 @@ uint16_str ADS131M08Hub::adc_register_read(uint8_t address, uint8_t nregs) { bool ADS131M08Hub::set_reg_osr() { uint16_t mask = MASK_CLOCK_OSR; uint16_t value = this->osr_ << 2; - // ESP_LOGD(TAG, "adc_register_write_masked(REG_CLOCK=%02X, value=%04X, mask=%04X, __LINE__)", REG_CLOCK, - // value, mask); - //this->settings.reg.clock = value & mask; return adc_register_write_masked(REG_CLOCK, value, mask, __LINE__); } @@ -1240,9 +1263,6 @@ bool ADS131M08Hub::set_channel_enable(uint8_t channel, bool enable) { return false; uint16_t mask = MASK_CLOCK_CH0 << channel; uint16_t value = (enable) ? mask : 0; - // ESP_LOGD(TAG, "adc_register_write_masked(REG_CLOCK=%02X, value=%04X, mask=%04X, __LINE__)", REG_CLOCK, - // value, mask); - //this->settings.reg.clock = value & mask; return adc_register_write_masked(REG_CLOCK, value, mask, __LINE__); } @@ -1253,11 +1273,6 @@ bool ADS131M08Hub::set_channel_gain(uint8_t channel, uint8_t gain) { uint8_t shift = (channel % 4) << 2; uint16_t mask = MASK_GAIN_PGAGAIN0 << shift; uint16_t value = gain << shift; - //if(reg == REG_GAIN1) - //this->settings.reg.gain1 = value & mask; - //else - //this->settings.reg.gain2 = value & mask; - // ESP_LOGW(TAG, "Ch%d: Set Gain: reg: %02X pga: %04X mask: %04X ", channel, reg, value, mask); return adc_register_write_masked(reg, value, mask, __LINE__); } @@ -1271,7 +1286,6 @@ bool ADS131M08Hub::set_global_chop(uint16_t global_chop) { bool ADS131M08Hub::set_global_chop_delay(uint16_t delay) { uint16_t mask = MASK_CFG_GC_DLY; uint16_t value = delay << 9; - //this->settings.reg.cfg = value & mask; return adc_register_write_masked(REG_CFG, value, mask, __LINE__); } @@ -1283,7 +1297,6 @@ bool ADS131M08Hub::set_channel_phase_calibration(uint8_t channel, int16_t phase_ return false; uint16_t mask = MASK_CHX_CFG_PHASE; uint16_t value = phase_offset << 6; - ////this->settings.reg.chan[channel].ch_cfg = value & mask; return adc_register_write_masked(reg_addr, value, mask, __LINE__); } @@ -1293,8 +1306,7 @@ bool ADS131M08Hub::set_dcblock_filter_disable(uint8_t channel, bool disable) { uint16_t reg_addr = 5 * channel + REG_CH0_CFG; uint16_t mask = MASK_CHX_CFG_DCBLKX_DIS; uint16_t value = (disable) ? mask : 0; - ////this->settings.reg.chan[channel].ch_cfg = value & mask; - ESP_LOGI(TAG, "Setting DC BLOCK of Ch%d reg:%02X to %s [%04X]", channel, reg_addr, (disable ? "disable" : "enable"), value); + //ESP_LOGI(TAG, "Setting DC BLOCK of Ch%d reg:%02X to %s [%04X]", channel, reg_addr, (disable ? "disable" : "enable"), value); return adc_register_write_masked(reg_addr, value, mask, __LINE__); } @@ -1304,7 +1316,6 @@ bool ADS131M08Hub::set_channel_input_selection(uint8_t channel, ADC_INPUT_CHANNE uint16_t reg_addr = 5 * channel + REG_CH0_CFG; uint16_t mask = MASK_CHX_CFG_MUX; uint16_t value = input; - ////this->settings.reg.chan[channel].ch_cfg = value & mask; return adc_register_write_masked(reg_addr, value, mask, __LINE__); } @@ -1319,8 +1330,6 @@ bool ADS131M08Hub::set_channel_offset_calibration(uint8_t channel, int32_t offse uint16_str masks = {MASK_CHX_OCAL_MSB, MASK_CHX_OCAL_LSB}; uint16_str values = {MSB, LSB}; - ////this->settings.reg.chan[channel].ch_ocal_msb = values[0] & masks[0]; - //this->settings.reg.chan[channel].ch_ocal_lsb = values[1] & masks[1]; return adc_register_write_masked(reg_addr, values, masks, __LINE__); } @@ -1335,8 +1344,6 @@ bool ADS131M08Hub::set_channel_gain_calibration(uint8_t channel, uint32_t gain) uint16_t reg_addr = 5 * channel + REG_CH0_GCAL_MSB; uint16_str masks = {MASK_CHX_GCAL_MSB, MASK_CHX_GCAL_LSB}; uint16_str values = {MSB, LSB}; - //this->settings.reg.chan[channel].ch_gcal_msb = values[0] & masks[0]; - //this->settings.reg.chan[channel].ch_gcal_lsb = values[1] & masks[1]; return adc_register_write_masked(reg_addr, values, masks, __LINE__); }