ADC Timeouts on ESP32-S3

volcore
Posts: 2
Joined: Fri Dec 01, 2023 2:11 pm

ADC Timeouts on ESP32-S3

Postby volcore » Fri Dec 01, 2023 2:22 pm

Hi,

We're using the ESP32-S3-WROOM-1-N16R2 for our boards. It is connected to two PT103J2 Thermistors on GPIO4 and GPIO5. We're using ADC continuous mode to sample them.

We're using the official release branch of ESP-IDF 5.1.2 commit 482a8fb2d78e3b58eb21b26da8a5bedf90623213 (https://github.com/espressif/esp-idf/re ... tag/v5.1.2).

However, we're running into an issue where after about 300s, adc_read_continuous will return ESP_ERR_TIMEOUT. All further reads also return an ESP_ERR_TIMEOUT. The only way to recover is to run adc_continuous_stop(); adc_continuous_start(); to unstuck them, at which point it works for another 300s (sometimes we need to stop & start twice before it recovers).

This is the related code:

Code: Select all

struct ADCContinuous : public ADCUnit {
  ADCContinuous(adc_unit_t unit);
  ~ADCContinuous();

  void ConfigureChannel(adc_channel_t channel, adc_atten_t atten, adc_bitwidth_t bitwidth) override;
  void FinishConfigure() override;

  int GetRaw(adc_channel_t channel) override;
  void TryGet();

  adc_unit_t unit;
  adc_continuous_handle_t handle = nullptr;
  std::vector<adc_digi_pattern_config_t> patterns;
  std::vector<adc_digi_output_data_t> results;
};

ADCContinuous::ADCContinuous(adc_unit_t unit) : unit(unit) {
}

ADCContinuous::~ADCContinuous() {
  if (handle != nullptr) {
    adc_continuous_stop(handle);
    adc_continuous_deinit(handle);
    handle = nullptr;
  }
}

void ADCContinuous::ConfigureChannel(adc_channel_t channel, adc_atten_t atten, adc_bitwidth_t bitwidth) {
  patterns.push_back({
                         .atten = atten,
                         .channel = channel,
                         .unit = unit,
                         .bit_width = bitwidth,
                     });
}

void ADCContinuous::FinishConfigure() {
  results.resize(64);
  bzero(results.data(), results.size() * sizeof(results[0]));
  adc_continuous_handle_cfg_t adc_config = {
      .max_store_buf_size = 1024,
      .conv_frame_size = 256,
  };
  auto err = adc_continuous_new_handle(&adc_config, &handle);
  if (err != ESP_OK) {
    Debug::Error(kLogTag, "Failed to create new cont ADC unit: (%d) %s", err, esp_err_to_name(err));
  }
  adc_continuous_config_t dig_cfg = {
      .pattern_num = patterns.size(),
      .adc_pattern = patterns.data(),
      .sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH,
      .conv_mode = unit == ADC_UNIT_1 ? ADC_CONV_SINGLE_UNIT_1 : ADC_CONV_SINGLE_UNIT_2,
      .format = ADC_DIGI_OUTPUT_FORMAT_TYPE2,
  };
  err = adc_continuous_config(handle, &dig_cfg);
  if (err != ESP_OK) {
    Debug::Error(kLogTag, "Failed to configure cont ADC unit: (%d) %s", err, esp_err_to_name(err));
  }
  err = adc_continuous_start(handle);
  if (err != ESP_OK) {
    Debug::Error(kLogTag, "Failed to start cont ADC unit: (%d) %s", err, esp_err_to_name(err));
  }
}

void ADCContinuous::TryGet() {
  uint32_t ret_num = 0;
  auto err = adc_continuous_read(handle,
                                 RCAST(uint8_t * , results.data()),
                                 results.size() * sizeof(results[0]),
                                 &ret_num,
                                 0);
  if (err != ESP_OK) {
    Debug::Error(kLogTag, "Failed to read cont ADC channel: (%d) %s", err, esp_err_to_name(err));
    Debug::Info(kLogTag, "Unstucking ADC");
    // try to restart if it fails
    err = adc_continuous_stop(handle);
    if (err != ESP_OK) {
      Debug::Error(kLogTag, "Failed to stop cont ADC channel: (%d) %s", err, esp_err_to_name(err));
    }
    err = adc_continuous_start(handle);
    if (err != ESP_OK) {
      Debug::Error(kLogTag, "Failed to restart cont ADC channel: (%d) %s", err, esp_err_to_name(err));
    }
    return;
  }
}

int ADCContinuous::GetRaw(adc_channel_t channel) {
  TryGet();
  // Find the most recent result for this channel
  for (auto const &result : results) {
    if (result.type2.channel == channel) {
      return result.type2.data;
    }
  }
  return -1;
}
Called with these inputs:

Code: Select all

  temp_adc->ConfigureChannel(pins.relay_temp_channel, ADC_ATTEN_DB_11, ADC_BITWIDTH_12);
  temp_adc->ConfigureChannel(pins.power_supply_temp_channel, ADC_ATTEN_DB_11, ADC_BITWIDTH_12);
  temp_adc->FinishConfigure();
A sample output from a running ESP32:

Code: Select all

E (3483293) ORANGE: <ADCU> [00] Failed to read cont ADC channel: (263) ESP_ERR_TIMEOUT
I (3483294) ORANGE: <ADCU> [00] Unstucking ADC
E (3663300) ORANGE: <ADCU> [00] Failed to read cont ADC channel: (263) ESP_ERR_TIMEOUT
I (3663300) ORANGE: <ADCU> [00] Unstucking ADC
E (3663301) ORANGE: <ADCU> [00] Failed to read cont ADC channel: (263) ESP_ERR_TIMEOUT
I (3663302) ORANGE: <ADCU> [00] Unstucking ADC
E (3963308) ORANGE: <ADCU> [00] Failed to read cont ADC channel: (263) ESP_ERR_TIMEOUT
I (3963308) ORANGE: <ADCU> [00] Unstucking ADC
E (3963309) ORANGE: <ADCU> [00] Failed to read cont ADC channel: (263) ESP_ERR_TIMEOUT
I (3963310) ORANGE: <ADCU> [00] Unstucking ADC
E (4263316) ORANGE: <ADCU> [00] Failed to read cont ADC channel: (263) ESP_ERR_TIMEOUT
I (4263316) ORANGE: <ADCU> [00] Unstucking ADC
E (4263317) ORANGE: <ADCU> [00] Failed to read cont ADC channel: (263) ESP_ERR_TIMEOUT
I (4263318) ORANGE: <ADCU> [00] Unstucking ADC
Any hint on why this timeout might be occuring, and what I might be doing wrong here?

Thanks for the help,
Volker

ZiyadEd
Posts: 1
Joined: Wed May 22, 2024 5:26 pm

Re: ADC Timeouts on ESP32-S3

Postby ZiyadEd » Wed May 22, 2024 5:29 pm

Hello I'm facing the same issue, but for me it was reliably working, but then without any changes it started timing out 100% of the time no matter what I do. Have you found any workaround or solution.

I have a esp32c3 and I'm using esp-idf

Thanks in advance.

Who is online

Users browsing this forum: nspode and 86 guests