diff --git a/ads131m08/__init__.py b/ads131m08/__init__.py index 3b157f2..f596dc3 100644 --- a/ads131m08/__init__.py +++ b/ads131m08/__init__.py @@ -33,8 +33,15 @@ POWER_MODES = { 2: POWER_MODE.HIGH_RESOLUTION, # default 3: POWER_MODE.HIGH_RESOLUTION2, "very_low": POWER_MODE.VERY_LOW_POWER, + "very_low_power": POWER_MODE.VERY_LOW_POWER, "low": POWER_MODE.LOW_POWER, + "low_power": POWER_MODE.LOW_POWER, "high": POWER_MODE.HIGH_RESOLUTION, + "high_resolution": POWER_MODE.HIGH_RESOLUTION, + "very low": POWER_MODE.VERY_LOW_POWER, + "very low power": POWER_MODE.VERY_LOW_POWER, + "low power": POWER_MODE.LOW_POWER, + "high resolution": POWER_MODE.HIGH_RESOLUTION, } GLOBAL_CHOP_DELAY = ads131m08_ns.enum("ADC_GLOBAL_CHOP_DELAY") @@ -137,9 +144,11 @@ CONFIG_SCHEMA = ( async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) + id = config[CONF_ID] + var = cg.new_Pvariable(id) await cg.register_component(var, config) await spi.register_spi_device(var, config) + cg.add(var.set_id(str(id))) drdy = await cg.gpio_pin_expression(config[CONF_DRDY_PIN]) if CONF_SYNC_RESET_PIN in config: sync_reset = await cg.gpio_pin_expression(config[CONF_SYNC_RESET_PIN]) diff --git a/ads131m08/ads131m08.cpp b/ads131m08/ads131m08.cpp index ca03055..eba6f7e 100644 --- a/ads131m08/ads131m08.cpp +++ b/ads131m08/ads131m08.cpp @@ -63,31 +63,31 @@ void ADS131M08Hub::setup() { bool reset_ok = adc_reset_retry(); // ESP_LOGW(TAG, "adc word length: %d", adc_word_length_); if (!reset_ok) { - ESP_LOGE(TAG, "ADC reset failed!"); + ESP_LOGE(TAG, "ADC '%s' reset failed!", this->id_.c_str()); this->mark_failed(LOG_STR("Reset failed.")); this->adc_init_ = 0; return; } if (!this->adc_initialize(DEFAULT_WORD_LENGTH)) { - ESP_LOGE(TAG, "ADC reset failed!"); + ESP_LOGE(TAG, "ADC '%s' initialisation failed!", this->id_.c_str()); this->mark_failed(LOG_STR("Initialisation failed.")); this->adc_init_ = 0; return; } if (!adc_lock(true)) { - ESP_LOGE(TAG, "ADC lock failed!"); + ESP_LOGE(TAG, "ADC '%s' spi lock failed!", this->id_.c_str()); this->mark_failed(LOG_STR("ADC lock failed.")); this->adc_init_ = 0; return; } if (!adc_lock(false)) { - ESP_LOGE(TAG, "ADC unlock failed!"); + ESP_LOGE(TAG, "ADC '%s' spi unlock failed!", this->id_.c_str()); this->mark_failed(LOG_STR("ADC unlock failed.")); this->adc_init_ = 0; return; } if (!adc_backup_registers()) { - ESP_LOGE(TAG, "Backing up ADC registers failed!"); + ESP_LOGE(TAG, "Backing up ADC '%s' registers failed!", this->id_.c_str()); this->mark_failed(LOG_STR("ADC register backup failed.")); this->adc_init_ = 0; return; @@ -100,7 +100,7 @@ void ADS131M08Hub::setup() { } void ADS131M08Hub::dump_config() { - ESP_LOGCONFIG(TAG, "ADS131M08:"); + ESP_LOGCONFIG(TAG, "ADS131M08: '%s'", this->id_.c_str()); LOG_PIN(" CS Pin: ", this->cs_); LOG_PIN(" DRDY Pin: ", this->drdy_pin_); if (this->sync_reset_pin_ != nullptr) { @@ -116,15 +116,24 @@ void ADS131M08Hub::dump_config() { } else { ESP_LOGCONFIG(TAG, " Clock frequency: %.3fMHz", this->clock_frequency_ / 1000000); } - uint16_t osr = convert_adc_osr_to_value(this->osr_); - - ESP_LOGCONFIG(TAG, " Oversampling ratio: %" PRId32, osr); + ESP_LOGCONFIG(TAG, " Oversampling ratio: %" PRId32, convert_adc_osr_to_value(this->osr_)); ESP_LOGCONFIG(TAG, " Reference Voltage: %.2fV", this->reference_voltage_); + ESP_LOGCONFIG(TAG, " Power Mode: %s", + this->power_mode_ == VERY_LOW_POWER ? "'very low power'" + : this->power_mode_ == LOW_POWER ? "'low power'" + : "'high resolution'"); + ESP_LOGCONFIG(TAG, " Global Chop: %s", this->global_chop_enable_ ? "enable" : "disable"); + ESP_LOGCONFIG(TAG, " Global Chop Delay: %u", 1 << (1 + this->global_chop_delay_)); + ESP_LOGCONFIG(TAG, " Current Detect: %s", this->current_detect_enable_ ? "enable" : "disable"); + ESP_LOGCONFIG(TAG, " Current Detect All: %s", this->current_detect_all_enable_ ? "YES" : "NO"); + ESP_LOGCONFIG(TAG, " Current Detect Number: %u", 1 << this->current_detect_number_); + ESP_LOGCONFIG(TAG, " Current Detect Length: %u", convert_adc_cd_len_to_value(this->current_detect_length_)); + ESP_LOGCONFIG(TAG, " Current Detect Threshold: %ld", this->current_detect_threshold_); ESP_LOGCONFIG(TAG, " SPI Mode: %d", this->mode_); ESP_LOGCONFIG(TAG, " Bit Order: %s", - this->bit_order_ == 1 ? "msb_first" - : this->bit_order_ == 0 ? "lsb_first" - : "unknown"); + this->bit_order_ == spi::BIT_ORDER_MSB_FIRST ? "msb_first" + : this->bit_order_ == spi::BIT_ORDER_LSB_FIRST ? "lsb_first" + : "unknown"); // TODO: add new configs } @@ -345,7 +354,6 @@ void ADS131M08Hub::loop() return; } { - CHIP_SELECTx uint32_t start = micros(); uint32_t end; this->adc_sync(); @@ -356,7 +364,7 @@ void ADS131M08Hub::loop() uint32_t elapsed_time = 0; uint32_t settling_end_time = 2 * get_filter_settling_time(); int i = 0; - while(elapsed_time < settling_end_time) { + while(elapsed_time < settling_end_time && this->recover_count_ == 0) { setup_frame(rx_frame, numFrameWords); this->transfer_array(rx_frame); //ESP_LOGD(TAG, "frame: %s", frame_to_string(rx_frame).c_str()); @@ -365,8 +373,8 @@ void ADS131M08Hub::loop() auto status = get_unsigned_frame_word(rx_frame, 0, true); update_adc_word_length(status); if(status == RSP_RESET_OK) { - recover_from_reset(); - return; + //recover_from_reset(); + this->recover_count_++; } end = micros(); elapsed_time = end - start; @@ -374,52 +382,55 @@ void ADS131M08Hub::loop() //ESP_LOGD(TAG, "iter: %d, elapsed: %u, settle_t: %u", i, elapsed_time, settling_end_time); } //ESP_LOGD(TAG, "iters: %d, elapsed: %u, st: %u", i, elapsed_time, settling_end_time); - if (rms_calc_req_) { - float_str result = {0, 0, 0, 0, 0}; - result = read_multi(); - num_samples = result[0]; - crc_errors = result[1]; - iterations = result[2]; - not_ready = result[3]; - sps = result[4]; - uint64_t end = micros(); - //update_averages(SAMPLE_TIME_SENSOR, 1, static_cast(end - start) / 1000.0); - //update_averages(MAX_SAMPLES_SENSOR, 1, static_cast(num_samples)); - //update_averages(CRC_ERRORS_SENSOR, 1, static_cast(crc_errors)); - //uint16_t ctr = isr_ctr_; - //update_averages(ISR_COUNT_SENSOR, 1, static_cast(ctr)); - //update_averages(ITERATIONS_SENSOR, 1, static_cast(iterations)); - //update_averages(NOT_READY_SENSOR, 1, static_cast(not_ready)); + if(this->recover_count_ == 0) { + if (rms_calc_req_) { + float_str result = {0, 0, 0, 0, 0}; + result = read_multi(); + num_samples = result[0]; + crc_errors = result[1]; + iterations = result[2]; + not_ready = result[3]; + sps = result[4]; + uint64_t end = micros(); + //update_averages(SAMPLE_TIME_SENSOR, 1, static_cast(end - start) / 1000.0); + //update_averages(MAX_SAMPLES_SENSOR, 1, static_cast(num_samples)); + //update_averages(CRC_ERRORS_SENSOR, 1, static_cast(crc_errors)); + //uint16_t ctr = isr_ctr_; + //update_averages(ISR_COUNT_SENSOR, 1, static_cast(ctr)); + //update_averages(ITERATIONS_SENSOR, 1, static_cast(iterations)); + //update_averages(NOT_READY_SENSOR, 1, static_cast(not_ready)); - if(this->sensors_dc[SAMPLE_TIME_SENSOR] != nullptr) - this->sensors_dc[SAMPLE_TIME_SENSOR]->publish_state((end - start)/1000.0); - if(this->sensors_dc[MAX_SAMPLES_SENSOR] != nullptr) - this->sensors_dc[MAX_SAMPLES_SENSOR]->publish_state(num_samples); - if(this->sensors_dc[CRC_ERRORS_SENSOR] != nullptr) - this->sensors_dc[CRC_ERRORS_SENSOR]->publish_state(crc_errors); - if(this->sensors_dc[ISR_COUNT_SENSOR] != nullptr) { - uint16_t ctr = isr_ctr_; - this->sensors_dc[ISR_COUNT_SENSOR]->publish_state(ctr); + if(this->sensors_dc[SAMPLE_TIME_SENSOR] != nullptr) + this->sensors_dc[SAMPLE_TIME_SENSOR]->publish_state((end - start)/1000.0); + if(this->sensors_dc[MAX_SAMPLES_SENSOR] != nullptr) + this->sensors_dc[MAX_SAMPLES_SENSOR]->publish_state(num_samples); + if(this->sensors_dc[CRC_ERRORS_SENSOR] != nullptr) + this->sensors_dc[CRC_ERRORS_SENSOR]->publish_state(crc_errors); + if(this->sensors_dc[ISR_COUNT_SENSOR] != nullptr) { + uint16_t ctr = isr_ctr_; + this->sensors_dc[ISR_COUNT_SENSOR]->publish_state(ctr); + } + if(this->sensors_dc[ITERATIONS_SENSOR] != nullptr) + this->sensors_dc[ITERATIONS_SENSOR]->publish_state(iterations); + if(this->sensors_dc[NOT_READY_SENSOR] != nullptr) + this->sensors_dc[NOT_READY_SENSOR]->publish_state(not_ready); + if(this->sensors_dc[SPS_SENSOR] != nullptr) + this->sensors_dc[SPS_SENSOR]->publish_state(sps); + + } else { + read_single(); } - if(this->sensors_dc[ITERATIONS_SENSOR] != nullptr) - this->sensors_dc[ITERATIONS_SENSOR]->publish_state(iterations); - if(this->sensors_dc[NOT_READY_SENSOR] != nullptr) - this->sensors_dc[NOT_READY_SENSOR]->publish_state(not_ready); - if(this->sensors_dc[SPS_SENSOR] != nullptr) - this->sensors_dc[SPS_SENSOR]->publish_state(sps); - - } else { - read_single(); } isr_ctr_ = 0; } if (crc_errors > 30) { ESP_LOGW(TAG, "High CRC error rate."); + this->recover_count_++; + //recover_from_reset(); + } + if(this->recover_count_ > 0) { recover_from_reset(); - //int i = 4; - //while(i-- > 0 && !adc_set_word_length(DEFAULT_WORD_LENGTH)); // for some reason the adc occasionally reverts to 24bits; this will - // // reset the word length to what it should be - + return; } // ESP_LOGW(TAG, "%llu ms (%llu us), max samples: %u", (end - start)/1000, (end - start), num_samples); } @@ -792,6 +803,7 @@ bool ADS131M08Hub::set_measure_rms(uint8_t channel, bool enable) { } void ADS131M08Hub::read_single() { + CHIP_SELECTx setup_frame(rx_frame, numFrameWords); this->transfer_array(rx_frame); bool crc_ok = check_crc(rx_frame); @@ -847,6 +859,7 @@ float_str ADS131M08Hub::read_multi() { sample_sum_[i] = 0; sample_squared_sum_[i] = 0; } + CHIP_SELECTx uint32_t settling_end_time = loop_start_time; while ((elapsed_time < sample_time) && (iteration++ < 1000)) { result[2] = iteration; @@ -859,8 +872,9 @@ float_str ADS131M08Hub::read_multi() { update_adc_word_length(status); if(status == RSP_RESET_OK) { ESP_LOGI(TAG,"Reset frame: %s", frame_to_string(rx_frame).c_str()); - ESP_LOGW(TAG, "ADC reset detected. Trying recover"); - recover_from_reset(); + ESP_LOGW(TAG, "ADC reset detected. Trying to recover"); + this->recover_count_++; + //recover_from_reset(); return result; } crc_ok = check_crc(rx_frame); @@ -954,9 +968,9 @@ void ADS131M08Hub::recover_from_reset() { update_adc_word_length(WLENGTH_24_BITS); // word length is 24 bits after reset auto wait_after_reset = convert_adc_clock_cycles_to_micros(300); delay_microseconds_safe(wait_after_reset); - ESP_LOGW(TAG, "ADC reset detected. Trying to restore registers. Retries: %u", this->recover_count_); + ESP_LOGW(TAG, "ADC '%s' reset detected", this->id_.c_str()); if(this->adc_restore_registers()) { - ESP_LOGW(TAG, "Mid data-read reset detected; restored registers"); + ESP_LOGI(TAG, "Restored ADC '%s' registers", this->id_.c_str()); this->recover_count_ = 0; return; } @@ -1283,14 +1297,6 @@ uint16_t ADS131M08Hub::convert_value_to_adc_osr(uint16_t osr_value) { return adc_osr; } -uint16_t ADS131M08Hub::convert_adc_osr_to_value(uint16_t adc_osr) { - uint16_t osr_value = 1 << (7 + adc_osr); - if (osr_value == 16384) { - osr_value = 16256; - } - return osr_value; -} - bool ADS131M08Hub::set_channel_enable(uint8_t channel, bool enable) { if (channel >= ADC_CHANNELS) return false; @@ -1316,7 +1322,7 @@ bool ADS131M08Hub::set_osr() { } bool ADS131M08Hub::set_current_detect_threshold() { - int32_t threshold = this->cd_threshold_; + int32_t threshold = this->current_detect_threshold_; uint16_t MSB = (threshold >> 8) & MASK_THRSHLD_MSB_CD_TH_MSB; uint16_t LSB = (threshold << 8) & MASK_THRSHLD_LSB_CD_TH_LSB; uint16_str masks = {MASK_THRSHLD_MSB_CD_TH_MSB, MASK_THRSHLD_LSB_CD_TH_LSB}; @@ -1326,25 +1332,25 @@ bool ADS131M08Hub::set_current_detect_threshold() { bool ADS131M08Hub::set_current_detect_length() { uint16_t mask = MASK_CFG_CD_LEN; - uint16_t value = this->cd_length_ << 1; + uint16_t value = this->current_detect_length_ << 1; return adc_register_write_masked(REG_CFG, value, mask, __LINE__); } bool ADS131M08Hub::set_current_detect_number() { uint16_t mask = MASK_CFG_CD_NUM; - uint16_t value = this->cd_number_ << 4; + uint16_t value = this->current_detect_number_ << 4; return adc_register_write_masked(REG_CFG, value, mask, __LINE__); } bool ADS131M08Hub::set_current_detect_all() { uint16_t mask = MASK_CFG_CD_ALLCH; - uint16_t value = this->cd_all_enable_ ? mask : 0; + uint16_t value = this->current_detect_all_enable_ ? mask : 0; return adc_register_write_masked(REG_CFG, value, mask, __LINE__); } bool ADS131M08Hub::set_current_detect() { uint16_t mask = MASK_CFG_CD_EN; - uint16_t value = this->cd_enable_ ? mask : 0; + uint16_t value = this->current_detect_enable_ ? mask : 0; return adc_register_write_masked(REG_CFG, value, mask, __LINE__); } @@ -1673,39 +1679,11 @@ std::string ADS131M08Hub::reg_data_to_string(int address, uint16_t data, bool na str += " / CUR DET= ["; str += ((data & MASK_CFG_CD_EN) != 0) ? "Y] " : "N] "; str += ((data & MASK_CFG_CD_ALLCH) != 0) ? "ALL_CH" : "ANY_CH"; - auto cd_num = 1 << ((data & MASK_CFG_CD_NUM) >> 4); - snprintf(buffer, sizeof(buffer), " / CD_NUM= %d", cd_num); + auto current_detect_num = 1 << ((data & MASK_CFG_CD_NUM) >> 4); + snprintf(buffer, sizeof(buffer), " / CD_NUM= %d", current_detect_num); str += buffer; auto cd_len = (data & MASK_CFG_CD_LEN) >> 1; - switch (cd_len) { - case 0: - cd_len = 128; - break; - case 1: - cd_len = 256; - break; - case 2: - cd_len = 512; - break; - case 3: - cd_len = 768; - break; - case 4: - cd_len = 1280; - break; - case 5: - cd_len = 1792; - break; - case 6: - cd_len = 2560; - break; - case 7: - cd_len = 3584; - break; - default: - cd_len = 0; // illegal case - break; - } + cd_len = convert_adc_cd_len_to_value(cd_len); snprintf(buffer, sizeof(buffer), " / CD_LEN= %d", cd_len); str += buffer; break; diff --git a/ads131m08/ads131m08.h b/ads131m08/ads131m08.h index 6f34cd8..6a94d15 100644 --- a/ads131m08/ads131m08.h +++ b/ads131m08/ads131m08.h @@ -50,6 +50,7 @@ class ADS131M08Hub : public Component, friend class ads131m08_select; public: + static constexpr uint16_t current_detect_lengths[] = { 128, 256, 512, 768, 1280, 1792, 2560, 3584 }; // register config values used static constexpr uint16_t reg_clock_cfg = MASK_CLOCK_EXTREF_EN | HIGH_RESOLUTION; // OSR must be added static constexpr uint16_t reg_clock_allch_on = MASK_CLOCK_ALLCH | reg_clock_cfg; @@ -80,9 +81,9 @@ class ADS131M08Hub : public Component, adc_channel_settings chan[8]; //uint16_t regmap_crc; }; - union regmap { + union regmap { adc_register_settings reg; - uint16_t data[sizeof(adc_register_settings)/2]; + uint16_t data[sizeof(adc_register_settings)/sizeof(uint16_t)]; }; // Semaphore handles @@ -102,6 +103,7 @@ class ADS131M08Hub : public Component, void setup() override; void loop() override; + void set_id(const std::string &id) { this->id_ = id; } void set_drdy_pin(InternalGPIOPin *pin) { drdy_pin_ = pin; } void set_sync_reset_pin(InternalGPIOPin *pin) { sync_reset_pin_ = pin; } void set_clock_frequency(float clock_frequency) { this->clock_frequency_ = clock_frequency; } @@ -118,11 +120,11 @@ class ADS131M08Hub : public Component, bool set_channel_phase_calibration(uint8_t channel, int16_t phase_offset); bool set_dcblock_filter_disable(uint8_t channel, bool disable); bool set_channel_gain(uint8_t channel, uint8_t gain); - void set_current_detect_threshold(int32_t threshold) { this->cd_threshold_ = threshold; } - void set_current_detect_length(uint16_t length) { this->cd_length_ = length; } - void set_current_detect_number(uint16_t number) { this->cd_number_ = number; } - void set_current_detect_all(bool enable) { this->cd_all_enable_ = enable; } - void set_current_detect(bool enable) { this->cd_enable_ = enable; } + void set_current_detect_threshold(int32_t threshold) { this->current_detect_threshold_ = threshold; } + void set_current_detect_length(uint16_t length) { this->current_detect_length_ = length; } + void set_current_detect_number(uint16_t number) { this->current_detect_number_ = number; } + void set_current_detect_all(bool enable) { this->current_detect_all_enable_ = enable; } + void set_current_detect(bool enable) { this->current_detect_enable_ = enable; } void set_global_chop_delay(uint16_t delay) { this->global_chop_delay_ = delay; } void set_global_chop(bool enable) { this->global_chop_enable_ = enable; } void set_power_mode(uint16_t power_mode) { this->power_mode_ = power_mode; } @@ -145,10 +147,12 @@ class ADS131M08Hub : public Component, //float get_average(uint8_t channel, bool read_ac); bool set_osr(); uint16_t convert_value_to_adc_osr(uint16_t osr_value); - uint16_t convert_adc_osr_to_value(uint16_t adc_osr); uint32_t convert_adc_clock_cycles_to_micros(uint32_t cycles); + uint16_t convert_adc_osr_to_value(uint16_t adc_osr) { auto osr = 1 << (7 + adc_osr); return (osr == 16384) ? 16256 : osr; } + uint16_t convert_adc_cd_len_to_value(uint16_t adc_cd_len) { return adc_cd_len >= sizeof(current_detect_lengths) ? 0 : current_detect_lengths[adc_cd_len]; } protected: + std::string id_; HighFrequencyLoopRequester high_freq_; static void IRAM_ATTR isr_handler(ADS131M08Hub *arg); float reference_voltage_; @@ -164,11 +168,11 @@ class ADS131M08Hub : public Component, uint16_t osr_{3}; uint16_t global_chop_delay_{16}; bool global_chop_enable_{false}; - int32_t cd_threshold_{0}; - uint16_t cd_length_{128}; - uint16_t cd_number_{1}; - bool cd_all_enable_{false}; - bool cd_enable_{false}; + int32_t current_detect_threshold_{0}; + uint16_t current_detect_length_{128}; + uint16_t current_detect_number_{1}; + bool current_detect_all_enable_{false}; + bool current_detect_enable_{false}; uint16_t power_mode_{2}; uint16_t dcblock_filter_{0}; uint8_t update_adc_word_length(); @@ -224,11 +228,9 @@ class ADS131M08Hub : public Component, void recover_from_reset(); //DRAM_ATTR static spiframe rx_frame; - inline void zero_fill(spiframe& frame) { - std::fill(frame.begin(), frame.end(), 0); - } + void zero_fill(spiframe& frame) { std::fill(frame.begin(), frame.end(), 0); } - inline size_t setup_frame(spiframe& frame, uint8_t word_count) { + size_t setup_frame(spiframe& frame, uint8_t word_count) { int word_nbytes = this->adc_word_length_ >> 3; frame.resize(word_nbytes * word_count); zero_fill(frame); diff --git a/ads131m08/sensor/__init__.py b/ads131m08/sensor/__init__.py index 266e024..2f1c242 100644 --- a/ads131m08/sensor/__init__.py +++ b/ads131m08/sensor/__init__.py @@ -62,7 +62,7 @@ Channel = ads131m08_ns.class_( CONFIG_SCHEMA = ( sensor.sensor_schema( Channel, - accuracy_decimals=6, + accuracy_decimals=2, icon=ICON_CURRENT_DC, unit_of_measurement=UNIT_VOLT, device_class=DEVICE_CLASS_VOLTAGE, diff --git a/ads131m08/sensor/ads131m08_sensor.cpp b/ads131m08/sensor/ads131m08_sensor.cpp index fc3d00d..c4427a7 100644 --- a/ads131m08/sensor/ads131m08_sensor.cpp +++ b/ads131m08/sensor/ads131m08_sensor.cpp @@ -82,7 +82,6 @@ void Channel::dump_config() { : "invalid"); } - void RMS_Sensor::loop() { if(!this->set_calc_rms_) { @@ -95,10 +94,6 @@ void RMS_Sensor::loop() } } } - //else { - // float value = this->parent_->get_average(this->calc_rms_); - // publish_state(value); - //} } void RMS_Sensor::dump_config()