Merge pull request #32 from m-RNA/update/AdcSampler

refactor(Monitoring): abstract platform-specific ADC code and add ESP32-S2 support
This commit is contained in:
Lorow
2026-02-05 23:25:44 +01:00
committed by GitHub
6 changed files with 159 additions and 54 deletions

View File

@@ -9,14 +9,30 @@
# +-----------------------+ # +-----------------------+
# | ESP-IDF ADC HAL | ← Espressif official driver # | ESP-IDF ADC HAL | ← Espressif official driver
# +-----------------------+ # +-----------------------+
#
# Supported platforms (must support ESP-CAM):
# - ESP32: Tested
# - ESP32-S3: Tested
# - ESP32-S2: UNTESTED - Based on datasheet
set( set(
requires requires
Helpers Helpers
) )
# List of supported ADC platforms (aligned with ESP_CAMERA_SUPPORTED)
set(ADC_SUPPORTED_TARGETS "esp32" "esp32s3" "esp32s2")
# Check if current target supports ADC
list(FIND ADC_SUPPORTED_TARGETS "$ENV{IDF_TARGET}" ADC_TARGET_INDEX)
if (NOT ADC_TARGET_INDEX EQUAL -1)
set(ADC_SAMPLER_SUPPORTED TRUE)
else()
set(ADC_SAMPLER_SUPPORTED FALSE)
endif()
# Platform-specific dependencies # Platform-specific dependencies
if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3" OR "$ENV{IDF_TARGET}" STREQUAL "esp32") if (ADC_SAMPLER_SUPPORTED)
list(APPEND requires list(APPEND requires
driver driver
esp_adc esp_adc
@@ -32,22 +48,20 @@ set(
) )
# BSP Layer: ADC sampler implementation # BSP Layer: ADC sampler implementation
if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3" OR "$ENV{IDF_TARGET}" STREQUAL "esp32") if (ADC_SAMPLER_SUPPORTED)
# Common ADC implementation # Common ADC implementation
list(APPEND source_files list(APPEND source_files
"Monitoring/AdcSampler.cpp" "Monitoring/AdcSampler.cpp"
) )
# Platform-specific GPIO-to-channel mapping # Platform-specific GPIO-to-channel mapping and calibration
if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3") if ("$ENV{IDF_TARGET}" STREQUAL "esp32s3")
list(APPEND source_files list(APPEND source_files "Monitoring/AdcSampler_esp32s3.cpp")
"Monitoring/AdcSampler_esp32s3.cpp" elseif ("$ENV{IDF_TARGET}" STREQUAL "esp32s2")
) list(APPEND source_files "Monitoring/AdcSampler_esp32s2.cpp")
elseif ("$ENV{IDF_TARGET}" STREQUAL "esp32") elseif ("$ENV{IDF_TARGET}" STREQUAL "esp32")
list(APPEND source_files list(APPEND source_files "Monitoring/AdcSampler_esp32.cpp")
"Monitoring/AdcSampler_esp32.cpp" endif()
)
endif()
endif() endif()

View File

@@ -3,14 +3,15 @@
* @brief BSP Layer - Common ADC sampling implementation * @brief BSP Layer - Common ADC sampling implementation
* *
* This file contains platform-independent ADC sampling logic. * This file contains platform-independent ADC sampling logic.
* Platform-specific GPIO-to-channel mapping is in separate files: * Platform-specific implementations are in separate files:
* - AdcSampler_esp32.cpp * - AdcSampler_esp32.cpp (Tested)
* - AdcSampler_esp32s3.cpp * - AdcSampler_esp32s3.cpp (Tested)
* - AdcSampler_esp32s2.cpp (UNTESTED)
*/ */
#include "AdcSampler.hpp" #include "AdcSampler.hpp"
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32) #if ADC_SAMPLER_SUPPORTED
#include <esp_log.h> #include <esp_log.h>
static const char* TAG = "[AdcSampler]"; static const char* TAG = "[AdcSampler]";
@@ -22,11 +23,7 @@ AdcSampler::~AdcSampler()
{ {
if (cali_handle_) if (cali_handle_)
{ {
#if defined(CONFIG_IDF_TARGET_ESP32S3) delete_calibration(cali_handle_);
adc_cali_delete_scheme_curve_fitting(cali_handle_);
#elif defined(CONFIG_IDF_TARGET_ESP32)
adc_cali_delete_scheme_line_fitting(cali_handle_);
#endif
cali_handle_ = nullptr; cali_handle_ = nullptr;
} }
} }
@@ -66,29 +63,8 @@ bool AdcSampler::init(int gpio, adc_atten_t atten, adc_bitwidth_t bitwidth, size
} }
// Try calibration (requires eFuse data) // Try calibration (requires eFuse data)
// ESP32-S3 uses curve-fitting, ESP32 uses line-fitting // Platform-specific: ESP32-S3/S2 use curve-fitting, ESP32 uses line-fitting
esp_err_t cal_err = ESP_FAIL; if (create_calibration(&cali_handle_))
#if defined(CONFIG_IDF_TARGET_ESP32S3)
// ESP32-S3 curve fitting calibration
adc_cali_curve_fitting_config_t cal_cfg = {
.unit_id = unit_,
.chan = channel_,
.atten = atten_,
.bitwidth = bitwidth_,
};
cal_err = adc_cali_create_scheme_curve_fitting(&cal_cfg, &cali_handle_);
#elif defined(CONFIG_IDF_TARGET_ESP32)
// ESP32 line-fitting calibration is per-unit, not per-channel
adc_cali_line_fitting_config_t cal_cfg = {
.unit_id = unit_,
.atten = atten_,
.bitwidth = bitwidth_,
};
cal_err = adc_cali_create_scheme_line_fitting(&cal_cfg, &cali_handle_);
#endif
if (cal_err == ESP_OK)
{ {
cali_inited_ = true; cali_inited_ = true;
ESP_LOGI(TAG, "ADC calibration initialized"); ESP_LOGI(TAG, "ADC calibration initialized");
@@ -193,4 +169,4 @@ bool AdcSampler::configure_channel(int gpio, adc_atten_t atten, adc_bitwidth_t b
return true; return true;
} }
#endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32 #endif // ADC_SAMPLER_SUPPORTED

View File

@@ -20,7 +20,17 @@
#include <cstdint> #include <cstdint>
#include "sdkconfig.h" #include "sdkconfig.h"
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32) // Supported ESP32 platforms with ADC1 oneshot driver
// - ESP32: Tested
// - ESP32-S3: Tested
// - ESP32-S2: UNTESTED - GPIO mapping based on datasheet
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2)
#define ADC_SAMPLER_SUPPORTED 1
#else
#define ADC_SAMPLER_SUPPORTED 0
#endif
#if ADC_SAMPLER_SUPPORTED
#include <vector> #include <vector>
#include "esp_adc/adc_cali.h" #include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h" #include "esp_adc/adc_cali_scheme.h"
@@ -86,10 +96,22 @@ class AdcSampler
/** /**
* @brief Platform-specific GPIO to ADC channel mapping * @brief Platform-specific GPIO to ADC channel mapping
* @note Implemented separately in AdcSampler_esp32.cpp and AdcSampler_esp32s3.cpp * @note Implemented in AdcSampler_esp32.cpp, AdcSampler_esp32s3 and AdcSampler_esp32s2.cpp
*/ */
static bool map_gpio_to_channel(int gpio, adc_unit_t& unit, adc_channel_t& channel); static bool map_gpio_to_channel(int gpio, adc_unit_t& unit, adc_channel_t& channel);
/**
* @brief Platform-specific ADC calibration initialization
* @note Implemented in AdcSampler_esp32.cpp, AdcSampler_esp32s3 and AdcSampler_esp32s2.cpp
*/
bool create_calibration(adc_cali_handle_t* handle);
/**
* @brief Platform-specific ADC calibration cleanup
* @note Implemented in AdcSampler_esp32.cpp, AdcSampler_esp32s3 and AdcSampler_esp32s2.cpp
*/
void delete_calibration(adc_cali_handle_t handle);
// Shared ADC1 oneshot handle (single instance for all AdcSampler objects) // Shared ADC1 oneshot handle (single instance for all AdcSampler objects)
static adc_oneshot_unit_handle_t shared_unit_; static adc_oneshot_unit_handle_t shared_unit_;
@@ -109,7 +131,7 @@ class AdcSampler
int filtered_mv_{0}; int filtered_mv_{0};
}; };
#else #else // !ADC_SAMPLER_SUPPORTED
// Stub for unsupported targets to keep interfaces consistent // Stub for unsupported targets to keep interfaces consistent
class AdcSampler class AdcSampler
{ {
@@ -131,4 +153,4 @@ class AdcSampler
return false; return false;
} }
}; };
#endif #endif // ADC_SAMPLER_SUPPORTED

View File

@@ -1,6 +1,6 @@
/** /**
* @file AdcSampler_esp32.cpp * @file AdcSampler_esp32.cpp
* @brief BSP Layer - ESP32 specific GPIO to ADC channel mapping * @brief BSP Layer - ESP32 specific ADC implementation
* *
* ESP32 ADC1 GPIO mapping: * ESP32 ADC1 GPIO mapping:
* - GPIO32 → ADC1_CH4 * - GPIO32 → ADC1_CH4
@@ -56,4 +56,20 @@ bool AdcSampler::map_gpio_to_channel(int gpio, adc_unit_t& unit, adc_channel_t&
} }
} }
bool AdcSampler::create_calibration(adc_cali_handle_t* handle)
{
// ESP32 uses line fitting calibration (per-unit, not per-channel)
adc_cali_line_fitting_config_t cal_cfg = {
.unit_id = unit_,
.atten = atten_,
.bitwidth = bitwidth_,
};
return adc_cali_create_scheme_line_fitting(&cal_cfg, handle) == ESP_OK;
}
void AdcSampler::delete_calibration(adc_cali_handle_t handle)
{
adc_cali_delete_scheme_line_fitting(handle);
}
#endif // CONFIG_IDF_TARGET_ESP32 #endif // CONFIG_IDF_TARGET_ESP32

View File

@@ -0,0 +1,60 @@
/**
* @file AdcSampler_esp32s2.cpp
* @brief BSP Layer - ESP32-S2 specific ADC implementation
*
* UNTESTED - This implementation is based on ESP32-S2 datasheet.
* Please verify on actual hardware before production use.
*
* ESP32-S2 ADC1 GPIO mapping:
* - GPIO1 → ADC1_CH0
* - GPIO2 → ADC1_CH1
* - GPIO3 → ADC1_CH2
* - GPIO4 → ADC1_CH3
* - GPIO5 → ADC1_CH4
* - GPIO6 → ADC1_CH5
* - GPIO7 → ADC1_CH6
* - GPIO8 → ADC1_CH7
* - GPIO9 → ADC1_CH8
* - GPIO10 → ADC1_CH9
*
* Note: ADC2 is not used to avoid conflicts with Wi-Fi.
* Same as ESP32-S3 implementation.
*/
#include "AdcSampler.hpp"
#if defined(CONFIG_IDF_TARGET_ESP32S2)
bool AdcSampler::map_gpio_to_channel(int gpio, adc_unit_t& unit, adc_channel_t& channel)
{
unit = ADC_UNIT_1; // Only use ADC1 to avoid Wi-Fi conflict
// ESP32-S2: ADC1 on GPIO110 → CH0CH9
if (gpio >= 1 && gpio <= 10)
{
channel = static_cast<adc_channel_t>(gpio - 1);
return true;
}
channel = ADC_CHANNEL_0;
return false;
}
bool AdcSampler::create_calibration(adc_cali_handle_t* handle)
{
// ESP32-S2 uses curve fitting calibration
adc_cali_curve_fitting_config_t cal_cfg = {
.unit_id = unit_,
.chan = channel_,
.atten = atten_,
.bitwidth = bitwidth_,
};
return adc_cali_create_scheme_curve_fitting(&cal_cfg, handle) == ESP_OK;
}
void AdcSampler::delete_calibration(adc_cali_handle_t handle)
{
adc_cali_delete_scheme_curve_fitting(handle);
}
#endif // CONFIG_IDF_TARGET_ESP32S2

View File

@@ -1,6 +1,6 @@
/** /**
* @file AdcSampler_esp32s3.cpp * @file AdcSampler_esp32s3.cpp
* @brief BSP Layer - ESP32-S3 specific GPIO to ADC channel mapping * @brief BSP Layer - ESP32-S3 specific ADC implementation
* *
* ESP32-S3 ADC1 GPIO mapping: * ESP32-S3 ADC1 GPIO mapping:
* - GPIO1 → ADC1_CH0 * - GPIO1 → ADC1_CH0
@@ -36,4 +36,21 @@ bool AdcSampler::map_gpio_to_channel(int gpio, adc_unit_t& unit, adc_channel_t&
return false; return false;
} }
bool AdcSampler::create_calibration(adc_cali_handle_t* handle)
{
// ESP32-S3 uses curve fitting calibration
adc_cali_curve_fitting_config_t cal_cfg = {
.unit_id = unit_,
.chan = channel_,
.atten = atten_,
.bitwidth = bitwidth_,
};
return adc_cali_create_scheme_curve_fitting(&cal_cfg, handle) == ESP_OK;
}
void AdcSampler::delete_calibration(adc_cali_handle_t handle)
{
adc_cali_delete_scheme_curve_fitting(handle);
}
#endif // CONFIG_IDF_TARGET_ESP32S3 #endif // CONFIG_IDF_TARGET_ESP32S3