diff --git a/components/driver/test/CMakeLists.txt b/components/driver/test/CMakeLists.txt index f79ac921c9..734c10b71e 100644 --- a/components/driver/test/CMakeLists.txt +++ b/components/driver/test/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRC_DIRS . param_test touch_sensor_test adc_dma_test dac_dma_test PRIV_INCLUDE_DIRS include param_test/include touch_sensor_test/include - PRIV_REQUIRES unity test_utils driver nvs_flash esp_serial_slave_link infrared_tools) \ No newline at end of file + PRIV_REQUIRES unity test_utils driver nvs_flash esp_serial_slave_link infrared_tools esp_adc_cal) \ No newline at end of file diff --git a/components/driver/test/test_dac.c b/components/driver/test/test_dac.c index 06a25cf868..182886ba43 100644 --- a/components/driver/test/test_dac.c +++ b/components/driver/test/test_dac.c @@ -2,6 +2,7 @@ Tests for the dac device driver */ #include "esp_system.h" + #include "driver/adc.h" #include "driver/dac.h" #include "unity.h" @@ -13,6 +14,8 @@ #include "test_utils.h" #include "driver/i2s.h" +#include "esp_adc_cal.h" + static const char *TAG = "test_dac"; #ifdef CONFIG_IDF_TARGET_ESP32 @@ -119,3 +122,58 @@ TEST_CASE("DAC cw generator output (RTC) check by adc", "[dac]") TEST_ESP_OK( dac_cw_generator_disable() ); TEST_ESP_OK( dac_output_disable( DAC_TEST_CHANNEL_NUM ) ); } + +#if CONFIG_IDF_TARGET_ESP32S2 +static int helper_calc_dac_output(int mV) +{ + return mV * 0.07722; +} +static bool subtest_adc_dac(int mV_ref, esp_adc_cal_characteristics_t * chars) +{ + dac_output_voltage(DAC_TEST_CHANNEL_NUM, helper_calc_dac_output(mV_ref)); + vTaskDelay(pdMS_TO_TICKS(80)); + int raw; + adc2_get_raw((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_WIDTH_BIT_13, &raw); + uint32_t voltage = esp_adc_cal_raw_to_voltage(raw, chars); + TEST_ASSERT_INT_WITHIN( 120, mV_ref, voltage ); // 120 mV error allowance, because both DAC and ADC have error + return true; +} + +TEST_CASE("esp32s2 adc2-dac with adc2 calibration", "[adc-dac]") +{ + gpio_num_t adc_gpio_num, dac_gpio_num; + TEST_ESP_OK( adc2_pad_get_io_num( ADC_TEST_CHANNEL_NUM, &adc_gpio_num ) ); + TEST_ESP_OK( dac_pad_get_io_num( DAC_TEST_CHANNEL_NUM, &dac_gpio_num ) ); + printf("Please connect ADC2 CH%d-GPIO%d <--> DAC CH%d-GPIO%d.\n", ADC_TEST_CHANNEL_NUM, adc_gpio_num, + DAC_TEST_CHANNEL_NUM + 1, dac_gpio_num ); + TEST_ESP_OK( dac_output_enable( DAC_TEST_CHANNEL_NUM ) ); + + esp_adc_cal_characteristics_t chars; + + printf("Test 0dB atten...\n"); + adc2_config_channel_atten((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_ATTEN_DB_0); + esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_0, ADC_WIDTH_BIT_13, 0, &chars); + printf("a %d, b %d\n", chars.coeff_a, chars.coeff_b); + subtest_adc_dac(750, &chars); + + printf("Test 2.5dB atten...\n"); + adc2_config_channel_atten((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_ATTEN_DB_2_5); + esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_2_5, ADC_WIDTH_BIT_13, 0, &chars); + printf("a %d, b %d\n", chars.coeff_a, chars.coeff_b); + subtest_adc_dac(1100, &chars); + + printf("Test 6dB atten...\n"); + adc2_config_channel_atten((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_ATTEN_DB_6); + esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_13, 0, &chars); + printf("a %d, b %d\n", chars.coeff_a, chars.coeff_b); + subtest_adc_dac(800, &chars); + subtest_adc_dac(1250, &chars); + + printf("Test 11dB atten...\n"); + adc2_config_channel_atten((adc2_channel_t)ADC_TEST_CHANNEL_NUM, ADC_ATTEN_DB_11); + esp_adc_cal_characterize(ADC_UNIT_2, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_13, 0, &chars); + printf("a %d, b %d\n", chars.coeff_a, chars.coeff_b); + subtest_adc_dac(1500, &chars); + subtest_adc_dac(2500, &chars); +} +#endif diff --git a/components/esp_adc_cal/CMakeLists.txt b/components/esp_adc_cal/CMakeLists.txt index d823c3b631..146f7af978 100644 --- a/components/esp_adc_cal/CMakeLists.txt +++ b/components/esp_adc_cal/CMakeLists.txt @@ -1,9 +1,15 @@ idf_build_get_property(target IDF_TARGET) -# ToDo: re-enable adc-cal for other target -if(NOT ${target} STREQUAL "esp32") - return() + +if(${target} STREQUAL "esp32") + idf_component_register(SRCS "esp_adc_cal_esp32.c" + INCLUDE_DIRS "include" + REQUIRES driver efuse) + +elseif(${target} STREQUAL "esp32s2") + idf_component_register(SRCS "esp_adc_cal_esp32s2.c" + INCLUDE_DIRS "include" + REQUIRES driver efuse) + endif() -idf_component_register(SRCS "esp_adc_cal.c" - INCLUDE_DIRS "include" - REQUIRES driver) + diff --git a/components/esp_adc_cal/Kconfig b/components/esp_adc_cal/Kconfig index 6c794be0fc..800cb6698b 100644 --- a/components/esp_adc_cal/Kconfig +++ b/components/esp_adc_cal/Kconfig @@ -1,6 +1,7 @@ menu "ADC-Calibration" config ADC_CAL_EFUSE_TP_ENABLE + depends on IDF_TARGET_ESP32 bool "Use Two Point Values" default "y" help @@ -9,6 +10,7 @@ menu "ADC-Calibration" ADC-Voltage curve using Two Point values if they are available. config ADC_CAL_EFUSE_VREF_ENABLE + depends on IDF_TARGET_ESP32 bool "Use eFuse Vref" default "y" help @@ -17,6 +19,7 @@ menu "ADC-Calibration" eFuse Vref if it is available. config ADC_CAL_LUT_ENABLE + depends on IDF_TARGET_ESP32 bool "Use Lookup Tables" default "y" help @@ -24,4 +27,5 @@ menu "ADC-Calibration" to correct for non-linear behavior in 11db attenuation. Other attenuations do not exhibit non-linear behavior hence will not be affected by this option. + endmenu # ADC-Calibration diff --git a/components/esp_adc_cal/component.mk b/components/esp_adc_cal/component.mk index dbaccb6c16..5f8b8731e5 100644 --- a/components/esp_adc_cal/component.mk +++ b/components/esp_adc_cal/component.mk @@ -2,4 +2,6 @@ # Component Makefile # -COMPONENT_ADD_INCLUDEDIRS := include \ No newline at end of file +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o + diff --git a/components/esp_adc_cal/esp_adc_cal.c b/components/esp_adc_cal/esp_adc_cal_esp32.c similarity index 100% rename from components/esp_adc_cal/esp_adc_cal.c rename to components/esp_adc_cal/esp_adc_cal_esp32.c diff --git a/components/esp_adc_cal/esp_adc_cal_esp32s2.c b/components/esp_adc_cal/esp_adc_cal_esp32s2.c new file mode 100644 index 0000000000..4c79a19e0b --- /dev/null +++ b/components/esp_adc_cal/esp_adc_cal_esp32s2.c @@ -0,0 +1,293 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "esp_types.h" +#include "driver/adc.h" +#include "soc/efuse_periph.h" +#include "esp_err.h" +#include "assert.h" +#include "esp_adc_cal.h" +#include "esp_efuse.h" + +#define ADC_CAL_CHECK(cond, ret) ({ \ + if(!(cond)){ \ + return ret; \ + } \ +}) +/* ------------------------ Characterization Constants ---------------------- */ +#define ADC_CHAR_VERSION1_EFUSEVAL 1 + +static const uint32_t adc1_D_mean_low[] = {2231, 1643, 1290, 701}; +static const uint32_t adc2_D_mean_low[] = {2305, 1693, 1343, 723}; +static const uint32_t adc1_D_mean_high[] = {5775, 5692, 5725, 6209}; +static const uint32_t adc2_D_mean_high[] = {5817, 5703, 5731, 6157}; + +static const int Dlow_data_length = 6; +static const int Dhigh_data_length = 8; + +static const int adc_efuse_block = 2; +static const int adc_calib_ver_block = 2; +static const int adc_calib_ver_word_loc = 4; +static const int adc_calib_ver_offset = 4; +static const int adc_calib_ver_len = 3; + +static const int adc1_atten0_Dlow_word_loc = 6; +static const int adc2_atten0_Dlow_word_loc = 7; +static const int adc1_atten0_Dhigh_word_loc = 4; +static const int adc2_atten0_Dhigh_word_loc = 5; + +static const int adc1_atten0_Dlow_offset = 16; +static const int adc2_atten0_Dlow_offset = 8; +static const int adc1_atten0_Dhigh_offset = 16; +static const int adc2_atten0_Dhigh_offset = 16; +/* ----------------------- EFuse Access Functions --------------------------- */ +/** + * Convenience function that reads a few bits from efuse and assembles them. + * For example, if the contents of the EFuse are: + * Word2: 0x1234 Word3:0x5678 + * Then, setting base=2, offset=24, len=24 will yield 0x456. + * @note does not check for boundaries, make sure parameters are correct + * @param blk EFuse Block + * @param base the starting word + * @param offset the bit offset in the starting word + * @param bit how many consecutive bits to fetch + * @return the assembled number + */ +static uint32_t get_consecutive_bits_from_blk(int blk, uint32_t base, int offset, int len) +{ + + base += offset / 32; + offset %= 32; + if (offset + len <= 32 || base == 7) { + uint32_t result = esp_efuse_read_reg(blk, base); + result <<= (32 - offset - len); + result >>= (32 - len); + return result; + } else { + // need to fetch both bytes. + uint64_t result = ((uint64_t)esp_efuse_read_reg(blk, base + 1) << 32) + esp_efuse_read_reg(blk, base); + result &= ((uint64_t)1 << (offset + len)) - 1; + result >>= offset; + return result; + } +} + +/** + * To save space in EFuse, the calibration values for adc are compressed. + * The compression scheme is: for X bits of ADC Efuse data, + * The actual ADC reading is: BASE_VALUE + 4*ADC_OFFSET + * where ADC_OFFSET = bits X-1:0 in Efuse, the highest bit is the sign bit (0:+, 1:-). + * + * The following functions do this conversion. + * @param efuse_val raw values read from efuse. + * @param adc_num Specifies the channel number. The 2 adc channels each have different calibration values. + * @param attem Specifies the attenuation. Different attenuation level have different calibration values. + */ +static uint32_t efuse_low_val_to_d(uint16_t efuse_val, adc_unit_t adc_num, adc_atten_t atten) +{ + // efuse_val is 5 bits + 6th sign bit. + int32_t rawoffsetval = efuse_val & ((1 << (Dlow_data_length - 1)) - 1); + // if the sign bit is 1, it means it is a negative sign. + int32_t offset = (efuse_val & (1 << (Dlow_data_length - 1))) ? (-rawoffsetval * 4) : (rawoffsetval * 4); + if (adc_num == ADC_UNIT_1) { + return offset + adc1_D_mean_low[atten - ADC_ATTEN_DB_0]; + } else { + return offset + adc2_D_mean_low[atten - ADC_ATTEN_DB_0]; + } +} + +static uint32_t efuse_high_val_to_d (uint16_t efuse_val, adc_unit_t adc_num, adc_atten_t atten) +{ + // efuse_val is 7 bits + 8th sign bit. + int32_t rawoffsetval = efuse_val & ((1 << (Dhigh_data_length - 1)) - 1); + int32_t offset = (efuse_val & (1 << (Dhigh_data_length - 1))) ? (-rawoffsetval * 4) : (rawoffsetval * 4); + if (adc_num == ADC_UNIT_1) { + return offset + adc1_D_mean_high[atten - ADC_ATTEN_DB_0]; + } else { + return offset + adc2_D_mean_high[atten - ADC_ATTEN_DB_0]; + } + +} + +/** + * To save space in EFuse, the calibration values for adc are compressed. + * The compression scheme is: for X bits of ADC Efuse data, + * The actual ADC reading is: BASE_VALUE + 4*ADC_OFFSET + * where ADC_OFFSET = bits X-1:0 in Efuse, the highest bit is the sign bit (0:+, 1:-). + * + * The following functions do the reading. + * @param efuse_val raw values read from efuse. + * @param adc_num Specifies the channel number. The 2 adc channels each have different calibration values. + * @param attem Specifies the attenuation. Different attenuation level have different calibration values. + */ +static uint32_t read_efuse_tp_low(adc_unit_t adc_num, adc_atten_t atten) +{ + // this fcn retrieves and decodes the calibration value stored in efuse. + uint32_t base; + int offset; + // may need to move magic numbers out + if (adc_num == ADC_UNIT_1) { + // the first value is at the 16th bit of the 6th word of the efuse block 2, each value is 6 bits long. + base = adc1_atten0_Dlow_word_loc; + offset = adc1_atten0_Dlow_offset + Dlow_data_length * (atten - ADC_ATTEN_DB_0); + + } else { + // the first value is at the 8th bit of the 7th word of the efuse block 2, each value is 6 bits long. + base = adc2_atten0_Dlow_word_loc; + offset = adc2_atten0_Dlow_offset + Dlow_data_length * (atten - ADC_ATTEN_DB_0); + } + uint32_t read_result = get_consecutive_bits_from_blk(adc_efuse_block, base, offset, Dlow_data_length); + return read_result; +} + +static uint32_t read_efuse_tp_high(adc_unit_t adc_num, adc_atten_t atten) +{ + // this fcn retrieves and decodes the calibration value stored in efuse. + uint32_t base; + int offset; + + if (adc_num == ADC_UNIT_1) { + // the first value is at the 16th bit of the 4th word of the efuse block 2, each value is 8 bits long. + base = adc1_atten0_Dhigh_word_loc; + offset = adc1_atten0_Dhigh_offset + Dhigh_data_length * (atten - ADC_ATTEN_DB_0); + + } else { + // the first value is at the 16th bit of the 5th word of the efuse block 2, each value is 8 bits long. + base = adc2_atten0_Dhigh_word_loc; + offset = adc2_atten0_Dhigh_offset + Dhigh_data_length * (atten - ADC_ATTEN_DB_0); + } + uint32_t read_result = get_consecutive_bits_from_blk(adc_efuse_block, base, offset, Dhigh_data_length); + return read_result; +} + +/* ----------------------- Characterization Functions ----------------------- */ + +// coeff_a and coeff_b are actually floats +// they are scaled to put them into uint32_t so that the headers do not have to be changed +static const int coeff_a_scaling = 65536; +static const int coeff_b_scaling = 1024; + +/** + * The Two Point calibration measures the reading at two specific input voltages, and calculates the (assumed linear) relation + * between input voltage and ADC response. (Response = A * Vinput + B) + * A and B are scaled ints. + * @param high The ADC response at the higher voltage of the corresponding attenuation (600mV, 800mV, 1000mV, 2000mV). + * @param low The ADC response at the lower voltage of the corresponding attenuation (all 250mV). + * + */ +static void characterize_using_two_point(adc_unit_t adc_num, + adc_atten_t atten, + uint32_t high, + uint32_t low, + uint32_t *coeff_a, + uint32_t *coeff_b) +{ + // once we have recovered the reference high(Dhigh) and low(Dlow) readings, we can calculate a and b from + // the measured high and low readings + static const uint32_t v_high[] = {600, 800, 1000, 2000}; + static const uint32_t v_low = 250; + *coeff_a = coeff_a_scaling * (v_high[atten] - v_low) / (high - low); + *coeff_b = coeff_b_scaling * (v_low * high - v_high[atten] * low) / (high - low); +} + + +/* ------------------------- Public API ------------------------------------- */ +esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source) +{ + if (source != ESP_ADC_CAL_VAL_EFUSE_TP) { + return ESP_ERR_NOT_SUPPORTED; + } + uint8_t adc1_atten0_dh = get_consecutive_bits_from_blk(adc_efuse_block, adc1_atten0_Dhigh_word_loc, adc1_atten0_Dhigh_offset, Dhigh_data_length); + uint8_t adc2_atten0_dh = get_consecutive_bits_from_blk(adc_efuse_block, adc2_atten0_Dhigh_word_loc, adc2_atten0_Dhigh_offset, Dhigh_data_length); + if (!adc1_atten0_dh || !adc2_atten0_dh) { + return ESP_ERR_NOT_SUPPORTED; + } + uint8_t adc_encoding_version = get_consecutive_bits_from_blk(adc_calib_ver_block, adc_calib_ver_word_loc, adc_calib_ver_offset, adc_calib_ver_len); + if (adc_encoding_version != 1) { + // current version only accepts encoding ver 1. + return ESP_ERR_INVALID_VERSION; + } + return ESP_OK; +} + +esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num, + adc_atten_t atten, + adc_bits_width_t bit_width, + uint32_t default_vref, + esp_adc_cal_characteristics_t *chars) +{ + // Check parameters + assert((adc_num == ADC_UNIT_1) || (adc_num == ADC_UNIT_2)); + assert(chars != NULL); + assert(bit_width == ADC_WIDTH_BIT_13); + + // Characterize based on efuse Two Point values. If these values are not present in efuse, + // or efuse values are of a version that we do not recognize, automatically assume default values. + uint32_t adc_calib_high, adc_calib_low; + if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) { + adc_calib_high = read_efuse_tp_high(adc_num, atten); + adc_calib_low = read_efuse_tp_low(adc_num, atten); + } else { + adc_calib_high = 0; + adc_calib_low = 0; + } + uint32_t high = efuse_high_val_to_d(adc_calib_high, adc_num, atten); + uint32_t low = efuse_low_val_to_d(adc_calib_low, adc_num, atten); + characterize_using_two_point(adc_num, atten, high, low, &(chars->coeff_a), &(chars->coeff_b)); + // Initialize remaining fields + chars->adc_num = adc_num; + chars->atten = atten; + chars->bit_width = bit_width; + + // these values are not used as the corresponding calibration themes are deprecated. + chars->vref = 0; + chars->low_curve = NULL; + chars->high_curve = NULL; + + // in esp32s2 we only use the two point method to calibrate the adc. + return ESP_ADC_CAL_VAL_EFUSE_TP; +} + +uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars) +{ + ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG); + + return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling; +} + +esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, + const esp_adc_cal_characteristics_t *chars, + uint32_t *voltage) +{ + // Check parameters + ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG); + ADC_CAL_CHECK(voltage != NULL, ESP_ERR_INVALID_ARG); + + int adc_reading; + if (chars->adc_num == ADC_UNIT_1) { + //Check if channel is valid on ADC1 + ADC_CAL_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, ESP_ERR_INVALID_ARG); + adc_reading = adc1_get_raw(channel); + } else { + //Check if channel is valid on ADC2 + ADC_CAL_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, ESP_ERR_INVALID_ARG); + if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) { + return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2 + } + } + *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars); + return ESP_OK; +} + diff --git a/components/esp_adc_cal/include/esp_adc_cal.h b/components/esp_adc_cal/include/esp_adc_cal.h index b1798847bd..7d8f1278bf 100644 --- a/components/esp_adc_cal/include/esp_adc_cal.h +++ b/components/esp_adc_cal/include/esp_adc_cal.h @@ -30,6 +30,7 @@ typedef enum { ESP_ADC_CAL_VAL_EFUSE_VREF = 0, /**< Characterization based on reference voltage stored in eFuse*/ ESP_ADC_CAL_VAL_EFUSE_TP = 1, /**< Characterization based on Two Point values stored in eFuse*/ ESP_ADC_CAL_VAL_DEFAULT_VREF = 2, /**< Characterization based on default reference voltage*/ + ESP_ADC_CAL_VAL_MAX } esp_adc_cal_value_t; /** @@ -71,12 +72,15 @@ esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t value_type); * Characterization can be based on Two Point values, eFuse Vref, or default Vref * and the calibration values will be prioritized in that order. * - * @note Two Point values and eFuse Vref can be enabled/disabled using menuconfig. + * @note + * For ESP32, Two Point values and eFuse Vref calibration can be enabled/disabled using menuconfig. + * For ESP32s2, only Two Point values calibration and only ADC_WIDTH_BIT_13 is supported. The parameter default_vref is unused. + * * * @param[in] adc_num ADC to characterize (ADC_UNIT_1 or ADC_UNIT_2) * @param[in] atten Attenuation to characterize * @param[in] bit_width Bit width configuration of ADC - * @param[in] default_vref Default ADC reference voltage in mV (used if eFuse values is not available) + * @param[in] default_vref Default ADC reference voltage in mV (Only in ESP32, used if eFuse values is not available) * @param[out] chars Pointer to empty structure used to store ADC characteristics * * @return diff --git a/examples/peripherals/adc/main/adc1_example_main.c b/examples/peripherals/adc/main/adc1_example_main.c index 85baf3a501..704032ea4d 100644 --- a/examples/peripherals/adc/main/adc1_example_main.c +++ b/examples/peripherals/adc/main/adc1_example_main.c @@ -12,15 +12,13 @@ #include "freertos/task.h" #include "driver/gpio.h" #include "driver/adc.h" -#if CONFIG_IDF_TARGET_ESP32 #include "esp_adc_cal.h" -#endif #define DEFAULT_VREF 1100 //Use adc2_vref_to_gpio() to obtain a better estimate #define NO_OF_SAMPLES 64 //Multisampling -#if CONFIG_IDF_TARGET_ESP32 static esp_adc_cal_characteristics_t *adc_chars; +#if CONFIG_IDF_TARGET_ESP32 static const adc_channel_t channel = ADC_CHANNEL_6; //GPIO34 if ADC1, GPIO14 if ADC2 static const adc_bits_width_t width = ADC_WIDTH_BIT_12; #elif CONFIG_IDF_TARGET_ESP32S2 @@ -30,24 +28,34 @@ static const adc_bits_width_t width = ADC_WIDTH_BIT_13; static const adc_atten_t atten = ADC_ATTEN_DB_0; static const adc_unit_t unit = ADC_UNIT_1; -#if CONFIG_IDF_TARGET_ESP32 + static void check_efuse(void) { - //Check TP is burned into eFuse +#if CONFIG_IDF_TARGET_ESP32 + //Check if TP is burned into eFuse if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) { printf("eFuse Two Point: Supported\n"); } else { printf("eFuse Two Point: NOT supported\n"); } - //Check Vref is burned into eFuse if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) { printf("eFuse Vref: Supported\n"); } else { printf("eFuse Vref: NOT supported\n"); } +#elif CONFIG_IDF_TARGET_ESP32S2 + if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) { + printf("eFuse Two Point: Supported\n"); + } else { + printf("Cannot retrieve eFuse Two Point calibration values. Default calibration values will be used.\n"); + } +#else +#error "This example is configured for ESP32/ESP32S2." +#endif } + static void print_char_val_type(esp_adc_cal_value_t val_type) { if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) { @@ -58,14 +66,12 @@ static void print_char_val_type(esp_adc_cal_value_t val_type) printf("Characterized using Default Vref\n"); } } -#endif + void app_main(void) { -#if CONFIG_IDF_TARGET_ESP32 //Check if Two Point or Vref are burned into eFuse check_efuse(); -#endif //Configure ADC if (unit == ADC_UNIT_1) { @@ -75,12 +81,10 @@ void app_main(void) adc2_config_channel_atten((adc2_channel_t)channel, atten); } -#if CONFIG_IDF_TARGET_ESP32 //Characterize ADC adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t)); esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars); print_char_val_type(val_type); -#endif //Continuously sample ADC1 while (1) { @@ -96,13 +100,9 @@ void app_main(void) } } adc_reading /= NO_OF_SAMPLES; -#if CONFIG_IDF_TARGET_ESP32 //Convert adc_reading to voltage in mV uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars); printf("Raw: %d\tVoltage: %dmV\n", adc_reading, voltage); -#elif CONFIG_IDF_TARGET_ESP32S2 - printf("ADC%d CH%d Raw: %d\t\n", unit, channel, adc_reading); -#endif vTaskDelay(pdMS_TO_TICKS(1000)); } } diff --git a/examples/peripherals/adc2/main/adc2_example_main.c b/examples/peripherals/adc2/main/adc2_example_main.c index ec35cce862..558e393ecf 100644 --- a/examples/peripherals/adc2/main/adc2_example_main.c +++ b/examples/peripherals/adc2/main/adc2_example_main.c @@ -45,7 +45,7 @@ void app_main(void) //be sure to do the init before using adc2. printf("adc2_init...\n"); - adc2_config_channel_atten( ADC2_EXAMPLE_CHANNEL, ADC_ATTEN_0db ); + adc2_config_channel_atten( ADC2_EXAMPLE_CHANNEL, ADC_ATTEN_11db ); vTaskDelay(2 * portTICK_PERIOD_MS);