mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Support ADC on RP2040 (#4040)
This commit is contained in:
		| @@ -11,6 +11,10 @@ ADC_MODE(ADC_VCC) | |||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #ifdef USE_RP2040 | ||||||
|  | #include <hardware/adc.h> | ||||||
|  | #endif | ||||||
|  |  | ||||||
| namespace esphome { | namespace esphome { | ||||||
| namespace adc { | namespace adc { | ||||||
|  |  | ||||||
| @@ -32,9 +36,13 @@ static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1;    // 4095 (12 b | |||||||
| 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;  // 2048 (12 bit) or 4096 (13 bit) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| void ADCSensor::setup() { | #ifdef USE_RP2040 | ||||||
|  | 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()); | ||||||
| #ifndef USE_ADC_SENSOR_VCC | #if !defined(USE_ADC_SENSOR_VCC) && !defined(USE_RP2040) | ||||||
|   pin_->setup(); |   pin_->setup(); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -63,6 +71,16 @@ void ADCSensor::setup() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
| #endif  // USE_ESP32 | #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() { | ||||||
| @@ -98,6 +116,12 @@ void ADCSensor::dump_config() { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| #endif  // USE_ESP32 | #endif  // USE_ESP32 | ||||||
|  | #ifdef USE_RP2040 | ||||||
|  |   if (this->is_temperature_) | ||||||
|  |     ESP_LOGCONFIG(TAG, "  Pin: Temperature"); | ||||||
|  |   else | ||||||
|  |     LOG_PIN("  Pin: ", pin_); | ||||||
|  | #endif | ||||||
|   LOG_UPDATE_INTERVAL(this); |   LOG_UPDATE_INTERVAL(this); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -175,6 +199,29 @@ float ADCSensor::sample() { | |||||||
| } | } | ||||||
| #endif  // USE_ESP32 | #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); | ||||||
|  |   } else { | ||||||
|  |     uint8_t pin = this->pin_->get_pin(); | ||||||
|  |     adc_gpio_init(pin); | ||||||
|  |     adc_select_input(pin - 26); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   int raw = adc_read(); | ||||||
|  |   if (this->is_temperature_) { | ||||||
|  |     adc_set_temp_sensor_enabled(false); | ||||||
|  |   } | ||||||
|  |   if (output_raw_) { | ||||||
|  |     return raw; | ||||||
|  |   } | ||||||
|  |   return raw * 3.3f / 4096.0f; | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #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 | ||||||
|   | |||||||
| @@ -38,10 +38,18 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | |||||||
|   std::string unique_id() override; |   std::string unique_id() override; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #ifdef USE_RP2040 | ||||||
|  |   void set_is_temperature() { is_temperature_ = true; } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   InternalGPIOPin *pin_; |   InternalGPIOPin *pin_; | ||||||
|   bool output_raw_{false}; |   bool output_raw_{false}; | ||||||
|  |  | ||||||
|  | #ifdef USE_RP2040 | ||||||
|  |   bool is_temperature_{false}; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #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_{}; |   adc1_channel_t channel_{}; | ||||||
|   | |||||||
| @@ -94,6 +94,9 @@ 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 str(value).upper() == "TEMPERATURE": | ||||||
|  |         return cv.only_on_rp2040("TEMPERATURE") | ||||||
|  |  | ||||||
|     if CORE.is_esp32: |     if CORE.is_esp32: | ||||||
|         value = pins.internal_gpio_input_pin_number(value) |         value = pins.internal_gpio_input_pin_number(value) | ||||||
|         variant = get_esp32_variant() |         variant = get_esp32_variant() | ||||||
| @@ -117,6 +120,12 @@ def validate_adc_pin(value): | |||||||
|             {CONF_ANALOG: True, CONF_INPUT: True}, internal=True |             {CONF_ANALOG: True, CONF_INPUT: True}, internal=True | ||||||
|         )(value) |         )(value) | ||||||
|  |  | ||||||
|  |     if CORE.is_rp2040: | ||||||
|  |         value = pins.internal_gpio_input_pin_number(value) | ||||||
|  |         if value not in (26, 27, 28, 29): | ||||||
|  |             raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC.") | ||||||
|  |         return pins.internal_gpio_input_pin_schema(value) | ||||||
|  |  | ||||||
|     raise NotImplementedError |     raise NotImplementedError | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -160,6 +169,8 @@ async def to_code(config): | |||||||
|  |  | ||||||
|     if config[CONF_PIN] == "VCC": |     if config[CONF_PIN] == "VCC": | ||||||
|         cg.add_define("USE_ADC_SENSOR_VCC") |         cg.add_define("USE_ADC_SENSOR_VCC") | ||||||
|  |     elif config[CONF_PIN] == "TEMPERATURE": | ||||||
|  |         cg.add(var.set_is_temperature()) | ||||||
|     else: |     else: | ||||||
|         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)) | ||||||
|   | |||||||
| @@ -548,6 +548,7 @@ def only_with_framework(frameworks): | |||||||
|  |  | ||||||
| only_on_esp32 = only_on("esp32") | only_on_esp32 = only_on("esp32") | ||||||
| only_on_esp8266 = only_on("esp8266") | only_on_esp8266 = only_on("esp8266") | ||||||
|  | only_on_rp2040 = only_on("rp2040") | ||||||
| only_with_arduino = only_with_framework("arduino") | only_with_arduino = only_with_framework("arduino") | ||||||
| only_with_esp_idf = only_with_framework("esp-idf") | only_with_esp_idf = only_with_framework("esp-idf") | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user