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__); }