ADC Timeouts on ESP32-S3
Posted: 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:
Called with these inputs:
A sample output from a running ESP32:
Any hint on why this timeout might be occuring, and what I might be doing wrong here?
Thanks for the help,
Volker
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;
}
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();
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
Thanks for the help,
Volker