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 | ||||
|  | ||||
| #ifdef USE_RP2040 | ||||
| #include <hardware/adc.h> | ||||
| #endif | ||||
|  | ||||
| namespace esphome { | ||||
| 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) | ||||
| #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()); | ||||
| #ifndef USE_ADC_SENSOR_VCC | ||||
| #if !defined(USE_ADC_SENSOR_VCC) && !defined(USE_RP2040) | ||||
|   pin_->setup(); | ||||
| #endif | ||||
|  | ||||
| @@ -63,6 +71,16 @@ void ADCSensor::setup() { | ||||
|   } | ||||
|  | ||||
| #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() { | ||||
| @@ -98,6 +116,12 @@ void ADCSensor::dump_config() { | ||||
|     } | ||||
|   } | ||||
| #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); | ||||
| } | ||||
|  | ||||
| @@ -175,6 +199,29 @@ float ADCSensor::sample() { | ||||
| } | ||||
| #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 | ||||
| std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; } | ||||
| #endif | ||||
|   | ||||
| @@ -38,10 +38,18 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage | ||||
|   std::string unique_id() override; | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_RP2040 | ||||
|   void set_is_temperature() { is_temperature_ = true; } | ||||
| #endif | ||||
|  | ||||
|  protected: | ||||
|   InternalGPIOPin *pin_; | ||||
|   bool output_raw_{false}; | ||||
|  | ||||
| #ifdef USE_RP2040 | ||||
|   bool is_temperature_{false}; | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_ESP32 | ||||
|   adc_atten_t attenuation_{ADC_ATTEN_DB_0}; | ||||
|   adc1_channel_t channel_{}; | ||||
|   | ||||
| @@ -94,6 +94,9 @@ def validate_adc_pin(value): | ||||
|     if str(value).upper() == "VCC": | ||||
|         return cv.only_on_esp8266("VCC") | ||||
|  | ||||
|     if str(value).upper() == "TEMPERATURE": | ||||
|         return cv.only_on_rp2040("TEMPERATURE") | ||||
|  | ||||
|     if CORE.is_esp32: | ||||
|         value = pins.internal_gpio_input_pin_number(value) | ||||
|         variant = get_esp32_variant() | ||||
| @@ -117,6 +120,12 @@ def validate_adc_pin(value): | ||||
|             {CONF_ANALOG: True, CONF_INPUT: True}, internal=True | ||||
|         )(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 | ||||
|  | ||||
|  | ||||
| @@ -160,6 +169,8 @@ async def to_code(config): | ||||
|  | ||||
|     if config[CONF_PIN] == "VCC": | ||||
|         cg.add_define("USE_ADC_SENSOR_VCC") | ||||
|     elif config[CONF_PIN] == "TEMPERATURE": | ||||
|         cg.add(var.set_is_temperature()) | ||||
|     else: | ||||
|         pin = await cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|         cg.add(var.set_pin(pin)) | ||||
|   | ||||
| @@ -548,6 +548,7 @@ def only_with_framework(frameworks): | ||||
|  | ||||
| only_on_esp32 = only_on("esp32") | ||||
| only_on_esp8266 = only_on("esp8266") | ||||
| only_on_rp2040 = only_on("rp2040") | ||||
| only_with_arduino = only_with_framework("arduino") | ||||
| only_with_esp_idf = only_with_framework("esp-idf") | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user