diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index 87d769fec2..11b0ba2389 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -18,11 +18,23 @@ from esphome.components.esp32.const import ( CODEOWNERS = ["@esphome/core"] +adc_ns = cg.esphome_ns.namespace("adc") + + +""" +From the below patch versions (and 5.2+) ADC_ATTEN_DB_11 is deprecated and replaced with ADC_ATTEN_DB_12. +4.4.7 +5.0.5 +5.1.3 +5.2+ +""" + ATTENUATION_MODES = { "0db": cg.global_ns.ADC_ATTEN_DB_0, "2.5db": cg.global_ns.ADC_ATTEN_DB_2_5, "6db": cg.global_ns.ADC_ATTEN_DB_6, - "11db": cg.global_ns.ADC_ATTEN_DB_11, + "11db": adc_ns.ADC_ATTEN_DB_12_COMPAT, + "12db": adc_ns.ADC_ATTEN_DB_12_COMPAT, "auto": "auto", } diff --git a/esphome/components/adc/adc_sensor.cpp b/esphome/components/adc/adc_sensor.cpp index a9ac5a5cfe..1a76bdb264 100644 --- a/esphome/components/adc/adc_sensor.cpp +++ b/esphome/components/adc/adc_sensor.cpp @@ -62,7 +62,7 @@ extern "C" } // load characteristics for each attenuation - for (int32_t i = 0; i <= ADC_ATTEN_DB_11; i++) { + for (int32_t i = 0; i <= ADC_ATTEN_DB_12_COMPAT; i++) { auto adc_unit = channel1_ != ADC1_CHANNEL_MAX ? ADC_UNIT_1 : ADC_UNIT_2; auto cal_value = esp_adc_cal_characterize(adc_unit, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS, 1100, // default vref @@ -118,8 +118,8 @@ void ADCSensor::dump_config() { case ADC_ATTEN_DB_6: ESP_LOGCONFIG(TAG, " Attenuation: 6db"); break; - case ADC_ATTEN_DB_11: - ESP_LOGCONFIG(TAG, " Attenuation: 11db"); + case ADC_ATTEN_DB_12_COMPAT: + ESP_LOGCONFIG(TAG, " Attenuation: 12db"); break; default: // This is to satisfy the unused ADC_ATTEN_MAX break; @@ -183,12 +183,12 @@ float ADCSensor::sample() { return mv / 1000.0f; } - int raw11 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; + int raw12 = ADC_MAX, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX; if (channel1_ != ADC1_CHANNEL_MAX) { - adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_11); - raw11 = adc1_get_raw(channel1_); - if (raw11 < ADC_MAX) { + adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_12_COMPAT); + raw12 = adc1_get_raw(channel1_); + if (raw12 < ADC_MAX) { adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_6); raw6 = adc1_get_raw(channel1_); if (raw6 < ADC_MAX) { @@ -201,9 +201,9 @@ float ADCSensor::sample() { } } } else if (channel2_ != ADC2_CHANNEL_MAX) { - adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_11); - adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw11); - if (raw11 < ADC_MAX) { + adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_12_COMPAT); + adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw12); + if (raw12 < ADC_MAX) { adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_6); adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw6); if (raw6 < ADC_MAX) { @@ -217,25 +217,25 @@ float ADCSensor::sample() { } } - if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw11 == -1) { + if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw12 == -1) { return NAN; } - uint32_t mv11 = esp_adc_cal_raw_to_voltage(raw11, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_11]); + uint32_t mv12 = esp_adc_cal_raw_to_voltage(raw12, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_12_COMPAT]); uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_6]); uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_2_5]); uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int32_t) ADC_ATTEN_DB_0]); // Contribution of each value, in range 0-2048 (12 bit ADC) or 0-4096 (13 bit ADC) - uint32_t c11 = std::min(raw11, ADC_HALF); + uint32_t c12 = std::min(raw12, ADC_HALF); uint32_t c6 = ADC_HALF - std::abs(raw6 - ADC_HALF); uint32_t c2 = ADC_HALF - std::abs(raw2 - ADC_HALF); uint32_t c0 = std::min(ADC_MAX - raw0, ADC_HALF); // max theoretical csum value is 4096*4 = 16384 - uint32_t csum = c11 + c6 + c2 + c0; + uint32_t csum = c12 + c6 + c2 + c0; // each mv is max 3900; so max value is 3900*4096*4, fits in unsigned32 - uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0); + uint32_t mv_scaled = (mv12 * c12) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0); return mv_scaled / (float) (csum * 1000U); } #endif // USE_ESP32 diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index b1fdcd5d29..d99c4bc75b 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -1,19 +1,34 @@ #pragma once -#include "esphome/core/component.h" -#include "esphome/core/hal.h" -#include "esphome/core/defines.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/voltage_sampler/voltage_sampler.h" +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" #ifdef USE_ESP32 -#include "driver/adc.h" #include +#include "driver/adc.h" #endif namespace esphome { namespace adc { +#ifdef USE_ESP32 +// clang-format off +#if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 7)) || \ + (ESP_IDF_VERSION_MAJOR == 5 && \ + ((ESP_IDF_VERSION_MINOR == 0 && ESP_IDF_VERSION_PATCH >= 5) || \ + (ESP_IDF_VERSION_MINOR == 1 && ESP_IDF_VERSION_PATCH >= 3) || \ + (ESP_IDF_VERSION_MINOR >= 2)) \ + ) +// clang-format on +static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_12; +#else +static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_11; +#endif +#endif // USE_ESP32 + class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler { public: #ifdef USE_ESP32 diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index c1ae22214d..4cf3d52802 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -1,3 +1,5 @@ +import logging + import esphome.codegen as cg import esphome.config_validation as cv import esphome.final_validate as fv @@ -19,16 +21,29 @@ from . import ( ATTENUATION_MODES, ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, ESP32_VARIANT_ADC2_PIN_TO_CHANNEL, + adc_ns, validate_adc_pin, ) +_LOGGER = logging.getLogger(__name__) + AUTO_LOAD = ["voltage_sampler"] +_attenuation = cv.enum(ATTENUATION_MODES, lower=True) + + def validate_config(config): if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto": raise cv.Invalid("Automatic attenuation cannot be used when raw output is set") + if config.get(CONF_ATTENUATION) == "11db": + _LOGGER.warning( + "`attenuation: 11db` is deprecated, use `attenuation: 12db` instead" + ) + # Alter value here so `config` command prints the recommended change + config[CONF_ATTENUATION] = _attenuation("12db") + return config @@ -47,7 +62,6 @@ def final_validate_config(config): return config -adc_ns = cg.esphome_ns.namespace("adc") ADCSensor = adc_ns.class_( "ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler ) @@ -65,7 +79,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_PIN): validate_adc_pin, cv.Optional(CONF_RAW, default=False): cv.boolean, cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All( - cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True) + cv.only_on_esp32, _attenuation ), } ) diff --git a/esphome/const.py b/esphome/const.py index 2e5e9cc9de..786f988f91 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2024.5.0b5" +__version__ = "2024.5.0b6" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = (