From f0de56a797ad6f2c677e5a447b97ba5a3c802a40 Mon Sep 17 00:00:00 2001 From: Simon Jouet Date: Mon, 15 Jul 2019 05:32:48 +0100 Subject: [PATCH] ESP32 HAL - Dynamic ADC attenuation (#14623) --- Marlin/src/HAL/HAL_ESP32/HAL.cpp | 53 ++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/Marlin/src/HAL/HAL_ESP32/HAL.cpp b/Marlin/src/HAL/HAL_ESP32/HAL.cpp index 37bba69260..907b3a9858 100644 --- a/Marlin/src/HAL/HAL_ESP32/HAL.cpp +++ b/Marlin/src/HAL/HAL_ESP32/HAL.cpp @@ -67,7 +67,9 @@ uint16_t HAL_adc_result; // Private Variables // ------------------------ -esp_adc_cal_characteristics_t characteristics; +esp_adc_cal_characteristics_t characteristics[ADC_ATTEN_MAX]; +adc_atten_t attenuations[ADC1_CHANNEL_MAX] = {}; +uint32_t thresholds[ADC_ATTEN_MAX]; volatile int numPWMUsed = 0, pwmPins[MAX_PWM_PINS], pwmValues[MAX_PWM_PINS]; @@ -129,49 +131,74 @@ adc1_channel_t get_channel(int pin) { return ADC1_CHANNEL_MAX; } +void adc1_set_attenuation(adc1_channel_t chan, adc_atten_t atten) { + if (attenuations[chan] != atten) { + adc1_config_channel_atten(chan, atten); + attenuations[chan] = atten; + } +} + void HAL_adc_init() { // Configure ADC adc1_config_width(ADC_WIDTH_12Bit); // Configure channels only if used as (re-)configuring a pin for ADC that is used elsewhere might have adverse effects #if HAS_TEMP_ADC_0 - adc1_config_channel_atten(get_channel(TEMP_0_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db); #endif #if HAS_TEMP_ADC_1 - adc1_config_channel_atten(get_channel(TEMP_1_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db); #endif #if HAS_TEMP_ADC_2 - adc1_config_channel_atten(get_channel(TEMP_2_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db); #endif #if HAS_TEMP_ADC_3 - adc1_config_channel_atten(get_channel(TEMP_3_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db); #endif #if HAS_TEMP_ADC_4 - adc1_config_channel_atten(get_channel(TEMP_4_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db); #endif #if HAS_TEMP_ADC_5 - adc1_config_channel_atten(get_channel(TEMP_5_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db); #endif #if HAS_HEATED_BED - adc1_config_channel_atten(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db); #endif #if HAS_TEMP_CHAMBER - adc1_config_channel_atten(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db); #endif #if ENABLED(FILAMENT_WIDTH_SENSOR) - adc1_config_channel_atten(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db); + adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db); #endif // Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail. // That's why we're not setting it up here. - // Calculate ADC characteristics i.e. gain and offset factors - esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, V_REF, &characteristics); + // Calculate ADC characteristics (i.e., gain and offset factors for each attenuation level) + for (int i = 0; i < ADC_ATTEN_MAX; i++) { + esp_adc_cal_characterize(ADC_UNIT_1, (adc_atten_t)i, ADC_WIDTH_BIT_12, V_REF, &characteristics[i]); + + // Change attenuation 100mV below the calibrated threshold + thresholds[i] = esp_adc_cal_raw_to_voltage(4095, &characteristics[i]); + } } void HAL_adc_start_conversion(uint8_t adc_pin) { + const adc1_channel_t chan = get_channel(adc_pin); uint32_t mv; - esp_adc_cal_get_voltage((adc_channel_t)get_channel(adc_pin), &characteristics, &mv); + esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); + + // Change the attenuation level based on the new reading + adc_atten_t atten; + if (mv < thresholds[ADC_ATTEN_DB_0] - 100) + adc1_set_attenuation(chan, ADC_ATTEN_DB_0); + else if (mv > thresholds[ADC_ATTEN_DB_0] - 50 && mv < thresholds[ADC_ATTEN_DB_2_5] - 100) + adc1_set_attenuation(chan, ADC_ATTEN_DB_2_5); + else if (mv > thresholds[ADC_ATTEN_DB_2_5] - 50 && mv < thresholds[ADC_ATTEN_DB_6] - 100) + adc1_set_attenuation(chan, ADC_ATTEN_DB_6); + else if (mv > thresholds[ADC_ATTEN_DB_6] - 50) + adc1_set_attenuation(chan, ADC_ATTEN_DB_11); + HAL_adc_result = mv * 1023.0 / 3300.0; }