mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 12:37:45 +01:00
Correct ADC auto-range for ESP32-S2 variant (13 bit adc) (#3158)
Co-authored-by: Otto Winter <otto@otto-winter.com>
This commit is contained in:
parent
d0dda48932
commit
dd24ffa24e
@ -15,10 +15,21 @@ namespace esphome {
|
||||
namespace adc {
|
||||
|
||||
static const char *const TAG = "adc";
|
||||
// 13 bits for S3 / 12 bit for all other esp32 variants
|
||||
// create a const to avoid the repated cast to enum
|
||||
|
||||
// 13bit for S2, and 12bit for all other esp32 variants
|
||||
#ifdef USE_ESP32
|
||||
static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast<adc_bits_width_t>(ADC_WIDTH_MAX - 1);
|
||||
|
||||
#ifndef SOC_ADC_RTC_MAX_BITWIDTH
|
||||
#if USE_ESP32_VARIANT_ESP32S2
|
||||
static const int SOC_ADC_RTC_MAX_BITWIDTH = 13;
|
||||
#else
|
||||
static const int SOC_ADC_RTC_MAX_BITWIDTH = 12;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1; // 4095 (12 bit) or 8191 (13 bit)
|
||||
static const int ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1; // 2048 (12 bit) or 4096 (13 bit)
|
||||
#endif
|
||||
|
||||
void ADCSensor::setup() {
|
||||
@ -75,16 +86,16 @@ void ADCSensor::dump_config() {
|
||||
} else {
|
||||
switch (this->attenuation_) {
|
||||
case ADC_ATTEN_DB_0:
|
||||
ESP_LOGCONFIG(TAG, " Attenuation: 0db (max 1.1V)");
|
||||
ESP_LOGCONFIG(TAG, " Attenuation: 0db");
|
||||
break;
|
||||
case ADC_ATTEN_DB_2_5:
|
||||
ESP_LOGCONFIG(TAG, " Attenuation: 2.5db (max 1.5V)");
|
||||
ESP_LOGCONFIG(TAG, " Attenuation: 2.5db");
|
||||
break;
|
||||
case ADC_ATTEN_DB_6:
|
||||
ESP_LOGCONFIG(TAG, " Attenuation: 6db (max 2.2V)");
|
||||
ESP_LOGCONFIG(TAG, " Attenuation: 6db");
|
||||
break;
|
||||
case ADC_ATTEN_DB_11:
|
||||
ESP_LOGCONFIG(TAG, " Attenuation: 11db (max 3.9V)");
|
||||
ESP_LOGCONFIG(TAG, " Attenuation: 11db");
|
||||
break;
|
||||
default: // This is to satisfy the unused ADC_ATTEN_MAX
|
||||
break;
|
||||
@ -129,16 +140,16 @@ float ADCSensor::sample() {
|
||||
return mv / 1000.0f;
|
||||
}
|
||||
|
||||
int raw11, raw6 = 4095, raw2 = 4095, raw0 = 4095;
|
||||
int raw11, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX;
|
||||
adc1_config_channel_atten(channel_, ADC_ATTEN_DB_11);
|
||||
raw11 = adc1_get_raw(channel_);
|
||||
if (raw11 < 4095) {
|
||||
if (raw11 < ADC_MAX) {
|
||||
adc1_config_channel_atten(channel_, ADC_ATTEN_DB_6);
|
||||
raw6 = adc1_get_raw(channel_);
|
||||
if (raw6 < 4095) {
|
||||
if (raw6 < ADC_MAX) {
|
||||
adc1_config_channel_atten(channel_, ADC_ATTEN_DB_2_5);
|
||||
raw2 = adc1_get_raw(channel_);
|
||||
if (raw2 < 4095) {
|
||||
if (raw2 < ADC_MAX) {
|
||||
adc1_config_channel_atten(channel_, ADC_ATTEN_DB_0);
|
||||
raw0 = adc1_get_raw(channel_);
|
||||
}
|
||||
@ -154,15 +165,15 @@ float ADCSensor::sample() {
|
||||
uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int) ADC_ATTEN_DB_2_5]);
|
||||
uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int) ADC_ATTEN_DB_0]);
|
||||
|
||||
// Contribution of each value, in range 0-2048
|
||||
uint32_t c11 = std::min(raw11, 2048);
|
||||
uint32_t c6 = 2048 - std::abs(raw6 - 2048);
|
||||
uint32_t c2 = 2048 - std::abs(raw2 - 2048);
|
||||
uint32_t c0 = std::min(4095 - raw0, 2048);
|
||||
// max theoretical csum value is 2048*4 = 8192
|
||||
// Contribution of each value, in range 0-2048 (12 bit ADC) or 0-4096 (13 bit ADC)
|
||||
uint32_t c11 = std::min(raw11, 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(ADC_MAX - raw0, ADC_HALF);
|
||||
// max theoretical csum value is 4096*4 = 16384
|
||||
uint32_t csum = c11 + c6 + c2 + c0;
|
||||
|
||||
// each mv is max 3900; so max value is 3900*2048*4, fits in unsigned
|
||||
// each mv is max 3900; so max value is 3900*4096*4, fits in unsigned32
|
||||
uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0);
|
||||
return mv_scaled / (float) (csum * 1000U);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user