Support ADC on RP2040 (#4040)

This commit is contained in:
Jesse Hills 2022-11-17 13:51:08 +13:00 committed by GitHub
parent 65030e1c37
commit 719c212009
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 2 deletions

View file

@ -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

View file

@ -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_{};

View file

@ -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))

View file

@ -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")