mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	ESP32 ADC use factory calibration data (#2574)
This commit is contained in:
		| @@ -16,50 +16,6 @@ namespace adc { | |||||||
|  |  | ||||||
| static const char *const TAG = "adc"; | static const char *const TAG = "adc"; | ||||||
|  |  | ||||||
| #ifdef USE_ESP32 |  | ||||||
| inline adc1_channel_t gpio_to_adc1(uint8_t pin) { |  | ||||||
| #if CONFIG_IDF_TARGET_ESP32 |  | ||||||
|   switch (pin) { |  | ||||||
|     case 36: |  | ||||||
|       return ADC1_CHANNEL_0; |  | ||||||
|     case 37: |  | ||||||
|       return ADC1_CHANNEL_1; |  | ||||||
|     case 38: |  | ||||||
|       return ADC1_CHANNEL_2; |  | ||||||
|     case 39: |  | ||||||
|       return ADC1_CHANNEL_3; |  | ||||||
|     case 32: |  | ||||||
|       return ADC1_CHANNEL_4; |  | ||||||
|     case 33: |  | ||||||
|       return ADC1_CHANNEL_5; |  | ||||||
|     case 34: |  | ||||||
|       return ADC1_CHANNEL_6; |  | ||||||
|     case 35: |  | ||||||
|       return ADC1_CHANNEL_7; |  | ||||||
|     default: |  | ||||||
|       return ADC1_CHANNEL_MAX; |  | ||||||
|   } |  | ||||||
| #elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 |  | ||||||
|   switch (pin) { |  | ||||||
|     case 0: |  | ||||||
|       return ADC1_CHANNEL_0; |  | ||||||
|     case 1: |  | ||||||
|       return ADC1_CHANNEL_1; |  | ||||||
|     case 2: |  | ||||||
|       return ADC1_CHANNEL_2; |  | ||||||
|     case 3: |  | ||||||
|       return ADC1_CHANNEL_3; |  | ||||||
|     case 4: |  | ||||||
|       return ADC1_CHANNEL_4; |  | ||||||
|     default: |  | ||||||
|       return ADC1_CHANNEL_MAX; |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| void ADCSensor::set_attenuation(adc_atten_t attenuation) { this->attenuation_ = attenuation; } |  | ||||||
| void ADCSensor::set_autorange(bool autorange) { this->autorange_ = autorange; } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| void ADCSensor::setup() { | void ADCSensor::setup() { | ||||||
|   ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str()); |   ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str()); | ||||||
| #ifndef USE_ADC_SENSOR_VCC | #ifndef USE_ADC_SENSOR_VCC | ||||||
| @@ -67,15 +23,36 @@ void ADCSensor::setup() { | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
|   if (this->autorange_) |  | ||||||
|     this->attenuation_ = ADC_ATTEN_DB_11; |  | ||||||
|   adc1_config_channel_atten(gpio_to_adc1(pin_->get_pin()), attenuation_); |  | ||||||
|   adc1_config_width(ADC_WIDTH_BIT_12); |   adc1_config_width(ADC_WIDTH_BIT_12); | ||||||
| #if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 |   if (!autorange_) { | ||||||
|   adc_gpio_init(ADC_UNIT_1, (adc_channel_t) gpio_to_adc1(pin_->get_pin())); |     adc1_config_channel_atten(channel_, attenuation_); | ||||||
| #endif |   } | ||||||
|  |  | ||||||
|  |   // load characteristics for each attenuation | ||||||
|  |   for (int i = 0; i < (int) ADC_ATTEN_MAX; i++) { | ||||||
|  |     auto cal_value = esp_adc_cal_characterize(ADC_UNIT_1, (adc_atten_t) i, ADC_WIDTH_BIT_12, | ||||||
|  |                                               1100,  // default vref | ||||||
|  |                                               &cal_characteristics_[i]); | ||||||
|  |     switch (cal_value) { | ||||||
|  |       case ESP_ADC_CAL_VAL_EFUSE_VREF: | ||||||
|  |         ESP_LOGV(TAG, "Using eFuse Vref for calibration"); | ||||||
|  |         break; | ||||||
|  |       case ESP_ADC_CAL_VAL_EFUSE_TP: | ||||||
|  |         ESP_LOGV(TAG, "Using two-point eFuse Vref for calibration"); | ||||||
|  |         break; | ||||||
|  |       case ESP_ADC_CAL_VAL_DEFAULT_VREF: | ||||||
|  |       default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // adc_gpio_init doesn't exist on ESP32-C3 or ESP32-H2 | ||||||
|  | #if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32H2) | ||||||
|  |   adc_gpio_init(ADC_UNIT_1, (adc_channel_t) channel_); | ||||||
| #endif | #endif | ||||||
|  | #endif  // USE_ESP32 | ||||||
| } | } | ||||||
|  |  | ||||||
| void ADCSensor::dump_config() { | void ADCSensor::dump_config() { | ||||||
|   LOG_SENSOR("", "ADC Sensor", this); |   LOG_SENSOR("", "ADC Sensor", this); | ||||||
| #ifdef USE_ESP8266 | #ifdef USE_ESP8266 | ||||||
| @@ -84,7 +61,8 @@ void ADCSensor::dump_config() { | |||||||
| #else | #else | ||||||
|   LOG_PIN("  Pin: ", pin_); |   LOG_PIN("  Pin: ", pin_); | ||||||
| #endif | #endif | ||||||
| #endif | #endif  // USE_ESP8266 | ||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
|   LOG_PIN("  Pin: ", pin_); |   LOG_PIN("  Pin: ", pin_); | ||||||
|   if (autorange_) |   if (autorange_) | ||||||
| @@ -106,101 +84,81 @@ void ADCSensor::dump_config() { | |||||||
|       default:  // This is to satisfy the unused ADC_ATTEN_MAX |       default:  // This is to satisfy the unused ADC_ATTEN_MAX | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| #endif | #endif  // USE_ESP32 | ||||||
|   LOG_UPDATE_INTERVAL(this); |   LOG_UPDATE_INTERVAL(this); | ||||||
| } | } | ||||||
|  |  | ||||||
| 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=%.2fV", this->get_name().c_str(), value_v); | ||||||
|   this->publish_state(value_v); |   this->publish_state(value_v); | ||||||
| } | } | ||||||
| uint16_t ADCSensor::read_raw_() { |  | ||||||
| #ifdef USE_ESP32 |  | ||||||
|   return adc1_get_raw(gpio_to_adc1(pin_->get_pin())); |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef USE_ESP8266 | #ifdef USE_ESP8266 | ||||||
| #ifdef USE_ADC_SENSOR_VCC |  | ||||||
|   return ESP.getVcc();  // NOLINT(readability-static-accessed-through-instance) |  | ||||||
| #else |  | ||||||
|   return analogRead(this->pin_->get_pin());  // NOLINT |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| uint32_t ADCSensor::raw_to_microvolts_(uint16_t raw) { |  | ||||||
| #ifdef USE_ESP32 |  | ||||||
| #if CONFIG_IDF_TARGET_ESP32 |  | ||||||
|   switch (this->attenuation_) { |  | ||||||
|     case ADC_ATTEN_DB_0: |  | ||||||
|       return raw * 269;  // 1e6 * 1.1 / 4095 |  | ||||||
|     case ADC_ATTEN_DB_2_5: |  | ||||||
|       return raw * 366;  // 1e6 * 1.5 / 4095 |  | ||||||
|     case ADC_ATTEN_DB_6: |  | ||||||
|       return raw * 537;  // 1e6 * 2.2 / 4095 |  | ||||||
|     case ADC_ATTEN_DB_11: |  | ||||||
|       return raw * 952;  // 1e6 * 3.9 / 4095 |  | ||||||
|     default:             // This is to satisfy the unused ADC_ATTEN_MAX |  | ||||||
|       return raw * 244;  // 1e6 * 1.0 / 4095 |  | ||||||
|   } |  | ||||||
| #elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 |  | ||||||
|   switch (this->attenuation_) { |  | ||||||
|     case ADC_ATTEN_DB_0: |  | ||||||
|       return raw * 205;  // 1e6 * 0.84 / 4095 |  | ||||||
|     case ADC_ATTEN_DB_2_5: |  | ||||||
|       return raw * 276;  // 1e6 * 1.13 / 4095 |  | ||||||
|     case ADC_ATTEN_DB_6: |  | ||||||
|       return raw * 381;  // 1e6 * 1.56 / 4095 |  | ||||||
|     case ADC_ATTEN_DB_11: |  | ||||||
|       return raw * 733;  // 1e6 * 3.0 / 4095 |  | ||||||
|     default:             // This is to satisfy the unused ADC_ATTEN_MAX |  | ||||||
|       return raw * 244;  // 1e6 * 1.0 / 4095 |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef USE_ESP8266 |  | ||||||
|   return raw * 977;  // 1e6 / 1024 |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| float ADCSensor::sample() { | float ADCSensor::sample() { | ||||||
|   int raw = this->read_raw_(); | #ifdef USE_ADC_SENSOR_VCC | ||||||
|   uint32_t v = this->raw_to_microvolts_(raw); |   return ESP.getVcc() / 1024.0f;  // NOLINT(readability-static-accessed-through-instance) | ||||||
| #ifdef USE_ESP32 | #else | ||||||
|   if (autorange_) { |   return analogRead(this->pin_->get_pin()) / 1024.0f;  // NOLINT | ||||||
|     int raw11 = raw, raw6 = 4095, raw2 = 4095, raw0 = 4095; |  | ||||||
|     uint32_t v11 = v, v6 = 0, v2 = 0, v0 = 0; |  | ||||||
|     if (raw11 < 4095) {  // Progressively read all attenuation ranges |  | ||||||
|       adc1_config_channel_atten(gpio_to_adc1(pin_->get_pin()), ADC_ATTEN_DB_6); |  | ||||||
|       raw6 = this->read_raw_(); |  | ||||||
|       v6 = this->raw_to_microvolts_(raw6); |  | ||||||
|       if (raw6 < 4095) { |  | ||||||
|         adc1_config_channel_atten(gpio_to_adc1(pin_->get_pin()), ADC_ATTEN_DB_2_5); |  | ||||||
|         raw2 = this->read_raw_(); |  | ||||||
|         v2 = this->raw_to_microvolts_(raw2); |  | ||||||
|         if (raw2 < 4095) { |  | ||||||
|           adc1_config_channel_atten(gpio_to_adc1(pin_->get_pin()), ADC_ATTEN_DB_0); |  | ||||||
|           raw0 = this->read_raw_(); |  | ||||||
|           v0 = this->raw_to_microvolts_(raw0); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       adc1_config_channel_atten(gpio_to_adc1(pin_->get_pin()), ADC_ATTEN_DB_11); |  | ||||||
|     }                                           // Contribution coefficients (normalized to 2048) |  | ||||||
|     uint16_t c11 = clamp(raw11, 0, 2048);       // high 1, middle 1, low 0 |  | ||||||
|     uint16_t c6 = (2048 - abs(raw6 - 2048));    // high 0, middle 1, low 0 |  | ||||||
|     uint16_t c2 = (2048 - abs(raw2 - 2048));    // high 0, middle 1, low 0 |  | ||||||
|     uint16_t c0 = clamp(4095 - raw0, 0, 2048);  // high 0, middle 1, low 1 |  | ||||||
|     uint32_t csum = c11 + c6 + c2 + c0;         // sum to normalize the final result |  | ||||||
|     if (csum > 0) |  | ||||||
|       v = (v11 * c11) + (v6 * c6) + (v2 * c2) + (v0 * c0); |  | ||||||
|     else  // in case of error, this keeps the 11db output (v) |  | ||||||
|       csum = 1; |  | ||||||
|     csum *= 1e6;                      // include the 1e6 microvolts->volts conversion factor |  | ||||||
|     return (float) v / (float) csum;  // normalize, convert & return |  | ||||||
|   } |  | ||||||
| #endif | #endif | ||||||
|   return v / (float) 1e6;  // convert from microvolts to volts |  | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef USE_ESP32 | ||||||
|  | float ADCSensor::sample() { | ||||||
|  |   if (!autorange_) { | ||||||
|  |     int raw = adc1_get_raw(channel_); | ||||||
|  |     if (raw == -1) { | ||||||
|  |       return NAN; | ||||||
|  |     } | ||||||
|  |     uint32_t mv = esp_adc_cal_raw_to_voltage(raw, &cal_characteristics_[(int) attenuation_]); | ||||||
|  |     return mv / 1000.0f; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   int raw11, raw6 = 4095, raw2 = 4095, raw0 = 4095; | ||||||
|  |   adc1_config_channel_atten(channel_, ADC_ATTEN_DB_11); | ||||||
|  |   raw11 = adc1_get_raw(channel_); | ||||||
|  |   if (raw11 < 4095) { | ||||||
|  |     adc1_config_channel_atten(channel_, ADC_ATTEN_DB_6); | ||||||
|  |     raw6 = adc1_get_raw(channel_); | ||||||
|  |     if (raw6 < 4095) { | ||||||
|  |       adc1_config_channel_atten(channel_, ADC_ATTEN_DB_2_5); | ||||||
|  |       raw2 = adc1_get_raw(channel_); | ||||||
|  |       if (raw2 < 4095) { | ||||||
|  |         adc1_config_channel_atten(channel_, ADC_ATTEN_DB_0); | ||||||
|  |         raw0 = adc1_get_raw(channel_); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw11 == -1) { | ||||||
|  |     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 mv6 = esp_adc_cal_raw_to_voltage(raw6, &cal_characteristics_[(int) ADC_ATTEN_DB_6]); | ||||||
|  |   uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int) ADC_ATTEN_DB_2_5]); | ||||||
|  |   uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int) ADC_ATTEN_DB_0]); | ||||||
|  |  | ||||||
|  |   // Contribution of each value, in range 0-2048 | ||||||
|  |   uint32_t c11 = std::min(raw11, 2048); | ||||||
|  |   uint32_t c6 = 2048 - std::abs(raw6 - 2048); | ||||||
|  |   uint32_t c2 = 2048 - std::abs(raw2 - 2048); | ||||||
|  |   uint32_t c0 = std::min(4095 - raw0, 2048); | ||||||
|  |   // max theoretical csum value is 2048*4 = 8192 | ||||||
|  |   uint32_t csum = c11 + c6 + c2 + c0; | ||||||
|  |  | ||||||
|  |   // each mv is max 3900; so max value is 3900*2048*4, fits in unsigned | ||||||
|  |   uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0); | ||||||
|  |   return mv_scaled / (float) (csum * 1000U); | ||||||
|  | } | ||||||
|  | #endif  // USE_ESP32 | ||||||
|  |  | ||||||
| #ifdef USE_ESP8266 | #ifdef USE_ESP8266 | ||||||
| std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; } | std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; } | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
| #include "driver/adc.h" | #include "driver/adc.h" | ||||||
|  | #include <esp_adc_cal.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| @@ -17,8 +18,9 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | |||||||
|  public: |  public: | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
|   /// Set the attenuation for this pin. Only available on the ESP32. |   /// Set the attenuation for this pin. Only available on the ESP32. | ||||||
|   void set_attenuation(adc_atten_t attenuation); |   void set_attenuation(adc_atten_t attenuation) { attenuation_ = attenuation; } | ||||||
|   void set_autorange(bool autorange); |   void set_channel(adc1_channel_t channel) { channel_ = channel; } | ||||||
|  |   void set_autorange(bool autorange) { autorange_ = autorange; } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   /// Update adc values. |   /// Update adc values. | ||||||
| @@ -42,7 +44,9 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | |||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
|   adc_atten_t attenuation_{ADC_ATTEN_DB_0}; |   adc_atten_t attenuation_{ADC_ATTEN_DB_0}; | ||||||
|  |   adc1_channel_t channel_{}; | ||||||
|   bool autorange_{false}; |   bool autorange_{false}; | ||||||
|  |   esp_adc_cal_characteristics_t cal_characteristics_[(int) ADC_ATTEN_MAX] = {}; | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,12 +6,21 @@ from esphome.const import ( | |||||||
|     CONF_ATTENUATION, |     CONF_ATTENUATION, | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|     CONF_INPUT, |     CONF_INPUT, | ||||||
|  |     CONF_NUMBER, | ||||||
|     CONF_PIN, |     CONF_PIN, | ||||||
|     DEVICE_CLASS_VOLTAGE, |     DEVICE_CLASS_VOLTAGE, | ||||||
|     STATE_CLASS_MEASUREMENT, |     STATE_CLASS_MEASUREMENT, | ||||||
|     UNIT_VOLT, |     UNIT_VOLT, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE | from esphome.core import CORE | ||||||
|  | from esphome.components.esp32 import get_esp32_variant | ||||||
|  | from esphome.components.esp32.const import ( | ||||||
|  |     VARIANT_ESP32, | ||||||
|  |     VARIANT_ESP32C3, | ||||||
|  |     VARIANT_ESP32H2, | ||||||
|  |     VARIANT_ESP32S2, | ||||||
|  |     VARIANT_ESP32S3, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
| AUTO_LOAD = ["voltage_sampler"] | AUTO_LOAD = ["voltage_sampler"] | ||||||
| @@ -24,21 +33,77 @@ ATTENUATION_MODES = { | |||||||
|     "auto": "auto", |     "auto": "auto", | ||||||
| } | } | ||||||
|  |  | ||||||
|  | adc1_channel_t = cg.global_ns.enum("adc1_channel_t") | ||||||
|  |  | ||||||
|  | # From https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/adc_common.h | ||||||
|  | # pin to adc1 channel mapping | ||||||
|  | ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = { | ||||||
|  |     VARIANT_ESP32: { | ||||||
|  |         36: adc1_channel_t.ADC1_CHANNEL_0, | ||||||
|  |         37: adc1_channel_t.ADC1_CHANNEL_1, | ||||||
|  |         38: adc1_channel_t.ADC1_CHANNEL_2, | ||||||
|  |         39: adc1_channel_t.ADC1_CHANNEL_3, | ||||||
|  |         32: adc1_channel_t.ADC1_CHANNEL_4, | ||||||
|  |         33: adc1_channel_t.ADC1_CHANNEL_5, | ||||||
|  |         34: adc1_channel_t.ADC1_CHANNEL_6, | ||||||
|  |         35: adc1_channel_t.ADC1_CHANNEL_7, | ||||||
|  |     }, | ||||||
|  |     VARIANT_ESP32S2: { | ||||||
|  |         1: adc1_channel_t.ADC1_CHANNEL_0, | ||||||
|  |         2: adc1_channel_t.ADC1_CHANNEL_1, | ||||||
|  |         3: adc1_channel_t.ADC1_CHANNEL_2, | ||||||
|  |         4: adc1_channel_t.ADC1_CHANNEL_3, | ||||||
|  |         5: adc1_channel_t.ADC1_CHANNEL_4, | ||||||
|  |         6: adc1_channel_t.ADC1_CHANNEL_5, | ||||||
|  |         7: adc1_channel_t.ADC1_CHANNEL_6, | ||||||
|  |         8: adc1_channel_t.ADC1_CHANNEL_7, | ||||||
|  |         9: adc1_channel_t.ADC1_CHANNEL_8, | ||||||
|  |         10: adc1_channel_t.ADC1_CHANNEL_9, | ||||||
|  |     }, | ||||||
|  |     VARIANT_ESP32S3: { | ||||||
|  |         1: adc1_channel_t.ADC1_CHANNEL_0, | ||||||
|  |         2: adc1_channel_t.ADC1_CHANNEL_1, | ||||||
|  |         3: adc1_channel_t.ADC1_CHANNEL_2, | ||||||
|  |         4: adc1_channel_t.ADC1_CHANNEL_3, | ||||||
|  |         5: adc1_channel_t.ADC1_CHANNEL_4, | ||||||
|  |         6: adc1_channel_t.ADC1_CHANNEL_5, | ||||||
|  |         7: adc1_channel_t.ADC1_CHANNEL_6, | ||||||
|  |         8: adc1_channel_t.ADC1_CHANNEL_7, | ||||||
|  |         9: adc1_channel_t.ADC1_CHANNEL_8, | ||||||
|  |         10: adc1_channel_t.ADC1_CHANNEL_9, | ||||||
|  |     }, | ||||||
|  |     VARIANT_ESP32C3: { | ||||||
|  |         0: adc1_channel_t.ADC1_CHANNEL_0, | ||||||
|  |         1: adc1_channel_t.ADC1_CHANNEL_1, | ||||||
|  |         2: adc1_channel_t.ADC1_CHANNEL_2, | ||||||
|  |         3: adc1_channel_t.ADC1_CHANNEL_3, | ||||||
|  |         4: adc1_channel_t.ADC1_CHANNEL_4, | ||||||
|  |     }, | ||||||
|  |     VARIANT_ESP32H2: { | ||||||
|  |         0: adc1_channel_t.ADC1_CHANNEL_0, | ||||||
|  |         1: adc1_channel_t.ADC1_CHANNEL_1, | ||||||
|  |         2: adc1_channel_t.ADC1_CHANNEL_2, | ||||||
|  |         3: adc1_channel_t.ADC1_CHANNEL_3, | ||||||
|  |         4: adc1_channel_t.ADC1_CHANNEL_4, | ||||||
|  |     }, | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| def validate_adc_pin(value): | def validate_adc_pin(value): | ||||||
|     if str(value).upper() == "VCC": |     if str(value).upper() == "VCC": | ||||||
|         return cv.only_on_esp8266("VCC") |         return cv.only_on_esp8266("VCC") | ||||||
|  |  | ||||||
|     if CORE.is_esp32: |     if CORE.is_esp32: | ||||||
|         from esphome.components.esp32 import is_esp32c3 |  | ||||||
|  |  | ||||||
|         value = pins.internal_gpio_input_pin_number(value) |         value = pins.internal_gpio_input_pin_number(value) | ||||||
|         if is_esp32c3(): |         variant = get_esp32_variant() | ||||||
|             if not (0 <= value <= 4):  # ADC1 |         if variant not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL: | ||||||
|                 raise cv.Invalid("ESP32-C3: Only pins 0 though 4 support ADC.") |             raise cv.Invalid(f"This ESP32 variant ({variant}) is not supported") | ||||||
|         elif not (32 <= value <= 39):  # ADC1 |  | ||||||
|             raise cv.Invalid("ESP32: Only pins 32 though 39 support ADC.") |         if value not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant]: | ||||||
|     elif CORE.is_esp8266: |             raise cv.Invalid(f"{variant} doesn't support ADC on this pin") | ||||||
|  |         return pins.internal_gpio_input_pin_schema(value) | ||||||
|  |  | ||||||
|  |     if CORE.is_esp8266: | ||||||
|         from esphome.components.esp8266.gpio import CONF_ANALOG |         from esphome.components.esp8266.gpio import CONF_ANALOG | ||||||
|  |  | ||||||
|         value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})( |         value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})( | ||||||
| @@ -50,10 +115,8 @@ def validate_adc_pin(value): | |||||||
|         return pins.gpio_pin_schema( |         return pins.gpio_pin_schema( | ||||||
|             {CONF_ANALOG: True, CONF_INPUT: True}, internal=True |             {CONF_ANALOG: True, CONF_INPUT: True}, internal=True | ||||||
|         )(value) |         )(value) | ||||||
|     else: |  | ||||||
|         raise NotImplementedError |  | ||||||
|  |  | ||||||
|     return pins.internal_gpio_input_pin_schema(value) |     raise NotImplementedError | ||||||
|  |  | ||||||
|  |  | ||||||
| adc_ns = cg.esphome_ns.namespace("adc") | adc_ns = cg.esphome_ns.namespace("adc") | ||||||
| @@ -97,3 +160,9 @@ async def to_code(config): | |||||||
|             cg.add(var.set_autorange(cg.global_ns.true)) |             cg.add(var.set_autorange(cg.global_ns.true)) | ||||||
|         else: |         else: | ||||||
|             cg.add(var.set_attenuation(config[CONF_ATTENUATION])) |             cg.add(var.set_attenuation(config[CONF_ATTENUATION])) | ||||||
|  |  | ||||||
|  |     if CORE.is_esp32: | ||||||
|  |         variant = get_esp32_variant() | ||||||
|  |         pin_num = config[CONF_PIN][CONF_NUMBER] | ||||||
|  |         chan = ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant][pin_num] | ||||||
|  |         cg.add(var.set_channel(chan)) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user