mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	[adc] Split files by platform (#7940)
This commit is contained in:
		| @@ -3,13 +3,12 @@ | |||||||
| #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/component.h" | ||||||
| #include "esphome/core/defines.h" |  | ||||||
| #include "esphome/core/hal.h" | #include "esphome/core/hal.h" | ||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
| #include <esp_adc_cal.h> | #include <esp_adc_cal.h> | ||||||
| #include "driver/adc.h" | #include "driver/adc.h" | ||||||
| #endif | #endif  // USE_ESP32 | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace adc { | namespace adc { | ||||||
| @@ -43,7 +42,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | |||||||
|     this->channel1_ = ADC1_CHANNEL_MAX; |     this->channel1_ = ADC1_CHANNEL_MAX; | ||||||
|   } |   } | ||||||
|   void set_autorange(bool autorange) { this->autorange_ = autorange; } |   void set_autorange(bool autorange) { this->autorange_ = autorange; } | ||||||
| #endif | #endif  // USE_ESP32 | ||||||
|  |  | ||||||
|   /// Update ADC values |   /// Update ADC values | ||||||
|   void update() override; |   void update() override; | ||||||
| @@ -59,11 +58,11 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | |||||||
|  |  | ||||||
| #ifdef USE_ESP8266 | #ifdef USE_ESP8266 | ||||||
|   std::string unique_id() override; |   std::string unique_id() override; | ||||||
| #endif | #endif  // USE_ESP8266 | ||||||
|  |  | ||||||
| #ifdef USE_RP2040 | #ifdef USE_RP2040 | ||||||
|   void set_is_temperature() { this->is_temperature_ = true; } |   void set_is_temperature() { this->is_temperature_ = true; } | ||||||
| #endif | #endif  // USE_RP2040 | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   InternalGPIOPin *pin_; |   InternalGPIOPin *pin_; | ||||||
| @@ -72,7 +71,7 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | |||||||
|  |  | ||||||
| #ifdef USE_RP2040 | #ifdef USE_RP2040 | ||||||
|   bool is_temperature_{false}; |   bool is_temperature_{false}; | ||||||
| #endif | #endif  // USE_RP2040 | ||||||
|  |  | ||||||
| #ifdef USE_ESP32 | #ifdef USE_ESP32 | ||||||
|   adc_atten_t attenuation_{ADC_ATTEN_DB_0}; |   adc_atten_t attenuation_{ADC_ATTEN_DB_0}; | ||||||
| @@ -83,8 +82,8 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | |||||||
|   esp_adc_cal_characteristics_t cal_characteristics_[SOC_ADC_ATTEN_NUM] = {}; |   esp_adc_cal_characteristics_t cal_characteristics_[SOC_ADC_ATTEN_NUM] = {}; | ||||||
| #else | #else | ||||||
|   esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {}; |   esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {}; | ||||||
| #endif | #endif  // ESP_IDF_VERSION_MAJOR | ||||||
| #endif | #endif  // USE_ESP32 | ||||||
| }; | }; | ||||||
|  |  | ||||||
| }  // namespace adc | }  // namespace adc | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								esphome/components/adc/adc_sensor_common.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								esphome/components/adc/adc_sensor_common.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | #include "adc_sensor.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace adc { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "adc.common"; | ||||||
|  |  | ||||||
|  | void ADCSensor::update() { | ||||||
|  |   float value_v = this->sample(); | ||||||
|  |   ESP_LOGV(TAG, "'%s': Got voltage=%.4fV", this->get_name().c_str(), value_v); | ||||||
|  |   this->publish_state(value_v); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ADCSensor::set_sample_count(uint8_t sample_count) { | ||||||
|  |   if (sample_count != 0) { | ||||||
|  |     this->sample_count_ = sample_count; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | float ADCSensor::get_setup_priority() const { return setup_priority::DATA; } | ||||||
|  |  | ||||||
|  | }  // namespace adc | ||||||
|  | }  // namespace esphome | ||||||
| @@ -1,30 +1,13 @@ | |||||||
|  | #ifdef USE_ESP32 | ||||||
|  | 
 | ||||||
| #include "adc_sensor.h" | #include "adc_sensor.h" | ||||||
| #include "esphome/core/helpers.h" |  | ||||||
| #include "esphome/core/log.h" | #include "esphome/core/log.h" | ||||||
| 
 | 
 | ||||||
| #ifdef USE_ESP8266 |  | ||||||
| #ifdef USE_ADC_SENSOR_VCC |  | ||||||
| #include <Esp.h> |  | ||||||
| ADC_MODE(ADC_VCC) |  | ||||||
| #else |  | ||||||
| #include <Arduino.h> |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifdef USE_RP2040 |  | ||||||
| #ifdef CYW43_USES_VSYS_PIN |  | ||||||
| #include "pico/cyw43_arch.h" |  | ||||||
| #endif |  | ||||||
| #include <hardware/adc.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace adc { | namespace adc { | ||||||
| 
 | 
 | ||||||
| static const char *const TAG = "adc"; | static const char *const TAG = "adc.esp32"; | ||||||
| 
 | 
 | ||||||
| // 13-bit for S2, 12-bit for all other ESP32 variants
 |  | ||||||
| #ifdef USE_ESP32 |  | ||||||
| static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast<adc_bits_width_t>(ADC_WIDTH_MAX - 1); | static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast<adc_bits_width_t>(ADC_WIDTH_MAX - 1); | ||||||
| 
 | 
 | ||||||
| #ifndef SOC_ADC_RTC_MAX_BITWIDTH | #ifndef SOC_ADC_RTC_MAX_BITWIDTH | ||||||
| @@ -32,24 +15,15 @@ static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast<adc_bits_widt | |||||||
| static const int32_t SOC_ADC_RTC_MAX_BITWIDTH = 13; | static const int32_t SOC_ADC_RTC_MAX_BITWIDTH = 13; | ||||||
| #else | #else | ||||||
| static const int32_t SOC_ADC_RTC_MAX_BITWIDTH = 12; | static const int32_t SOC_ADC_RTC_MAX_BITWIDTH = 12; | ||||||
| #endif | #endif  // USE_ESP32_VARIANT_ESP32S2
 | ||||||
| #endif | #endif  // SOC_ADC_RTC_MAX_BITWIDTH
 | ||||||
| 
 | 
 | ||||||
| static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1;    // 4095 (12 bit) or 8191 (13 bit)
 | static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1; | ||||||
| static const int ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1;  // 2048 (12 bit) or 4096 (13 bit)
 | static const int ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1; | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| #ifdef USE_RP2040 | void ADCSensor::setup() { | ||||||
| extern "C" |  | ||||||
| #endif |  | ||||||
|     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()); | ||||||
| #if !defined(USE_ADC_SENSOR_VCC) && !defined(USE_RP2040) |  | ||||||
|   this->pin_->setup(); |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| #ifdef USE_ESP32 |  | ||||||
|   if (this->channel1_ != ADC1_CHANNEL_MAX) { |   if (this->channel1_ != ADC1_CHANNEL_MAX) { | ||||||
|     adc1_config_width(ADC_WIDTH_MAX_SOC_BITS); |     adc1_config_width(ADC_WIDTH_MAX_SOC_BITS); | ||||||
|     if (!this->autorange_) { |     if (!this->autorange_) { | ||||||
| @@ -61,7 +35,6 @@ extern "C" | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // load characteristics for each attenuation
 |  | ||||||
|   for (int32_t i = 0; i <= ADC_ATTEN_DB_12_COMPAT; i++) { |   for (int32_t i = 0; i <= ADC_ATTEN_DB_12_COMPAT; i++) { | ||||||
|     auto adc_unit = this->channel1_ != ADC1_CHANNEL_MAX ? ADC_UNIT_1 : ADC_UNIT_2; |     auto adc_unit = this->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, | ||||||
| @@ -79,31 +52,10 @@ extern "C" | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
| #endif  // USE_ESP32
 |  | ||||||
| 
 |  | ||||||
| #ifdef USE_RP2040 |  | ||||||
|   static bool initialized = false; |  | ||||||
|   if (!initialized) { |  | ||||||
|     adc_init(); |  | ||||||
|     initialized = true; |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|   ESP_LOGCONFIG(TAG, "ADC '%s' setup finished!", this->get_name().c_str()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ADCSensor::dump_config() { | void ADCSensor::dump_config() { | ||||||
|   LOG_SENSOR("", "ADC Sensor", this); |   LOG_SENSOR("", "ADC Sensor", this); | ||||||
| #if defined(USE_ESP8266) || defined(USE_LIBRETINY) |  | ||||||
| #ifdef USE_ADC_SENSOR_VCC |  | ||||||
|   ESP_LOGCONFIG(TAG, "  Pin: VCC"); |  | ||||||
| #else |  | ||||||
|   LOG_PIN("  Pin: ", this->pin_); |  | ||||||
| #endif |  | ||||||
| #endif  // USE_ESP8266 || USE_LIBRETINY
 |  | ||||||
| 
 |  | ||||||
| #ifdef USE_ESP32 |  | ||||||
|   LOG_PIN("  Pin: ", this->pin_); |   LOG_PIN("  Pin: ", this->pin_); | ||||||
|   if (this->autorange_) { |   if (this->autorange_) { | ||||||
|     ESP_LOGCONFIG(TAG, "  Attenuation: auto"); |     ESP_LOGCONFIG(TAG, "  Attenuation: auto"); | ||||||
| @@ -125,55 +77,10 @@ void ADCSensor::dump_config() { | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| #endif  // USE_ESP32
 |  | ||||||
| 
 |  | ||||||
| #ifdef USE_RP2040 |  | ||||||
|   if (this->is_temperature_) { |  | ||||||
|     ESP_LOGCONFIG(TAG, "  Pin: Temperature"); |  | ||||||
|   } else { |  | ||||||
| #ifdef USE_ADC_SENSOR_VCC |  | ||||||
|     ESP_LOGCONFIG(TAG, "  Pin: VCC"); |  | ||||||
| #else |  | ||||||
|     LOG_PIN("  Pin: ", this->pin_); |  | ||||||
| #endif  // USE_ADC_SENSOR_VCC
 |  | ||||||
|   } |  | ||||||
| #endif  // USE_RP2040
 |  | ||||||
|   ESP_LOGCONFIG(TAG, "  Samples: %i", this->sample_count_); |   ESP_LOGCONFIG(TAG, "  Samples: %i", this->sample_count_); | ||||||
|   LOG_UPDATE_INTERVAL(this); |   LOG_UPDATE_INTERVAL(this); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float ADCSensor::get_setup_priority() const { return setup_priority::DATA; } |  | ||||||
| void ADCSensor::update() { |  | ||||||
|   float value_v = this->sample(); |  | ||||||
|   ESP_LOGV(TAG, "'%s': Got voltage=%.4fV", this->get_name().c_str(), value_v); |  | ||||||
|   this->publish_state(value_v); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ADCSensor::set_sample_count(uint8_t sample_count) { |  | ||||||
|   if (sample_count != 0) { |  | ||||||
|     this->sample_count_ = sample_count; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #ifdef USE_ESP8266 |  | ||||||
| float ADCSensor::sample() { |  | ||||||
|   uint32_t raw = 0; |  | ||||||
|   for (uint8_t sample = 0; sample < this->sample_count_; sample++) { |  | ||||||
| #ifdef USE_ADC_SENSOR_VCC |  | ||||||
|     raw += ESP.getVcc();  // NOLINT(readability-static-accessed-through-instance)
 |  | ||||||
| #else |  | ||||||
|     raw += analogRead(this->pin_->get_pin());  // NOLINT
 |  | ||||||
| #endif |  | ||||||
|   } |  | ||||||
|   raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_;  // NOLINT(clang-analyzer-core.DivideZero)
 |  | ||||||
|   if (this->output_raw_) { |  | ||||||
|     return raw; |  | ||||||
|   } |  | ||||||
|   return raw / 1024.0f; |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifdef USE_ESP32 |  | ||||||
| float ADCSensor::sample() { | float ADCSensor::sample() { | ||||||
|   if (!this->autorange_) { |   if (!this->autorange_) { | ||||||
|     uint32_t sum = 0; |     uint32_t sum = 0; | ||||||
| @@ -240,93 +147,17 @@ float ADCSensor::sample() { | |||||||
|   uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &this->cal_characteristics_[(int32_t) ADC_ATTEN_DB_2_5]); |   uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &this->cal_characteristics_[(int32_t) ADC_ATTEN_DB_2_5]); | ||||||
|   uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &this->cal_characteristics_[(int32_t) ADC_ATTEN_DB_0]); |   uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &this->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 c12 = std::min(raw12, 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
 |  | ||||||
|   uint32_t csum = c12 + 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 = (mv12 * c12) + (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
 |  | ||||||
| 
 |  | ||||||
| #ifdef USE_RP2040 |  | ||||||
| float ADCSensor::sample() { |  | ||||||
|   if (this->is_temperature_) { |  | ||||||
|     adc_set_temp_sensor_enabled(true); |  | ||||||
|     delay(1); |  | ||||||
|     adc_select_input(4); |  | ||||||
|     uint32_t raw = 0; |  | ||||||
|     for (uint8_t sample = 0; sample < this->sample_count_; sample++) { |  | ||||||
|       raw += adc_read(); |  | ||||||
|     } |  | ||||||
|     raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_;  // NOLINT(clang-analyzer-core.DivideZero)
 |  | ||||||
|     adc_set_temp_sensor_enabled(false); |  | ||||||
|     if (this->output_raw_) { |  | ||||||
|       return raw; |  | ||||||
|     } |  | ||||||
|     return raw * 3.3f / 4096.0f; |  | ||||||
|   } else { |  | ||||||
|     uint8_t pin = this->pin_->get_pin(); |  | ||||||
| #ifdef CYW43_USES_VSYS_PIN |  | ||||||
|     if (pin == PICO_VSYS_PIN) { |  | ||||||
|       // Measuring VSYS on Raspberry Pico W needs to be wrapped with
 |  | ||||||
|       // `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in
 |  | ||||||
|       // https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and
 |  | ||||||
|       // VSYS ADC both share GPIO29
 |  | ||||||
|       cyw43_thread_enter(); |  | ||||||
|     } |  | ||||||
| #endif  // CYW43_USES_VSYS_PIN
 |  | ||||||
| 
 |  | ||||||
|     adc_gpio_init(pin); |  | ||||||
|     adc_select_input(pin - 26); |  | ||||||
| 
 |  | ||||||
|     uint32_t raw = 0; |  | ||||||
|     for (uint8_t sample = 0; sample < this->sample_count_; sample++) { |  | ||||||
|       raw += adc_read(); |  | ||||||
|     } |  | ||||||
|     raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_;  // NOLINT(clang-analyzer-core.DivideZero)
 |  | ||||||
| 
 |  | ||||||
| #ifdef CYW43_USES_VSYS_PIN |  | ||||||
|     if (pin == PICO_VSYS_PIN) { |  | ||||||
|       cyw43_thread_exit(); |  | ||||||
|     } |  | ||||||
| #endif  // CYW43_USES_VSYS_PIN
 |  | ||||||
| 
 |  | ||||||
|     if (this->output_raw_) { |  | ||||||
|       return raw; |  | ||||||
|     } |  | ||||||
|     float coeff = pin == PICO_VSYS_PIN ? 3.0 : 1.0; |  | ||||||
|     return raw * 3.3f / 4096.0f * coeff; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #ifdef USE_LIBRETINY |  | ||||||
| float ADCSensor::sample() { |  | ||||||
|   uint32_t raw = 0; |  | ||||||
|   if (this->output_raw_) { |  | ||||||
|     for (uint8_t sample = 0; sample < this->sample_count_; sample++) { |  | ||||||
|       raw += analogRead(this->pin_->get_pin());  // NOLINT
 |  | ||||||
|     } |  | ||||||
|     raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_;  // NOLINT(clang-analyzer-core.DivideZero)
 |  | ||||||
|     return raw; |  | ||||||
|   } |  | ||||||
|   for (uint8_t sample = 0; sample < this->sample_count_; sample++) { |  | ||||||
|     raw += analogReadVoltage(this->pin_->get_pin());  // NOLINT
 |  | ||||||
|   } |  | ||||||
|   raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_;  // NOLINT(clang-analyzer-core.DivideZero)
 |  | ||||||
|   return raw / 1000.0f; |  | ||||||
| } |  | ||||||
| #endif  // USE_LIBRETINY
 |  | ||||||
| 
 |  | ||||||
| #ifdef USE_ESP8266 |  | ||||||
| std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; } |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| }  // namespace adc
 | }  // namespace adc
 | ||||||
| }  // namespace esphome
 | }  // namespace esphome
 | ||||||
|  | 
 | ||||||
|  | #endif  // USE_ESP32
 | ||||||
							
								
								
									
										58
									
								
								esphome/components/adc/adc_sensor_esp8266.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								esphome/components/adc/adc_sensor_esp8266.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | #ifdef USE_ESP8266 | ||||||
|  |  | ||||||
|  | #include "adc_sensor.h" | ||||||
|  | #include "esphome/core/helpers.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | #ifdef USE_ADC_SENSOR_VCC | ||||||
|  | #include <Esp.h> | ||||||
|  | ADC_MODE(ADC_VCC) | ||||||
|  | #else | ||||||
|  | #include <Arduino.h> | ||||||
|  | #endif  // USE_ADC_SENSOR_VCC | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace adc { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "adc.esp8266"; | ||||||
|  |  | ||||||
|  | void ADCSensor::setup() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str()); | ||||||
|  | #ifndef USE_ADC_SENSOR_VCC | ||||||
|  |   this->pin_->setup(); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ADCSensor::dump_config() { | ||||||
|  |   LOG_SENSOR("", "ADC Sensor", this); | ||||||
|  | #ifdef USE_ADC_SENSOR_VCC | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Pin: VCC"); | ||||||
|  | #else | ||||||
|  |   LOG_PIN("  Pin: ", this->pin_); | ||||||
|  | #endif  // USE_ADC_SENSOR_VCC | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Samples: %i", this->sample_count_); | ||||||
|  |   LOG_UPDATE_INTERVAL(this); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | float ADCSensor::sample() { | ||||||
|  |   uint32_t raw = 0; | ||||||
|  |   for (uint8_t sample = 0; sample < this->sample_count_; sample++) { | ||||||
|  | #ifdef USE_ADC_SENSOR_VCC | ||||||
|  |     raw += ESP.getVcc();  // NOLINT(readability-static-accessed-through-instance) | ||||||
|  | #else | ||||||
|  |     raw += analogRead(this->pin_->get_pin());  // NOLINT | ||||||
|  | #endif  // USE_ADC_SENSOR_VCC | ||||||
|  |   } | ||||||
|  |   raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_;  // NOLINT(clang-analyzer-core.DivideZero) | ||||||
|  |   if (this->output_raw_) { | ||||||
|  |     return raw; | ||||||
|  |   } | ||||||
|  |   return raw / 1024.0f; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; } | ||||||
|  |  | ||||||
|  | }  // namespace adc | ||||||
|  | }  // namespace esphome | ||||||
|  |  | ||||||
|  | #endif  // USE_ESP8266 | ||||||
							
								
								
									
										93
									
								
								esphome/components/adc/adc_sensor_rp2040.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								esphome/components/adc/adc_sensor_rp2040.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | |||||||
|  | #ifdef USE_RP2040 | ||||||
|  |  | ||||||
|  | #include "adc_sensor.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | #ifdef CYW43_USES_VSYS_PIN | ||||||
|  | #include "pico/cyw43_arch.h" | ||||||
|  | #endif  // CYW43_USES_VSYS_PIN | ||||||
|  | #include <hardware/adc.h> | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace adc { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "adc.rp2040"; | ||||||
|  |  | ||||||
|  | void ADCSensor::setup() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str()); | ||||||
|  |   static bool initialized = false; | ||||||
|  |   if (!initialized) { | ||||||
|  |     adc_init(); | ||||||
|  |     initialized = true; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ADCSensor::dump_config() { | ||||||
|  |   LOG_SENSOR("", "ADC Sensor", this); | ||||||
|  |   if (this->is_temperature_) { | ||||||
|  |     ESP_LOGCONFIG(TAG, "  Pin: Temperature"); | ||||||
|  |   } else { | ||||||
|  | #ifdef USE_ADC_SENSOR_VCC | ||||||
|  |     ESP_LOGCONFIG(TAG, "  Pin: VCC"); | ||||||
|  | #else | ||||||
|  |     LOG_PIN("  Pin: ", this->pin_); | ||||||
|  | #endif  // USE_ADC_SENSOR_VCC | ||||||
|  |   } | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Samples: %i", this->sample_count_); | ||||||
|  |   LOG_UPDATE_INTERVAL(this); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | float ADCSensor::sample() { | ||||||
|  |   if (this->is_temperature_) { | ||||||
|  |     adc_set_temp_sensor_enabled(true); | ||||||
|  |     delay(1); | ||||||
|  |     adc_select_input(4); | ||||||
|  |     uint32_t raw = 0; | ||||||
|  |     for (uint8_t sample = 0; sample < this->sample_count_; sample++) { | ||||||
|  |       raw += adc_read(); | ||||||
|  |     } | ||||||
|  |     raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_;  // NOLINT(clang-analyzer-core.DivideZero) | ||||||
|  |     adc_set_temp_sensor_enabled(false); | ||||||
|  |     if (this->output_raw_) { | ||||||
|  |       return raw; | ||||||
|  |     } | ||||||
|  |     return raw * 3.3f / 4096.0f; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   uint8_t pin = this->pin_->get_pin(); | ||||||
|  | #ifdef CYW43_USES_VSYS_PIN | ||||||
|  |   if (pin == PICO_VSYS_PIN) { | ||||||
|  |     // Measuring VSYS on Raspberry Pico W needs to be wrapped with | ||||||
|  |     // `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in | ||||||
|  |     // https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and | ||||||
|  |     // VSYS ADC both share GPIO29 | ||||||
|  |     cyw43_thread_enter(); | ||||||
|  |   } | ||||||
|  | #endif  // CYW43_USES_VSYS_PIN | ||||||
|  |  | ||||||
|  |   adc_gpio_init(pin); | ||||||
|  |   adc_select_input(pin - 26); | ||||||
|  |  | ||||||
|  |   uint32_t raw = 0; | ||||||
|  |   for (uint8_t sample = 0; sample < this->sample_count_; sample++) { | ||||||
|  |     raw += adc_read(); | ||||||
|  |   } | ||||||
|  |   raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_;  // NOLINT(clang-analyzer-core.DivideZero) | ||||||
|  |  | ||||||
|  | #ifdef CYW43_USES_VSYS_PIN | ||||||
|  |   if (pin == PICO_VSYS_PIN) { | ||||||
|  |     cyw43_thread_exit(); | ||||||
|  |   } | ||||||
|  | #endif  // CYW43_USES_VSYS_PIN | ||||||
|  |  | ||||||
|  |   if (this->output_raw_) { | ||||||
|  |     return raw; | ||||||
|  |   } | ||||||
|  |   float coeff = pin == PICO_VSYS_PIN ? 3.0f : 1.0f; | ||||||
|  |   return raw * 3.3f / 4096.0f * coeff; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace adc | ||||||
|  | }  // namespace esphome | ||||||
|  |  | ||||||
|  | #endif  // USE_RP2040 | ||||||
		Reference in New Issue
	
	Block a user