[ESP32 ADC] Add option for raw uncalibrated output (#2663)

This commit is contained in:
Carlos Garcia Saura 2021-11-10 19:12:57 +01:00 committed by GitHub
parent 2ac232e634
commit 219b225ac0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 11 deletions

View file

@ -91,17 +91,21 @@ void ADCSensor::dump_config() {
float ADCSensor::get_setup_priority() const { return setup_priority::DATA; } float ADCSensor::get_setup_priority() const { return setup_priority::DATA; }
void ADCSensor::update() { void ADCSensor::update() {
float value_v = this->sample(); float value_v = this->sample();
ESP_LOGD(TAG, "'%s': Got voltage=%.2fV", this->get_name().c_str(), value_v); ESP_LOGD(TAG, "'%s': Got voltage=%.4fV", this->get_name().c_str(), value_v);
this->publish_state(value_v); this->publish_state(value_v);
} }
#ifdef USE_ESP8266 #ifdef USE_ESP8266
float ADCSensor::sample() { float ADCSensor::sample() {
#ifdef USE_ADC_SENSOR_VCC #ifdef USE_ADC_SENSOR_VCC
return ESP.getVcc() / 1024.0f; // NOLINT(readability-static-accessed-through-instance) int raw = ESP.getVcc(); // NOLINT(readability-static-accessed-through-instance)
#else #else
return analogRead(this->pin_->get_pin()) / 1024.0f; // NOLINT int raw = analogRead(this->pin_->get_pin()); // NOLINT
#endif #endif
if (output_raw_) {
return raw;
}
return raw / 1024.0f;
} }
#endif #endif
@ -112,6 +116,9 @@ float ADCSensor::sample() {
if (raw == -1) { if (raw == -1) {
return NAN; return NAN;
} }
if (output_raw_) {
return raw;
}
uint32_t mv = esp_adc_cal_raw_to_voltage(raw, &cal_characteristics_[(int) attenuation_]); uint32_t mv = esp_adc_cal_raw_to_voltage(raw, &cal_characteristics_[(int) attenuation_]);
return mv / 1000.0f; return mv / 1000.0f;
} }
@ -135,10 +142,6 @@ float ADCSensor::sample() {
if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw11 == -1) { if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw11 == -1) {
return NAN; return NAN;
} }
// prevent divide by zero
if (raw0 == 0 && raw2 == 0 && raw6 == 0 && raw11 == 0) {
return 0;
}
uint32_t mv11 = esp_adc_cal_raw_to_voltage(raw11, &cal_characteristics_[(int) ADC_ATTEN_DB_11]); uint32_t mv11 = esp_adc_cal_raw_to_voltage(raw11, &cal_characteristics_[(int) ADC_ATTEN_DB_11]);
uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int) ADC_ATTEN_DB_6]); uint32_t mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int) ADC_ATTEN_DB_6]);

View file

@ -31,6 +31,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
/// `HARDWARE_LATE` setup priority. /// `HARDWARE_LATE` setup priority.
float get_setup_priority() const override; float get_setup_priority() const override;
void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; } void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; }
void set_output_raw(bool output_raw) { output_raw_ = output_raw; }
float sample() override; float sample() override;
#ifdef USE_ESP8266 #ifdef USE_ESP8266
@ -39,8 +40,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
protected: protected:
InternalGPIOPin *pin_; InternalGPIOPin *pin_;
uint16_t read_raw_(); bool output_raw_{false};
uint32_t raw_to_microvolts_(uint16_t raw);
#ifdef USE_ESP32 #ifdef USE_ESP32
adc_atten_t attenuation_{ADC_ATTEN_DB_0}; adc_atten_t attenuation_{ADC_ATTEN_DB_0};

View file

@ -4,6 +4,7 @@ from esphome import pins
from esphome.components import sensor, voltage_sampler from esphome.components import sensor, voltage_sampler
from esphome.const import ( from esphome.const import (
CONF_ATTENUATION, CONF_ATTENUATION,
CONF_RAW,
CONF_ID, CONF_ID,
CONF_INPUT, CONF_INPUT,
CONF_NUMBER, CONF_NUMBER,
@ -119,12 +120,18 @@ def validate_adc_pin(value):
raise NotImplementedError raise NotImplementedError
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.")
return config
adc_ns = cg.esphome_ns.namespace("adc") 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
) )
CONFIG_SCHEMA = ( CONFIG_SCHEMA = cv.All(
sensor.sensor_schema( sensor.sensor_schema(
unit_of_measurement=UNIT_VOLT, unit_of_measurement=UNIT_VOLT,
accuracy_decimals=2, accuracy_decimals=2,
@ -135,12 +142,14 @@ CONFIG_SCHEMA = (
{ {
cv.GenerateID(): cv.declare_id(ADCSensor), cv.GenerateID(): cv.declare_id(ADCSensor),
cv.Required(CONF_PIN): validate_adc_pin, cv.Required(CONF_PIN): validate_adc_pin,
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, cv.enum(ATTENUATION_MODES, lower=True)
), ),
} }
) )
.extend(cv.polling_component_schema("60s")) .extend(cv.polling_component_schema("60s")),
validate_config,
) )
@ -155,6 +164,9 @@ async def to_code(config):
pin = await cg.gpio_pin_expression(config[CONF_PIN]) pin = await cg.gpio_pin_expression(config[CONF_PIN])
cg.add(var.set_pin(pin)) cg.add(var.set_pin(pin))
if CONF_RAW in config:
cg.add(var.set_output_raw(config[CONF_RAW]))
if CONF_ATTENUATION in config: if CONF_ATTENUATION in config:
if config[CONF_ATTENUATION] == "auto": if config[CONF_ATTENUATION] == "auto":
cg.add(var.set_autorange(cg.global_ns.true)) cg.add(var.set_autorange(cg.global_ns.true))