adc: add an example of using ADC Single Read driver and ADC Calibration driver

This commit is contained in:
Armando 2021-09-07 11:23:28 +08:00 committed by Armando (Dou Yiwen)
parent 9aae92fd16
commit 5d54a34a9b
6 changed files with 178 additions and 0 deletions

View File

@ -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)

View File

@ -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

View File

@ -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
```

View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "single_read.c"
INCLUDE_DIRS ".")

View File

@ -0,0 +1,3 @@
#
# Main Makefile. This is basically the same as a component makefile.
#

View File

@ -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 <stdio.h>
#include <stdlib.h>
#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));
}
}