mirror of
https://github.com/esphome/esphome.git
synced 2025-03-01 00:08:15 +00:00
Use esp_adc/adc_cali.h for IDF v5
This add compatibility to ESP-IDF v5 to the ADC component, preventing the warning message related to the deprecated libraries.
This commit is contained in:
parent
bf2823a52c
commit
5a4e4f6454
@ -3,17 +3,50 @@
|
|||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
#include "esphome/components/voltage_sampler/voltage_sampler.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/hal.h"
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
#include "esp_adc/adc_oneshot.h"
|
||||||
|
#include "esp_adc/adc_cali.h"
|
||||||
|
#include "esp_adc/adc_cali_scheme.h"
|
||||||
|
#else
|
||||||
#include <esp_adc_cal.h>
|
#include <esp_adc_cal.h>
|
||||||
#include "driver/adc.h"
|
#include "driver/adc.h"
|
||||||
|
#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
#endif // USE_ESP32
|
#endif // USE_ESP32
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace adc {
|
namespace adc {
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
// Map old channel names to new ones for compatibility
|
||||||
|
#define ADC1_CHANNEL_0 ADC_CHANNEL_0
|
||||||
|
#define ADC1_CHANNEL_1 ADC_CHANNEL_1
|
||||||
|
#define ADC1_CHANNEL_2 ADC_CHANNEL_2
|
||||||
|
#define ADC1_CHANNEL_3 ADC_CHANNEL_3
|
||||||
|
#define ADC1_CHANNEL_4 ADC_CHANNEL_4
|
||||||
|
#define ADC1_CHANNEL_5 ADC_CHANNEL_5
|
||||||
|
#define ADC1_CHANNEL_6 ADC_CHANNEL_6
|
||||||
|
#define ADC1_CHANNEL_7 ADC_CHANNEL_7
|
||||||
|
#define ADC1_CHANNEL_MAX ADC_CHANNEL_MAX
|
||||||
|
|
||||||
|
#define ADC2_CHANNEL_0 ADC_CHANNEL_0
|
||||||
|
#define ADC2_CHANNEL_1 ADC_CHANNEL_1
|
||||||
|
#define ADC2_CHANNEL_2 ADC_CHANNEL_2
|
||||||
|
#define ADC2_CHANNEL_3 ADC_CHANNEL_3
|
||||||
|
#define ADC2_CHANNEL_4 ADC_CHANNEL_4
|
||||||
|
#define ADC2_CHANNEL_5 ADC_CHANNEL_5
|
||||||
|
#define ADC2_CHANNEL_6 ADC_CHANNEL_6
|
||||||
|
#define ADC2_CHANNEL_7 ADC_CHANNEL_7
|
||||||
|
#define ADC2_CHANNEL_8 ADC_CHANNEL_8
|
||||||
|
#define ADC2_CHANNEL_9 ADC_CHANNEL_9
|
||||||
|
#define ADC2_CHANNEL_MAX ADC_CHANNEL_MAX
|
||||||
|
#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 7)) || \
|
#if (ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 7)) || \
|
||||||
(ESP_IDF_VERSION_MAJOR == 5 && \
|
(ESP_IDF_VERSION_MAJOR == 5 && \
|
||||||
@ -25,37 +58,106 @@ namespace adc {
|
|||||||
static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_12;
|
static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_12;
|
||||||
#else
|
#else
|
||||||
static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_11;
|
static const adc_atten_t ADC_ATTEN_DB_12_COMPAT = ADC_ATTEN_DB_11;
|
||||||
#endif
|
#endif // ESP_IDF_VERSION check for ADC_ATTEN_DB_12_COMPAT
|
||||||
#endif // USE_ESP32
|
#endif // USE_ESP32
|
||||||
|
|
||||||
class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler {
|
class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage_sampler::VoltageSampler {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// Update the sensor's state by reading the current ADC value.
|
||||||
|
/// This method is called periodically based on the update interval.
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
/// Set up the ADC sensor by initializing hardware and calibration parameters.
|
||||||
|
/// This method is called once during device initialization.
|
||||||
|
void setup() override;
|
||||||
|
|
||||||
|
/// Output the configuration details of the ADC sensor for debugging purposes.
|
||||||
|
/// This method is called during the ESPHome setup process to log the configuration.
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
/// Return the setup priority for this component.
|
||||||
|
/// Components with higher priority are initialized earlier during setup.
|
||||||
|
/// @return A float representing the setup priority.
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
|
||||||
|
/// Set the GPIO pin to be used by the ADC sensor.
|
||||||
|
/// @param pin Pointer to an InternalGPIOPin representing the ADC input pin.
|
||||||
|
void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; }
|
||||||
|
|
||||||
|
/// Enable or disable the output of raw ADC values (unprocessed data).
|
||||||
|
/// @param output_raw Boolean indicating whether to output raw ADC values (true) or processed values (false).
|
||||||
|
void set_output_raw(bool output_raw) { this->output_raw_ = output_raw; }
|
||||||
|
|
||||||
|
/// Set the number of samples to be taken for ADC readings to improve accuracy.
|
||||||
|
/// A higher sample count reduces noise but increases the reading time.
|
||||||
|
/// @param sample_count The number of samples (e.g., 1, 4, 8).
|
||||||
|
void set_sample_count(uint8_t sample_count);
|
||||||
|
|
||||||
|
/// Perform a single ADC sampling operation and return the measured value.
|
||||||
|
/// This function handles raw readings, calibration, and averaging as needed.
|
||||||
|
/// @return The sampled value as a float.
|
||||||
|
float sample() override;
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
/// Set the attenuation for this pin. Only available on the ESP32.
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
/// Set the ADC attenuation level to adjust the input voltage range.
|
||||||
|
/// This determines how the ADC interprets input voltages, allowing for greater precision
|
||||||
|
/// or the ability to measure higher voltages depending on the chosen attenuation level.
|
||||||
|
/// @param attenuation The desired ADC attenuation level (e.g., ADC_ATTEN_DB_0, ADC_ATTEN_DB_11).
|
||||||
|
void set_attenuation(adc_atten_t attenuation) {
|
||||||
|
this->attenuation_ = attenuation;
|
||||||
|
this->do_setup_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configure the ADC to use a specific channel on ADC1.
|
||||||
|
/// This sets the channel for single-shot or continuous ADC measurements.
|
||||||
|
/// @param channel The ADC1 channel to configure, such as ADC_CHANNEL_0, ADC_CHANNEL_3, etc.
|
||||||
|
void set_channel1(adc_channel_t channel) {
|
||||||
|
this->channel_ = channel;
|
||||||
|
this->is_adc1_ = true;
|
||||||
|
this->do_setup_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configure the ADC to use a specific channel on ADC2.
|
||||||
|
/// This sets the channel for single-shot or continuous ADC measurements.
|
||||||
|
/// ADC2 is shared with other peripherals, so care must be taken to avoid conflicts.
|
||||||
|
/// @param channel The ADC2 channel to configure, such as ADC_CHANNEL_0, ADC_CHANNEL_3, etc.
|
||||||
|
void set_channel2(adc_channel_t channel) {
|
||||||
|
this->channel_ = channel;
|
||||||
|
this->is_adc1_ = false;
|
||||||
|
this->do_setup_ = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/// Set the ADC attenuation level to adjust the input voltage range.
|
||||||
|
/// This determines how the ADC interprets input voltages, allowing for greater precision
|
||||||
|
/// or the ability to measure higher voltages depending on the chosen attenuation level.
|
||||||
|
/// @param attenuation The desired ADC attenuation level (e.g., ADC_ATTEN_DB_0, ADC_ATTEN_DB_11).
|
||||||
void set_attenuation(adc_atten_t attenuation) { this->attenuation_ = attenuation; }
|
void set_attenuation(adc_atten_t attenuation) { this->attenuation_ = attenuation; }
|
||||||
|
|
||||||
|
/// Configure the ADC to use a specific channel on ADC1.
|
||||||
|
/// This sets the ADC1 channel for measurement and disables ADC2 channel usage.
|
||||||
|
/// @param channel The ADC1 channel to configure (e.g., ADC1_CHANNEL_0, ADC1_CHANNEL_3).
|
||||||
void set_channel1(adc1_channel_t channel) {
|
void set_channel1(adc1_channel_t channel) {
|
||||||
this->channel1_ = channel;
|
this->channel1_ = channel;
|
||||||
this->channel2_ = ADC2_CHANNEL_MAX;
|
this->channel2_ = ADC2_CHANNEL_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configure the ADC to use a specific channel on ADC2.
|
||||||
|
/// This sets the ADC2 channel for measurement and disables ADC1 channel usage.
|
||||||
|
/// Note: ADC2 may have limitations due to shared resources with Wi-Fi or other peripherals.
|
||||||
|
/// @param channel The ADC2 channel to configure (e.g., ADC2_CHANNEL_0, ADC2_CHANNEL_3).
|
||||||
void set_channel2(adc2_channel_t channel) {
|
void set_channel2(adc2_channel_t channel) {
|
||||||
this->channel2_ = channel;
|
this->channel2_ = channel;
|
||||||
this->channel1_ = ADC1_CHANNEL_MAX;
|
this->channel1_ = ADC1_CHANNEL_MAX;
|
||||||
}
|
}
|
||||||
|
#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
/// Set whether autoranging should be enabled for the ADC.
|
||||||
|
/// Autoranging automatically adjusts the attenuation level to handle a wide range of input voltages.
|
||||||
|
/// @param autorange Boolean indicating whether to enable autoranging.
|
||||||
void set_autorange(bool autorange) { this->autorange_ = autorange; }
|
void set_autorange(bool autorange) { this->autorange_ = autorange; }
|
||||||
#endif // USE_ESP32
|
#endif // USE_ESP32
|
||||||
|
|
||||||
/// Update ADC values
|
|
||||||
void update() override;
|
|
||||||
/// Setup ADC
|
|
||||||
void setup() override;
|
|
||||||
void dump_config() override;
|
|
||||||
/// `HARDWARE_LATE` setup priority
|
|
||||||
float get_setup_priority() const override;
|
|
||||||
void set_pin(InternalGPIOPin *pin) { this->pin_ = pin; }
|
|
||||||
void set_output_raw(bool output_raw) { this->output_raw_ = output_raw; }
|
|
||||||
void set_sample_count(uint8_t sample_count);
|
|
||||||
float sample() override;
|
|
||||||
|
|
||||||
#ifdef USE_ESP8266
|
#ifdef USE_ESP8266
|
||||||
std::string unique_id() override;
|
std::string unique_id() override;
|
||||||
#endif // USE_ESP8266
|
#endif // USE_ESP8266
|
||||||
@ -69,21 +171,31 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
|
|||||||
bool output_raw_{false};
|
bool output_raw_{false};
|
||||||
uint8_t sample_count_{1};
|
uint8_t sample_count_{1};
|
||||||
|
|
||||||
#ifdef USE_RP2040
|
|
||||||
bool is_temperature_{false};
|
|
||||||
#endif // USE_RP2040
|
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
bool autorange_{false};
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
adc_oneshot_unit_handle_t adc1_handle_{nullptr};
|
||||||
|
adc_oneshot_unit_handle_t adc2_handle_{nullptr};
|
||||||
|
adc_cali_handle_t calibration_handle_{nullptr};
|
||||||
|
adc_atten_t attenuation_{ADC_ATTEN_DB_0};
|
||||||
|
adc_channel_t channel_;
|
||||||
|
bool is_adc1_{true};
|
||||||
|
bool do_setup_{false};
|
||||||
|
#else
|
||||||
adc_atten_t attenuation_{ADC_ATTEN_DB_0};
|
adc_atten_t attenuation_{ADC_ATTEN_DB_0};
|
||||||
adc1_channel_t channel1_{ADC1_CHANNEL_MAX};
|
adc1_channel_t channel1_{ADC1_CHANNEL_MAX};
|
||||||
adc2_channel_t channel2_{ADC2_CHANNEL_MAX};
|
adc2_channel_t channel2_{ADC2_CHANNEL_MAX};
|
||||||
bool autorange_{false};
|
|
||||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
esp_adc_cal_characteristics_t cal_characteristics_[SOC_ADC_ATTEN_NUM] = {};
|
esp_adc_cal_characteristics_t cal_characteristics_[SOC_ADC_ATTEN_NUM] = {};
|
||||||
#else
|
#else
|
||||||
esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {};
|
esp_adc_cal_characteristics_t cal_characteristics_[ADC_ATTEN_MAX] = {};
|
||||||
#endif // ESP_IDF_VERSION_MAJOR
|
#endif // ESP_IDF_VERSION_MAJOR >= 5
|
||||||
|
#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
#endif // USE_ESP32
|
#endif // USE_ESP32
|
||||||
|
|
||||||
|
#ifdef USE_RP2040
|
||||||
|
bool is_temperature_{false};
|
||||||
|
#endif // USE_RP2040
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace adc
|
} // namespace adc
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "adc_sensor.h"
|
#include "adc_sensor.h"
|
||||||
#include "esphome/core/log.h"
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace adc {
|
namespace adc {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include "adc_sensor.h"
|
#include "adc_sensor.h"
|
||||||
#include "esphome/core/log.h"
|
|
||||||
|
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace adc {
|
namespace adc {
|
||||||
|
|
||||||
static const char *const TAG = "adc.esp32";
|
static const char *const TAG = "adc.esp32.v4";
|
||||||
|
|
||||||
static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast<adc_bits_width_t>(ADC_WIDTH_MAX - 1);
|
static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast<adc_bits_width_t>(ADC_WIDTH_MAX - 1);
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ void ADCSensor::dump_config() {
|
|||||||
case ADC_ATTEN_DB_12_COMPAT:
|
case ADC_ATTEN_DB_12_COMPAT:
|
||||||
ESP_LOGCONFIG(TAG, " Attenuation: 12db");
|
ESP_LOGCONFIG(TAG, " Attenuation: 12db");
|
||||||
break;
|
break;
|
||||||
default: // This is to satisfy the unused ADC_ATTEN_MAX
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,4 +161,6 @@ float ADCSensor::sample() {
|
|||||||
} // namespace adc
|
} // namespace adc
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
|
||||||
#endif // USE_ESP32
|
#endif // USE_ESP32
|
203
esphome/components/adc/adc_sensor_esp32_v5.cpp
Normal file
203
esphome/components/adc/adc_sensor_esp32_v5.cpp
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
#include "adc_sensor.h"
|
||||||
|
|
||||||
|
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0))
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace adc {
|
||||||
|
|
||||||
|
static const char *const TAG = "adc.esp32.v5";
|
||||||
|
|
||||||
|
void ADCSensor::setup() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str());
|
||||||
|
|
||||||
|
if (!this->do_setup_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->is_adc1_) {
|
||||||
|
if (this->adc1_handle_ == nullptr) {
|
||||||
|
adc_oneshot_unit_init_cfg_t init_config1 = {
|
||||||
|
.unit_id = ADC_UNIT_1,
|
||||||
|
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &this->adc1_handle_));
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_oneshot_chan_cfg_t config = {
|
||||||
|
.atten = this->attenuation_,
|
||||||
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(this->adc1_handle_, this->channel_, &config));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (this->adc2_handle_ == nullptr) {
|
||||||
|
adc_oneshot_unit_init_cfg_t init_config2 = {
|
||||||
|
.unit_id = ADC_UNIT_2,
|
||||||
|
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config2, &this->adc2_handle_));
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_oneshot_chan_cfg_t config = {
|
||||||
|
.atten = this->attenuation_,
|
||||||
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(this->adc2_handle_, this->channel_, &config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize ADC calibration
|
||||||
|
if (this->calibration_handle_ == nullptr) {
|
||||||
|
adc_cali_handle_t handle = nullptr;
|
||||||
|
adc_unit_t unit_id = this->is_adc1_ ? ADC_UNIT_1 : ADC_UNIT_2;
|
||||||
|
adc_cali_line_fitting_config_t cali_config = {
|
||||||
|
.unit_id = unit_id,
|
||||||
|
.atten = this->attenuation_,
|
||||||
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (adc_cali_create_scheme_line_fitting(&cali_config, &handle) == ESP_OK) {
|
||||||
|
this->calibration_handle_ = handle;
|
||||||
|
ESP_LOGV(TAG, "Using line fitting for calibration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->do_setup_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADCSensor::dump_config() {
|
||||||
|
LOG_SENSOR("", "ADC Sensor", this);
|
||||||
|
LOG_PIN(" Pin: ", this->pin_);
|
||||||
|
if (this->autorange_) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Attenuation: auto");
|
||||||
|
} else {
|
||||||
|
switch (this->attenuation_) {
|
||||||
|
case ADC_ATTEN_DB_0:
|
||||||
|
ESP_LOGCONFIG(TAG, " Attenuation: 0db");
|
||||||
|
break;
|
||||||
|
case ADC_ATTEN_DB_2_5:
|
||||||
|
ESP_LOGCONFIG(TAG, " Attenuation: 2.5db");
|
||||||
|
break;
|
||||||
|
case ADC_ATTEN_DB_6:
|
||||||
|
ESP_LOGCONFIG(TAG, " Attenuation: 6db");
|
||||||
|
break;
|
||||||
|
case ADC_ATTEN_DB_12:
|
||||||
|
ESP_LOGCONFIG(TAG, " Attenuation: 12db");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_LOGCONFIG(TAG, " Samples: %i", this->sample_count_);
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ADCSensor::sample() {
|
||||||
|
if (!this->autorange_) {
|
||||||
|
uint32_t sum = 0;
|
||||||
|
for (uint8_t sample = 0; sample < this->sample_count_; sample++) {
|
||||||
|
int raw = -1;
|
||||||
|
if (this->is_adc1_) {
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_read(this->adc1_handle_, this->channel_, &raw));
|
||||||
|
} else {
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_read(this->adc2_handle_, this->channel_, &raw));
|
||||||
|
}
|
||||||
|
if (raw == -1) {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
sum += raw;
|
||||||
|
}
|
||||||
|
sum = (sum + (this->sample_count_ >> 1)) / this->sample_count_; // NOLINT(clang-analyzer-core.DivideZero)
|
||||||
|
|
||||||
|
if (this->output_raw_) {
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->calibration_handle_ != nullptr) {
|
||||||
|
int voltage_mv;
|
||||||
|
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(this->calibration_handle_, sum, &voltage_mv));
|
||||||
|
return voltage_mv / 1000.0f;
|
||||||
|
}
|
||||||
|
return sum * 3.3f / 4095.0f; // Fallback if no calibration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-range mode
|
||||||
|
int raw12 = 4095, raw6 = 4095, raw2 = 4095, raw0 = 4095;
|
||||||
|
float mv12 = 0, mv6 = 0, mv2 = 0, mv0 = 0;
|
||||||
|
|
||||||
|
// Helper lambda for reading with different attenuations
|
||||||
|
auto read_atten = [this](adc_atten_t atten) -> std::pair<int, float> {
|
||||||
|
if (this->is_adc1_) {
|
||||||
|
adc_oneshot_chan_cfg_t config = {
|
||||||
|
.atten = atten,
|
||||||
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(this->adc1_handle_, this->channel_, &config));
|
||||||
|
int raw;
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_read(this->adc1_handle_, this->channel_, &raw));
|
||||||
|
if (this->calibration_handle_ != nullptr) {
|
||||||
|
int voltage_mv;
|
||||||
|
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(this->calibration_handle_, raw, &voltage_mv));
|
||||||
|
return {raw, voltage_mv / 1000.0f};
|
||||||
|
}
|
||||||
|
return {raw, raw * 3.3f / 4095.0f};
|
||||||
|
} else {
|
||||||
|
adc_oneshot_chan_cfg_t config = {
|
||||||
|
.atten = atten,
|
||||||
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_config_channel(this->adc2_handle_, this->channel_, &config));
|
||||||
|
int raw;
|
||||||
|
ESP_ERROR_CHECK(adc_oneshot_read(this->adc2_handle_, this->channel_, &raw));
|
||||||
|
if (this->calibration_handle_ != nullptr) {
|
||||||
|
int voltage_mv;
|
||||||
|
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(this->calibration_handle_, raw, &voltage_mv));
|
||||||
|
return {raw, voltage_mv / 1000.0f};
|
||||||
|
}
|
||||||
|
return {raw, raw * 3.3f / 4095.0f};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto [raw12_val, mv12_val] = read_atten(ADC_ATTEN_DB_12);
|
||||||
|
raw12 = raw12_val;
|
||||||
|
mv12 = mv12_val;
|
||||||
|
|
||||||
|
if (raw12 < 4095) {
|
||||||
|
auto [raw6_val, mv6_val] = read_atten(ADC_ATTEN_DB_6);
|
||||||
|
raw6 = raw6_val;
|
||||||
|
mv6 = mv6_val;
|
||||||
|
|
||||||
|
if (raw6 < 4095) {
|
||||||
|
auto [raw2_val, mv2_val] = read_atten(ADC_ATTEN_DB_2_5);
|
||||||
|
raw2 = raw2_val;
|
||||||
|
mv2 = mv2_val;
|
||||||
|
|
||||||
|
if (raw2 < 4095) {
|
||||||
|
auto [raw0_val, mv0_val] = read_atten(ADC_ATTEN_DB_0);
|
||||||
|
raw0 = raw0_val;
|
||||||
|
mv0 = mv0_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw0 == -1 || raw2 == -1 || raw6 == -1 || raw12 == -1) {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int ADC_HALF = 2048;
|
||||||
|
uint32_t c12 = std::min(raw12, ADC_HALF);
|
||||||
|
uint32_t c6 = ADC_HALF - std::abs(raw6 - ADC_HALF);
|
||||||
|
uint32_t c2 = ADC_HALF - std::abs(raw2 - ADC_HALF);
|
||||||
|
uint32_t c0 = std::min(4095 - raw0, ADC_HALF);
|
||||||
|
uint32_t csum = c12 + c6 + c2 + c0;
|
||||||
|
|
||||||
|
return (mv12 * c12 + mv6 * c6 + mv2 * c2 + mv0 * c0) / csum;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace adc
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||||
|
|
||||||
|
#endif // USE_ESP32
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "adc_sensor.h"
|
#include "adc_sensor.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
|
||||||
|
|
||||||
#ifdef USE_ADC_SENSOR_VCC
|
#ifdef USE_ADC_SENSOR_VCC
|
||||||
#include <Esp.h>
|
#include <Esp.h>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
|
|
||||||
#include "adc_sensor.h"
|
#include "adc_sensor.h"
|
||||||
#include "esphome/core/log.h"
|
|
||||||
|
|
||||||
#ifdef CYW43_USES_VSYS_PIN
|
#ifdef CYW43_USES_VSYS_PIN
|
||||||
#include "pico/cyw43_arch.h"
|
#include "pico/cyw43_arch.h"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user