mirror of
https://github.com/esphome/esphome.git
synced 2025-04-08 11:50:34 +01:00
add basic adc
This commit is contained in:
parent
db750fa53b
commit
101046d5de
@ -193,4 +193,9 @@ def validate_adc_pin(value):
|
||||
{CONF_ANALOG: True, CONF_INPUT: True}, internal=True
|
||||
)(value)
|
||||
|
||||
if CORE.is_nrf52:
|
||||
return pins.gpio_pin_schema(
|
||||
{CONF_ANALOG: True, CONF_INPUT: True}, internal=True
|
||||
)(value)
|
||||
|
||||
raise NotImplementedError
|
||||
|
@ -18,6 +18,10 @@ ADC_MODE(ADC_VCC)
|
||||
#include <hardware/adc.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_ZEPHYR
|
||||
static const struct adc_dt_spec adc_chan = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 1);
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace adc {
|
||||
|
||||
@ -45,7 +49,7 @@ extern "C"
|
||||
void
|
||||
ADCSensor::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str());
|
||||
#if !defined(USE_ADC_SENSOR_VCC) && !defined(USE_RP2040)
|
||||
#if !defined(USE_ADC_SENSOR_VCC) && !defined(USE_RP2040) && !defined(USE_ZEPHYR)
|
||||
pin_->setup();
|
||||
#endif
|
||||
|
||||
@ -90,6 +94,20 @@ extern "C"
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_ZEPHYR
|
||||
adc_chan_ = &adc_chan;
|
||||
if (!adc_is_ready_dt(adc_chan_)) {
|
||||
ESP_LOGE(TAG, "ADC controller device %s not ready", adc_chan_->dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
auto err = adc_channel_setup_dt(adc_chan_);
|
||||
if (err < 0) {
|
||||
ESP_LOGE(TAG, "Could not setup channel %s (%d)", adc_chan_->dev->name, err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGCONFIG(TAG, "ADC '%s' setup finished!", this->get_name().c_str());
|
||||
}
|
||||
|
||||
@ -139,6 +157,10 @@ void ADCSensor::dump_config() {
|
||||
}
|
||||
#endif // USE_RP2040
|
||||
|
||||
#ifdef USE_ZEPHYR
|
||||
ESP_LOGCONFIG(TAG, " Name: %s, channel_id: %d", adc_chan_->dev->name, adc_chan_->channel_id);
|
||||
#endif
|
||||
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
@ -298,5 +320,49 @@ float ADCSensor::sample() {
|
||||
std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; }
|
||||
#endif
|
||||
|
||||
#ifdef USE_ZEPHYR
|
||||
float ADCSensor::sample() {
|
||||
uint16_t buf;
|
||||
struct adc_sequence sequence = {
|
||||
.buffer = &buf,
|
||||
/* buffer size in bytes, not number of samples */
|
||||
.buffer_size = sizeof(buf),
|
||||
};
|
||||
int32_t val_mv;
|
||||
|
||||
adc_sequence_init_dt(adc_chan_, &sequence);
|
||||
|
||||
auto err = adc_read(adc_chan_->dev, &sequence);
|
||||
if (err < 0) {
|
||||
ESP_LOGE(TAG, "Could not read %s (%d)", adc_chan_->dev->name, err);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If using differential mode, the 16 bit value
|
||||
* in the ADC sample buffer should be a signed 2's
|
||||
* complement value.
|
||||
*/
|
||||
if (adc_chan_->channel_cfg.differential) {
|
||||
val_mv = (int32_t) ((int16_t) buf);
|
||||
} else {
|
||||
val_mv = (int32_t) buf;
|
||||
}
|
||||
|
||||
if (output_raw_) {
|
||||
return val_mv;
|
||||
}
|
||||
|
||||
err = adc_raw_to_millivolts_dt(adc_chan_, &val_mv);
|
||||
/* conversion to mV may not be supported, skip if not */
|
||||
if (err < 0) {
|
||||
ESP_LOGE(TAG, "Value in mV not available %s (%d)", adc_chan_->dev->name, err);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return val_mv / 1000.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace adc
|
||||
} // namespace esphome
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "driver/adc.h"
|
||||
#include <esp_adc_cal.h>
|
||||
#endif
|
||||
#ifdef USE_ZEPHYR
|
||||
#include <zephyr/drivers/adc.h>
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace adc {
|
||||
@ -37,7 +40,9 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
|
||||
void dump_config() override;
|
||||
/// `HARDWARE_LATE` setup priority
|
||||
float get_setup_priority() const override;
|
||||
#ifndef USE_ZEPHYR
|
||||
void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; }
|
||||
#endif
|
||||
void set_output_raw(bool output_raw) { output_raw_ = output_raw; }
|
||||
float sample() override;
|
||||
|
||||
@ -50,7 +55,11 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#ifndef USE_ZEPHYR
|
||||
InternalGPIOPin *pin_;
|
||||
#else
|
||||
const struct adc_dt_spec *adc_chan_;
|
||||
#endif
|
||||
bool output_raw_{false};
|
||||
|
||||
#ifdef USE_RP2040
|
||||
|
@ -21,6 +21,10 @@ from . import (
|
||||
ESP32_VARIANT_ADC2_PIN_TO_CHANNEL,
|
||||
validate_adc_pin,
|
||||
)
|
||||
from esphome.components.zephyr import (
|
||||
zephyr_add_overlay,
|
||||
zephyr_add_prj_conf,
|
||||
)
|
||||
|
||||
AUTO_LOAD = ["voltage_sampler"]
|
||||
|
||||
@ -85,6 +89,52 @@ async def to_code(config):
|
||||
cg.add_define("USE_ADC_SENSOR_VCC")
|
||||
elif config[CONF_PIN] == "TEMPERATURE":
|
||||
cg.add(var.set_is_temperature())
|
||||
elif CORE.using_zephyr:
|
||||
zephyr_add_prj_conf("ADC", True)
|
||||
zephyr_add_overlay(
|
||||
"""
|
||||
/ {
|
||||
zephyr,user {
|
||||
io-channels = <&adc 0>, <&adc 1>, <&adc 7>;
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
zephyr,gain = "ADC_GAIN_1_6";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||
zephyr,input-positive = <NRF_SAADC_AIN1>; /* P0.03 */
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
zephyr,gain = "ADC_GAIN_1_6";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||
zephyr,input-positive = <NRF_SAADC_VDD>;
|
||||
zephyr,resolution = <14>;
|
||||
zephyr,oversampling = <8>;
|
||||
};
|
||||
|
||||
channel@7 {
|
||||
reg = <7>;
|
||||
zephyr,gain = "ADC_GAIN_1_5";
|
||||
zephyr,reference = "ADC_REF_VDD_1_4";
|
||||
zephyr,vref-mv = <750>;
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||
zephyr,input-positive = <NRF_SAADC_AIN6>; /* P0.30 */
|
||||
zephyr,input-negative = <NRF_SAADC_AIN7>; /* P0.31 */
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
};
|
||||
"""
|
||||
)
|
||||
else:
|
||||
pin = await cg.gpio_pin_expression(config[CONF_PIN])
|
||||
cg.add(var.set_pin(pin))
|
||||
|
@ -7,6 +7,7 @@ from esphome.const import (
|
||||
CONF_MODE,
|
||||
CONF_INVERTED,
|
||||
CONF_NUMBER,
|
||||
CONF_ANALOG,
|
||||
)
|
||||
from esphome.components.zephyr.const import (
|
||||
zephyr_ns,
|
||||
@ -35,7 +36,23 @@ def _translate_pin(value):
|
||||
raise cv.Invalid(f"Invalid pin: {value}")
|
||||
|
||||
|
||||
ADC_INPUTS = [
|
||||
"AIN0",
|
||||
"AIN1",
|
||||
"AIN2",
|
||||
"AIN3",
|
||||
"AIN4",
|
||||
"AIN5",
|
||||
"AIN6",
|
||||
"AIN7",
|
||||
"VDD",
|
||||
"VDDH",
|
||||
]
|
||||
|
||||
|
||||
def validate_gpio_pin(value):
|
||||
if value in ADC_INPUTS:
|
||||
return value
|
||||
value = _translate_pin(value)
|
||||
if value < 0 or value > (32 + 16):
|
||||
raise cv.Invalid(f"NRF52: Invalid pin number: {value}")
|
||||
@ -43,7 +60,11 @@ def validate_gpio_pin(value):
|
||||
|
||||
|
||||
NRF52_PIN_SCHEMA = cv.All(
|
||||
pins.gpio_base_schema(GPIOPin, validate_gpio_pin, modes=pins.GPIO_STANDARD_MODES),
|
||||
pins.gpio_base_schema(
|
||||
GPIOPin,
|
||||
validate_gpio_pin,
|
||||
modes=pins.GPIO_STANDARD_MODES + (CONF_ANALOG,),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
namespace esphome {
|
||||
namespace zephyr {
|
||||
|
||||
static const char *const TAG = "nrf52";
|
||||
static const char *const TAG = "zephyr";
|
||||
|
||||
static int flags_to_mode(gpio::Flags flags, uint8_t pin, bool inverted, bool value) {
|
||||
int ret = 0;
|
||||
|
@ -79,9 +79,16 @@ zephyr_debug:
|
||||
|
||||
debug:
|
||||
|
||||
text_sensor:
|
||||
- platform: debug
|
||||
device:
|
||||
name: "Device Info"
|
||||
reset_reason:
|
||||
name: "Reset Reason"
|
||||
sensor:
|
||||
- platform: adc
|
||||
pin: VDDH
|
||||
name: "VDDH Voltage"
|
||||
update_interval: 5sec
|
||||
- platform: adc
|
||||
pin: VDD
|
||||
name: "VDD Voltage"
|
||||
update_interval: 5sec
|
||||
- platform: adc
|
||||
pin: AIN0
|
||||
name: "AIN0 Voltage"
|
||||
update_interval: 5sec
|
||||
|
Loading…
x
Reference in New Issue
Block a user