mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 13:34:54 +01:00
commit
ad0a1c5c35
5 changed files with 64 additions and 23 deletions
|
@ -18,11 +18,23 @@ from esphome.components.esp32.const import (
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
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 = {
|
ATTENUATION_MODES = {
|
||||||
"0db": cg.global_ns.ADC_ATTEN_DB_0,
|
"0db": cg.global_ns.ADC_ATTEN_DB_0,
|
||||||
"2.5db": cg.global_ns.ADC_ATTEN_DB_2_5,
|
"2.5db": cg.global_ns.ADC_ATTEN_DB_2_5,
|
||||||
"6db": cg.global_ns.ADC_ATTEN_DB_6,
|
"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",
|
"auto": "auto",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ extern "C"
|
||||||
}
|
}
|
||||||
|
|
||||||
// load characteristics for each attenuation
|
// 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 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,
|
auto cal_value = esp_adc_cal_characterize(adc_unit, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS,
|
||||||
1100, // default vref
|
1100, // default vref
|
||||||
|
@ -118,8 +118,8 @@ void ADCSensor::dump_config() {
|
||||||
case ADC_ATTEN_DB_6:
|
case ADC_ATTEN_DB_6:
|
||||||
ESP_LOGCONFIG(TAG, " Attenuation: 6db");
|
ESP_LOGCONFIG(TAG, " Attenuation: 6db");
|
||||||
break;
|
break;
|
||||||
case ADC_ATTEN_DB_11:
|
case ADC_ATTEN_DB_12_COMPAT:
|
||||||
ESP_LOGCONFIG(TAG, " Attenuation: 11db");
|
ESP_LOGCONFIG(TAG, " Attenuation: 12db");
|
||||||
break;
|
break;
|
||||||
default: // This is to satisfy the unused ADC_ATTEN_MAX
|
default: // This is to satisfy the unused ADC_ATTEN_MAX
|
||||||
break;
|
break;
|
||||||
|
@ -183,12 +183,12 @@ float ADCSensor::sample() {
|
||||||
return mv / 1000.0f;
|
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) {
|
if (channel1_ != ADC1_CHANNEL_MAX) {
|
||||||
adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_11);
|
adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_12_COMPAT);
|
||||||
raw11 = adc1_get_raw(channel1_);
|
raw12 = adc1_get_raw(channel1_);
|
||||||
if (raw11 < ADC_MAX) {
|
if (raw12 < ADC_MAX) {
|
||||||
adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_6);
|
adc1_config_channel_atten(channel1_, ADC_ATTEN_DB_6);
|
||||||
raw6 = adc1_get_raw(channel1_);
|
raw6 = adc1_get_raw(channel1_);
|
||||||
if (raw6 < ADC_MAX) {
|
if (raw6 < ADC_MAX) {
|
||||||
|
@ -201,9 +201,9 @@ float ADCSensor::sample() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (channel2_ != ADC2_CHANNEL_MAX) {
|
} else if (channel2_ != ADC2_CHANNEL_MAX) {
|
||||||
adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_11);
|
adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_12_COMPAT);
|
||||||
adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw11);
|
adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw12);
|
||||||
if (raw11 < ADC_MAX) {
|
if (raw12 < ADC_MAX) {
|
||||||
adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_6);
|
adc2_config_channel_atten(channel2_, ADC_ATTEN_DB_6);
|
||||||
adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw6);
|
adc2_get_raw(channel2_, ADC_WIDTH_MAX_SOC_BITS, &raw6);
|
||||||
if (raw6 < ADC_MAX) {
|
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;
|
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 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 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]);
|
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)
|
// 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 c6 = ADC_HALF - std::abs(raw6 - ADC_HALF);
|
||||||
uint32_t c2 = ADC_HALF - std::abs(raw2 - ADC_HALF);
|
uint32_t c2 = ADC_HALF - std::abs(raw2 - ADC_HALF);
|
||||||
uint32_t c0 = std::min(ADC_MAX - raw0, ADC_HALF);
|
uint32_t c0 = std::min(ADC_MAX - raw0, ADC_HALF);
|
||||||
// max theoretical csum value is 4096*4 = 16384
|
// 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
|
// 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);
|
return mv_scaled / (float) (csum * 1000U);
|
||||||
}
|
}
|
||||||
#endif // USE_ESP32
|
#endif // USE_ESP32
|
||||||
|
|
|
@ -1,19 +1,34 @@
|
||||||
#pragma once
|
#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/sensor/sensor.h"
|
||||||
#include "esphome/components/voltage_sampler/voltage_sampler.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
|
#ifdef USE_ESP32
|
||||||
#include "driver/adc.h"
|
|
||||||
#include <esp_adc_cal.h>
|
#include <esp_adc_cal.h>
|
||||||
|
#include "driver/adc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace adc {
|
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 {
|
class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler {
|
||||||
public:
|
public:
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
import esphome.final_validate as fv
|
import esphome.final_validate as fv
|
||||||
|
@ -19,16 +21,29 @@ from . import (
|
||||||
ATTENUATION_MODES,
|
ATTENUATION_MODES,
|
||||||
ESP32_VARIANT_ADC1_PIN_TO_CHANNEL,
|
ESP32_VARIANT_ADC1_PIN_TO_CHANNEL,
|
||||||
ESP32_VARIANT_ADC2_PIN_TO_CHANNEL,
|
ESP32_VARIANT_ADC2_PIN_TO_CHANNEL,
|
||||||
|
adc_ns,
|
||||||
validate_adc_pin,
|
validate_adc_pin,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
AUTO_LOAD = ["voltage_sampler"]
|
AUTO_LOAD = ["voltage_sampler"]
|
||||||
|
|
||||||
|
|
||||||
|
_attenuation = cv.enum(ATTENUATION_MODES, lower=True)
|
||||||
|
|
||||||
|
|
||||||
def validate_config(config):
|
def validate_config(config):
|
||||||
if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto":
|
if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto":
|
||||||
raise cv.Invalid("Automatic attenuation cannot be used when raw output is set")
|
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
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,7 +62,6 @@ def final_validate_config(config):
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
adc_ns = cg.esphome_ns.namespace("adc")
|
|
||||||
ADCSensor = adc_ns.class_(
|
ADCSensor = adc_ns.class_(
|
||||||
"ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler
|
"ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler
|
||||||
)
|
)
|
||||||
|
@ -65,7 +79,7 @@ CONFIG_SCHEMA = cv.All(
|
||||||
cv.Required(CONF_PIN): validate_adc_pin,
|
cv.Required(CONF_PIN): validate_adc_pin,
|
||||||
cv.Optional(CONF_RAW, default=False): cv.boolean,
|
cv.Optional(CONF_RAW, default=False): cv.boolean,
|
||||||
cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All(
|
cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All(
|
||||||
cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True)
|
cv.only_on_esp32, _attenuation
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
__version__ = "2024.5.0b5"
|
__version__ = "2024.5.0b6"
|
||||||
|
|
||||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||||
|
|
Loading…
Reference in a new issue