From 5d54a34a9b9937f49613ba61e82c8b491eb0847c Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 7 Sep 2021 11:23:28 +0800 Subject: [PATCH] adc: add an example of using ADC Single Read driver and ADC Calibration driver --- .../single_read/single_read/CMakeLists.txt | 6 + .../adc/single_read/single_read/Makefile | 8 ++ .../adc/single_read/single_read/README.md | 55 +++++++++ .../single_read/main/CMakeLists.txt | 2 + .../single_read/single_read/main/component.mk | 3 + .../single_read/main/single_read.c | 104 ++++++++++++++++++ 6 files changed, 178 insertions(+) create mode 100644 examples/peripherals/adc/single_read/single_read/CMakeLists.txt create mode 100644 examples/peripherals/adc/single_read/single_read/Makefile create mode 100644 examples/peripherals/adc/single_read/single_read/README.md create mode 100644 examples/peripherals/adc/single_read/single_read/main/CMakeLists.txt create mode 100644 examples/peripherals/adc/single_read/single_read/main/component.mk create mode 100644 examples/peripherals/adc/single_read/single_read/main/single_read.c diff --git a/examples/peripherals/adc/single_read/single_read/CMakeLists.txt b/examples/peripherals/adc/single_read/single_read/CMakeLists.txt new file mode 100644 index 0000000000..e4103e9bff --- /dev/null +++ b/examples/peripherals/adc/single_read/single_read/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(single_read) diff --git a/examples/peripherals/adc/single_read/single_read/Makefile b/examples/peripherals/adc/single_read/single_read/Makefile new file mode 100644 index 0000000000..af71b9c915 --- /dev/null +++ b/examples/peripherals/adc/single_read/single_read/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := single_read + +include $(IDF_PATH)/make/project.mk diff --git a/examples/peripherals/adc/single_read/single_read/README.md b/examples/peripherals/adc/single_read/single_read/README.md new file mode 100644 index 0000000000..ba9650c15d --- /dev/null +++ b/examples/peripherals/adc/single_read/single_read/README.md @@ -0,0 +1,55 @@ +# ADC Single Read Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +This example demonstrates the following: + +- How to obtain a single ADC reading from a GPIO pin using the ADC Driver's Single Read function +- How to use the ADC Calibration functions to obtain a calibrated result (in mV) + +## How to use example + +### Hardware Required + +* A development board with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) +* A USB cable for power supply and programming + +In this example, you need to connect a voltage source (e.g. a DC power supply) to the GPIO pins specified in `single_read.c` (see the macros defined on the top of the source file). Feel free to modify the pin setting. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +Running this example, you will see the following log output on the serial monitor: + +``` +I (302) ADC1_CH2: raw data: 4095 +I (302) ADC1_CH2: cali data: 3109 mV +I (1302) ADC2_CH0: raw data: 0 +I (1302) ADC2_CH0: cali data: 0 mV +I (2302) ADC1_CH2: raw data: 4095 +I (2302) ADC1_CH2: cali data: 3109 mV +I (3302) ADC2_CH0: raw data: 0 +I (3302) ADC2_CH0: cali data: 0 mV +I (4302) ADC1_CH2: raw data: 4095 +I (4302) ADC1_CH2: cali data: 3109 mV +... +``` + +## Troubleshooting + +If following warning is printed out, it means the calibration required eFuse bits are not burnt correctly on your board. The calibration will be skipped. Only raw data will be printed out. +``` +W (300) ADC SINGLE: eFuse not burnt, skip calibration +I (1310) ADC2_CH0: raw data: 2715 +``` \ No newline at end of file diff --git a/examples/peripherals/adc/single_read/single_read/main/CMakeLists.txt b/examples/peripherals/adc/single_read/single_read/main/CMakeLists.txt new file mode 100644 index 0000000000..995f58e522 --- /dev/null +++ b/examples/peripherals/adc/single_read/single_read/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "single_read.c" + INCLUDE_DIRS ".") diff --git a/examples/peripherals/adc/single_read/single_read/main/component.mk b/examples/peripherals/adc/single_read/single_read/main/component.mk new file mode 100644 index 0000000000..44bd2b5273 --- /dev/null +++ b/examples/peripherals/adc/single_read/single_read/main/component.mk @@ -0,0 +1,3 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# diff --git a/examples/peripherals/adc/single_read/single_read/main/single_read.c b/examples/peripherals/adc/single_read/single_read/main/single_read.c new file mode 100644 index 0000000000..7f8e97abf5 --- /dev/null +++ b/examples/peripherals/adc/single_read/single_read/main/single_read.c @@ -0,0 +1,104 @@ +/* ADC1 Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/adc_common.h" +#include "esp_adc_cal.h" + + +//ADC Channels +#if CONFIG_IDF_TARGET_ESP32 +#define ADC1_EXAMPLE_CHAN0 ADC1_CHANNEL_6 +#define ADC2_EXAMPLE_CHAN0 ADC2_CHANNEL_0 +static const char *TAG_CH[2][10] = {{"ADC1_CH6"}, {"ADC2_CH0"}}; +#else +#define ADC1_EXAMPLE_CHAN0 ADC1_CHANNEL_2 +#define ADC2_EXAMPLE_CHAN0 ADC2_CHANNEL_0 +static const char *TAG_CH[2][10] = {{"ADC1_CH2"}, {"ADC2_CH0"}}; +#endif + +//ADC Attenuation +#define ADC_EXAMPLE_ATTEN ADC_ATTEN_DB_11 + +//ADC Calibration +#if CONFIG_IDF_TARGET_ESP32 +#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_VREF +#elif CONFIG_IDF_TARGET_ESP32S2 +#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP +#elif CONFIG_IDF_TARGET_ESP32C3 +#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP +#elif CONFIG_IDF_TARGET_ESP32S3 +#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP_FIT +#endif + + +static int adc_raw[2][10]; +static const char *TAG = "ADC SINGLE"; + +static esp_adc_cal_characteristics_t adc1_chars; +static esp_adc_cal_characteristics_t adc2_chars; + +static bool adc_calibration_init(void) +{ + esp_err_t ret; + bool cali_enable = false; + + ret = esp_adc_cal_check_efuse(ADC_EXAMPLE_CALI_SCHEME); + if (ret == ESP_ERR_NOT_SUPPORTED) { + ESP_LOGW(TAG, "Calibration scheme not supported, skip calibration"); + } else if (ret == ESP_ERR_INVALID_VERSION) { + ESP_LOGW(TAG, "eFuse not burnt, skip calibration"); + } else if (ret == ESP_OK) { + cali_enable = true; + esp_adc_cal_characterize(ADC_UNIT_1, ADC_EXAMPLE_ATTEN, ADC_WIDTH_BIT_DEFAULT, 0, &adc1_chars); + esp_adc_cal_characterize(ADC_UNIT_2, ADC_EXAMPLE_ATTEN, ADC_WIDTH_BIT_DEFAULT, 0, &adc2_chars); + } else { + ESP_LOGE(TAG, "Invalid arg"); + } + + return cali_enable; +} + +void app_main(void) +{ + esp_err_t ret = ESP_OK; + uint32_t voltage = 0; + bool cali_enable = adc_calibration_init(); + + //ADC1 config + ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_DEFAULT)); + ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_EXAMPLE_CHAN0, ADC_EXAMPLE_ATTEN)); + //ADC2 config + ESP_ERROR_CHECK(adc2_config_channel_atten(ADC2_EXAMPLE_CHAN0, ADC_EXAMPLE_ATTEN)); + + while (1) { + adc_raw[0][0] = adc1_get_raw(ADC1_EXAMPLE_CHAN0); + ESP_LOGI(TAG_CH[0][0], "raw data: %d", adc_raw[0][0]); + if (cali_enable) { + voltage = esp_adc_cal_raw_to_voltage(adc_raw[0][0], &adc1_chars); + ESP_LOGI(TAG_CH[0][0], "cali data: %d mV", voltage); + } + vTaskDelay(pdMS_TO_TICKS(1000)); + + do { + ret = adc2_get_raw(ADC2_EXAMPLE_CHAN0, ADC_WIDTH_BIT_DEFAULT, &adc_raw[1][0]); + } while (ret == ESP_ERR_INVALID_STATE); + ESP_ERROR_CHECK(ret); + + ESP_LOGI(TAG_CH[1][0], "raw data: %d", adc_raw[1][0]); + if (cali_enable) { + voltage = esp_adc_cal_raw_to_voltage(adc_raw[1][0], &adc2_chars); + ESP_LOGI(TAG_CH[1][0], "cali data: %d mV", voltage); + } + vTaskDelay(pdMS_TO_TICKS(1000)); + } +}