mirror of
https://github.com/esphome/esphome.git
synced 2024-11-21 22:48:10 +01:00
[ADC] Support measuring VCC on Raspberry Pico (W) (#5335)
* [ADC] Support measuring VCC on Raspberry Pico (W) Added support for measuring VCC on Raspberry Pico (W) with ADC. GPIO pin is provided as `VCC`, same as with ESP8266. VSYS is the voltage being actually processed, and might have an offset from actual power supply voltage (e.g. USB on VBUS) due to voltage drop on Schottky diode between VSYS and VBUS on Rasberry Pico. The offset has experimentally been found to be ~0.25V on Pico W and ~0.1 on Pico, presumably due to different power consumption. Example usage: sensor: - platform: adc pin: VCC name: "VSYS" * + Added tests for VCC measuring on `rpipicow` board
This commit is contained in:
parent
ccc30116ba
commit
7bb67ae94b
3 changed files with 45 additions and 4 deletions
|
@ -5,6 +5,10 @@ from esphome.const import CONF_ANALOG, CONF_INPUT
|
|||
|
||||
from esphome.core import CORE
|
||||
from esphome.components.esp32 import get_esp32_variant
|
||||
from esphome.const import (
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_RP2040,
|
||||
)
|
||||
from esphome.components.esp32.const import (
|
||||
VARIANT_ESP32,
|
||||
VARIANT_ESP32C2,
|
||||
|
@ -143,7 +147,7 @@ ESP32_VARIANT_ADC2_PIN_TO_CHANNEL = {
|
|||
|
||||
def validate_adc_pin(value):
|
||||
if str(value).upper() == "VCC":
|
||||
return cv.only_on_esp8266("VCC")
|
||||
return cv.only_on([PLATFORM_ESP8266, PLATFORM_RP2040])("VCC")
|
||||
|
||||
if str(value).upper() == "TEMPERATURE":
|
||||
return cv.only_on_rp2040("TEMPERATURE")
|
||||
|
|
|
@ -12,6 +12,9 @@ ADC_MODE(ADC_VCC)
|
|||
#endif
|
||||
|
||||
#ifdef USE_RP2040
|
||||
#ifdef CYW43_USES_VSYS_PIN
|
||||
#include "pico/cyw43_arch.h"
|
||||
#endif
|
||||
#include <hardware/adc.h>
|
||||
#endif
|
||||
|
||||
|
@ -123,13 +126,19 @@ void ADCSensor::dump_config() {
|
|||
}
|
||||
}
|
||||
#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: ", pin_);
|
||||
#endif // USE_ADC_SENSOR_VCC
|
||||
}
|
||||
#endif
|
||||
#endif // USE_RP2040
|
||||
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
|
@ -238,7 +247,20 @@ float ADCSensor::sample() {
|
|||
delay(1);
|
||||
adc_select_input(4);
|
||||
} else {
|
||||
uint8_t pin = this->pin_->get_pin();
|
||||
uint8_t pin;
|
||||
#ifdef USE_ADC_SENSOR_VCC
|
||||
#ifdef CYW43_USES_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
|
||||
pin = PICO_VSYS_PIN;
|
||||
#else
|
||||
pin = this->pin_->get_pin();
|
||||
#endif // USE_ADC_SENSOR_VCC
|
||||
|
||||
adc_gpio_init(pin);
|
||||
adc_select_input(pin - 26);
|
||||
}
|
||||
|
@ -246,11 +268,23 @@ float ADCSensor::sample() {
|
|||
int32_t raw = adc_read();
|
||||
if (this->is_temperature_) {
|
||||
adc_set_temp_sensor_enabled(false);
|
||||
} else {
|
||||
#ifdef USE_ADC_SENSOR_VCC
|
||||
#ifdef CYW43_USES_VSYS_PIN
|
||||
cyw43_thread_exit();
|
||||
#endif // CYW43_USES_VSYS_PIN
|
||||
#endif // USE_ADC_SENSOR_VCC
|
||||
}
|
||||
|
||||
if (output_raw_) {
|
||||
return raw;
|
||||
}
|
||||
return raw * 3.3f / 4096.0f;
|
||||
float coeff = 1.0;
|
||||
#ifdef USE_ADC_SENSOR_VCC
|
||||
// As per Raspberry Pico (W) datasheet (section 2.1) the VSYS/3 is measured
|
||||
coeff = 3.0;
|
||||
#endif // USE_ADC_SENSOR_VCC
|
||||
return raw * 3.3f / 4096.0f * coeff;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -62,3 +62,6 @@ switch:
|
|||
sensor:
|
||||
- platform: internal_temperature
|
||||
name: Internal Temperature
|
||||
- platform: adc
|
||||
pin: VCC
|
||||
name: VSYS
|
||||
|
|
Loading…
Reference in a new issue