ESPHome  2024.12.2
adc_sensor_rp2040.cpp
Go to the documentation of this file.
1 #ifdef USE_RP2040
2 
3 #include "adc_sensor.h"
4 #include "esphome/core/log.h"
5 
6 #ifdef CYW43_USES_VSYS_PIN
7 #include "pico/cyw43_arch.h"
8 #endif // CYW43_USES_VSYS_PIN
9 #include <hardware/adc.h>
10 
11 namespace esphome {
12 namespace adc {
13 
14 static const char *const TAG = "adc.rp2040";
15 
16 void ADCSensor::setup() {
17  ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str());
18  static bool initialized = false;
19  if (!initialized) {
20  adc_init();
21  initialized = true;
22  }
23 }
24 
26  LOG_SENSOR("", "ADC Sensor", this);
27  if (this->is_temperature_) {
28  ESP_LOGCONFIG(TAG, " Pin: Temperature");
29  } else {
30 #ifdef USE_ADC_SENSOR_VCC
31  ESP_LOGCONFIG(TAG, " Pin: VCC");
32 #else
33  LOG_PIN(" Pin: ", this->pin_);
34 #endif // USE_ADC_SENSOR_VCC
35  }
36  ESP_LOGCONFIG(TAG, " Samples: %i", this->sample_count_);
37  LOG_UPDATE_INTERVAL(this);
38 }
39 
40 float ADCSensor::sample() {
41  if (this->is_temperature_) {
42  adc_set_temp_sensor_enabled(true);
43  delay(1);
44  adc_select_input(4);
45  uint32_t raw = 0;
46  for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
47  raw += adc_read();
48  }
49  raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
50  adc_set_temp_sensor_enabled(false);
51  if (this->output_raw_) {
52  return raw;
53  }
54  return raw * 3.3f / 4096.0f;
55  }
56 
57  uint8_t pin = this->pin_->get_pin();
58 #ifdef CYW43_USES_VSYS_PIN
59  if (pin == PICO_VSYS_PIN) {
60  // Measuring VSYS on Raspberry Pico W needs to be wrapped with
61  // `cyw43_thread_enter()`/`cyw43_thread_exit()` as discussed in
62  // https://github.com/raspberrypi/pico-sdk/issues/1222, since Wifi chip and
63  // VSYS ADC both share GPIO29
64  cyw43_thread_enter();
65  }
66 #endif // CYW43_USES_VSYS_PIN
67 
68  adc_gpio_init(pin);
69  adc_select_input(pin - 26);
70 
71  uint32_t raw = 0;
72  for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
73  raw += adc_read();
74  }
75  raw = (raw + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
76 
77 #ifdef CYW43_USES_VSYS_PIN
78  if (pin == PICO_VSYS_PIN) {
79  cyw43_thread_exit();
80  }
81 #endif // CYW43_USES_VSYS_PIN
82 
83  if (this->output_raw_) {
84  return raw;
85  }
86  float coeff = pin == PICO_VSYS_PIN ? 3.0f : 1.0f;
87  return raw * 3.3f / 4096.0f * coeff;
88 }
89 
90 } // namespace adc
91 } // namespace esphome
92 
93 #endif // USE_RP2040
uint8_t raw[35]
Definition: bl0939.h:19
void setup() override
Setup ADC.
virtual uint8_t get_pin() const =0
InternalGPIOPin * pin_
Definition: adc_sensor.h:68
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
const StringRef & get_name() const
Definition: entity_base.cpp:10
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26