Merge branch 'feature/adc_driver_ng' into 'master'

ADC Driver NG

Closes IDF-4560, IDF-3908, IDF-4225, IDF-2482, IDF-4111, IDF-3610, IDF-4058, IDF-3801, IDF-3636, IDF-2537, IDF-4310, IDF-5150, IDF-5151, and IDF-4979

See merge request espressif/esp-idf!17960
This commit is contained in:
Armando (Dou Yiwen)
2022-07-19 21:28:31 +08:00
185 changed files with 7783 additions and 6462 deletions

View File

@@ -1,28 +1,10 @@
# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps
examples/peripherals/adc/dma_read:
examples/peripherals/adc/continuous_read:
disable:
- if: IDF_TARGET == "esp32c2"
temporary: true
reason: target esp32c2 is not supported yet
examples/peripherals/adc/single_read/adc:
enable:
- if: IDF_TARGET == "esp32"
temporary: true
reason: the other targets are not tested yet
examples/peripherals/adc/single_read/adc2:
enable:
- if: IDF_TARGET == "esp32"
temporary: true
reason: the other targets are not tested yet
examples/peripherals/adc/single_read/single_read:
disable:
- if: IDF_TARGET == "esp32c2"
temporary: true
reason: target esp32c2 is not supported yet
reason: adc dma mode isn't supported on these targets
examples/peripherals/gpio/generic_gpio:
disable_test:

View File

@@ -3,4 +3,4 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(adc)
project(continuous_read)

View File

@@ -48,7 +48,7 @@ I (368) ADC DMA: adc_pattern[1].unit is :0
I (368) ADC DMA: adc_pattern[2].atten is :0
I (378) ADC DMA: adc_pattern[2].channel is :0
I (378) ADC DMA: adc_pattern[2].unit is :1
I (388) TASK:: ret is 0, ret_num is 256
I (388) TASK: ret is 0, ret_num is 256
I (388) ADC DMA: Unit: 1,_Channel: 2, Value: bec
I (398) ADC DMA: Unit: 2,_Channel: 0, Value: 9cb
I (398) ADC DMA: Unit: 1,_Channel: 3, Value: acb

View File

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

View File

@@ -0,0 +1,173 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdio.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_adc/adc_continuous.h"
#define EXAMPLE_READ_LEN 256
#define GET_UNIT(x) ((x>>3) & 0x1)
#if CONFIG_IDF_TARGET_ESP32
#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 //ESP32 only supports ADC1 DMA mode
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1
#elif CONFIG_IDF_TARGET_ESP32S2
#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
#define ADC_CONV_MODE ADC_CONV_ALTER_UNIT //ESP32C3 only supports alter mode
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
#elif CONFIG_IDF_TARGET_ESP32S3
#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
#endif
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
static adc_channel_t channel[3] = {ADC_CHANNEL_2, ADC_CHANNEL_3, (ADC_CHANNEL_0 | 1 << 3)};
#endif
#if CONFIG_IDF_TARGET_ESP32S2
static adc_channel_t channel[3] = {ADC_CHANNEL_2, ADC_CHANNEL_3, (ADC_CHANNEL_0 | 1 << 3)};
#endif
#if CONFIG_IDF_TARGET_ESP32
static adc_channel_t channel[1] = {ADC_CHANNEL_7};
#endif
static TaskHandle_t s_task_handle;
static const char *TAG = "EXAMPLE";
static bool IRAM_ATTR s_conv_done_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data)
{
BaseType_t mustYield = pdFALSE;
//Notify that ADC continuous driver has done enough number of conversions
vTaskNotifyGiveFromISR(s_task_handle, &mustYield);
return (mustYield == pdTRUE);
}
static void continuous_adc_init(adc_channel_t *channel, uint8_t channel_num, adc_continuous_handle_t *out_handle)
{
adc_continuous_handle_t handle = NULL;
adc_continuous_handle_cfg_t adc_config = {
.max_store_buf_size = 1024,
.conv_frame_size = EXAMPLE_READ_LEN,
};
ESP_ERROR_CHECK(adc_continuous_new_handle(&adc_config, &handle));
adc_continuous_config_t dig_cfg = {
.sample_freq_hz = 20 * 1000,
.conv_mode = ADC_CONV_MODE,
.format = ADC_OUTPUT_TYPE,
};
adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
dig_cfg.pattern_num = channel_num;
for (int i = 0; i < channel_num; i++) {
uint8_t unit = GET_UNIT(channel[i]);
uint8_t ch = channel[i] & 0x7;
adc_pattern[i].atten = ADC_ATTEN_DB_0;
adc_pattern[i].channel = ch;
adc_pattern[i].unit = unit;
adc_pattern[i].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;
ESP_LOGI(TAG, "adc_pattern[%d].atten is :%x", i, adc_pattern[i].atten);
ESP_LOGI(TAG, "adc_pattern[%d].channel is :%x", i, adc_pattern[i].channel);
ESP_LOGI(TAG, "adc_pattern[%d].unit is :%x", i, adc_pattern[i].unit);
}
dig_cfg.adc_pattern = adc_pattern;
ESP_ERROR_CHECK(adc_continuous_config(handle, &dig_cfg));
*out_handle = handle;
}
#if !CONFIG_IDF_TARGET_ESP32
static bool check_valid_data(const adc_digi_output_data_t *data)
{
const unsigned int unit = data->type2.unit;
if (unit > 2) return false;
if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) return false;
return true;
}
#endif
void app_main(void)
{
esp_err_t ret;
uint32_t ret_num = 0;
uint8_t result[EXAMPLE_READ_LEN] = {0};
memset(result, 0xcc, EXAMPLE_READ_LEN);
s_task_handle = xTaskGetCurrentTaskHandle();
adc_continuous_handle_t handle = NULL;
continuous_adc_init(channel, sizeof(channel) / sizeof(adc_channel_t), &handle);
adc_continuous_evt_cbs_t cbs = {
.on_conv_done = s_conv_done_cb,
};
ESP_ERROR_CHECK(adc_continuous_register_event_callbacks(handle, &cbs, NULL));
ESP_ERROR_CHECK(adc_continuous_start(handle));
while(1) {
/**
* This is to show you the way to use the ADC continuous mode driver event callback.
* This `ulTaskNotifyTake` will block when the data processing in the task is fast.
* However in this example, the data processing (print) is slow, so you barely block here.
*
* Without using this event callback (to notify this task), you can still just call
* `adc_continuous_read()` here in a loop, with/without a certain block timeout.
*/
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
while (1) {
ret = adc_continuous_read(handle, result, EXAMPLE_READ_LEN, &ret_num, 0);
if (ret == ESP_OK) {
ESP_LOGI("TASK", "ret is %x, ret_num is %d", ret, ret_num);
for (int i = 0; i < ret_num; i += SOC_ADC_DIGI_RESULT_BYTES) {
adc_digi_output_data_t *p = (void*)&result[i];
#if CONFIG_IDF_TARGET_ESP32
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data);
#else
if (ADC_CONV_MODE == ADC_CONV_BOTH_UNIT || ADC_CONV_MODE == ADC_CONV_ALTER_UNIT) {
if (check_valid_data(p)) {
ESP_LOGI(TAG, "Unit: %d,_Channel: %d, Value: %x", p->type2.unit+1, p->type2.channel, p->type2.data);
} else {
ESP_LOGI(TAG, "Invalid data [%d_%d_%x]", p->type2.unit+1, p->type2.channel, p->type2.data);
}
}
#if CONFIG_IDF_TARGET_ESP32S2
else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_2) {
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 2, p->type1.channel, p->type1.data);
} else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_1) {
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data);
}
#endif //#if CONFIG_IDF_TARGET_ESP32S2
#endif
}
/**
* Because printing is slow, so every time you call `ulTaskNotifyTake`, it will immediately return.
* To avoid a task watchdog timeout, add a delay here. When you replace the way you process the data,
* usually you don't need this delay (as this task will block for a while).
*/
vTaskDelay(1);
} else if (ret == ESP_ERR_TIMEOUT) {
//We try to read `EXAMPLE_READ_LEN` until API returns timeout, which means there's no available data
break;
}
}
}
ESP_ERROR_CHECK(adc_continuous_stop(handle));
ESP_ERROR_CHECK(adc_continuous_deinit(handle));
}

View File

@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded.dut import Dut
@pytest.mark.esp32
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32c3
def test_adc_continuous(dut: Dut) -> None:
res = dut.expect(r'TASK: ret is 0, ret_num is (\d+)')
num = res.group(1).decode('utf8')
assert int(num) == 256

View File

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

View File

@@ -1,176 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdio.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/adc.h"
#define TIMES 256
#define GET_UNIT(x) ((x>>3) & 0x1)
#if CONFIG_IDF_TARGET_ESP32
#define ADC_RESULT_BYTE 2
#define ADC_CONV_LIMIT_EN 1 //For ESP32, this should always be set to 1
#define ADC_CONV_MODE ADC_CONV_SINGLE_UNIT_1 //ESP32 only supports ADC1 DMA mode
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE1
#elif CONFIG_IDF_TARGET_ESP32S2
#define ADC_RESULT_BYTE 2
#define ADC_CONV_LIMIT_EN 0
#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
#define ADC_RESULT_BYTE 4
#define ADC_CONV_LIMIT_EN 0
#define ADC_CONV_MODE ADC_CONV_ALTER_UNIT //ESP32C3 only supports alter mode
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
#elif CONFIG_IDF_TARGET_ESP32S3
#define ADC_RESULT_BYTE 4
#define ADC_CONV_LIMIT_EN 0
#define ADC_CONV_MODE ADC_CONV_BOTH_UNIT
#define ADC_OUTPUT_TYPE ADC_DIGI_OUTPUT_FORMAT_TYPE2
#endif
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
static uint16_t adc1_chan_mask = BIT(2) | BIT(3);
static uint16_t adc2_chan_mask = BIT(0);
static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)};
#endif
#if CONFIG_IDF_TARGET_ESP32S2
static uint16_t adc1_chan_mask = BIT(2) | BIT(3);
static uint16_t adc2_chan_mask = BIT(0);
static adc_channel_t channel[3] = {ADC1_CHANNEL_2, ADC1_CHANNEL_3, (ADC2_CHANNEL_0 | 1 << 3)};
#endif
#if CONFIG_IDF_TARGET_ESP32
static uint16_t adc1_chan_mask = BIT(7);
static uint16_t adc2_chan_mask = 0;
static adc_channel_t channel[1] = {ADC1_CHANNEL_7};
#endif
static const char *TAG = "ADC DMA";
static void continuous_adc_init(uint16_t adc1_chan_mask, uint16_t adc2_chan_mask, adc_channel_t *channel, uint8_t channel_num)
{
adc_digi_init_config_t adc_dma_config = {
.max_store_buf_size = 1024,
.conv_num_each_intr = TIMES,
.adc1_chan_mask = adc1_chan_mask,
.adc2_chan_mask = adc2_chan_mask,
};
ESP_ERROR_CHECK(adc_digi_initialize(&adc_dma_config));
adc_digi_configuration_t dig_cfg = {
.conv_limit_en = ADC_CONV_LIMIT_EN,
.conv_limit_num = 250,
.sample_freq_hz = 10 * 1000,
.conv_mode = ADC_CONV_MODE,
.format = ADC_OUTPUT_TYPE,
};
adc_digi_pattern_config_t adc_pattern[SOC_ADC_PATT_LEN_MAX] = {0};
dig_cfg.pattern_num = channel_num;
for (int i = 0; i < channel_num; i++) {
uint8_t unit = GET_UNIT(channel[i]);
uint8_t ch = channel[i] & 0x7;
adc_pattern[i].atten = ADC_ATTEN_DB_0;
adc_pattern[i].channel = ch;
adc_pattern[i].unit = unit;
adc_pattern[i].bit_width = SOC_ADC_DIGI_MAX_BITWIDTH;
ESP_LOGI(TAG, "adc_pattern[%d].atten is :%x", i, adc_pattern[i].atten);
ESP_LOGI(TAG, "adc_pattern[%d].channel is :%x", i, adc_pattern[i].channel);
ESP_LOGI(TAG, "adc_pattern[%d].unit is :%x", i, adc_pattern[i].unit);
}
dig_cfg.adc_pattern = adc_pattern;
ESP_ERROR_CHECK(adc_digi_controller_configure(&dig_cfg));
}
#if !CONFIG_IDF_TARGET_ESP32
static bool check_valid_data(const adc_digi_output_data_t *data)
{
const unsigned int unit = data->type2.unit;
if (unit > 2) return false;
if (data->type2.channel >= SOC_ADC_CHANNEL_NUM(unit)) return false;
return true;
}
#endif
void app_main(void)
{
esp_err_t ret;
uint32_t ret_num = 0;
uint8_t result[TIMES] = {0};
memset(result, 0xcc, TIMES);
continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t));
adc_digi_start();
while(1) {
ret = adc_digi_read_bytes(result, TIMES, &ret_num, ADC_MAX_DELAY);
if (ret == ESP_OK || ret == ESP_ERR_INVALID_STATE) {
if (ret == ESP_ERR_INVALID_STATE) {
/**
* @note 1
* Issue:
* As an example, we simply print the result out, which is super slow. Therefore the conversion is too
* fast for the task to handle. In this condition, some conversion results lost.
*
* Reason:
* When this error occurs, you will usually see the task watchdog timeout issue also.
* Because the conversion is too fast, whereas the task calling `adc_digi_read_bytes` is slow.
* So `adc_digi_read_bytes` will hardly block. Therefore Idle Task hardly has chance to run. In this
* example, we add a `vTaskDelay(1)` below, to prevent the task watchdog timeout.
*
* Solution:
* Either decrease the conversion speed, or increase the frequency you call `adc_digi_read_bytes`
*/
}
ESP_LOGI("TASK:", "ret is %x, ret_num is %d", ret, ret_num);
for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) {
adc_digi_output_data_t *p = (void*)&result[i];
#if CONFIG_IDF_TARGET_ESP32
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data);
#else
if (ADC_CONV_MODE == ADC_CONV_BOTH_UNIT || ADC_CONV_MODE == ADC_CONV_ALTER_UNIT) {
if (check_valid_data(p)) {
ESP_LOGI(TAG, "Unit: %d,_Channel: %d, Value: %x", p->type2.unit+1, p->type2.channel, p->type2.data);
} else {
// abort();
ESP_LOGI(TAG, "Invalid data [%d_%d_%x]", p->type2.unit+1, p->type2.channel, p->type2.data);
}
}
#if CONFIG_IDF_TARGET_ESP32S2
else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_2) {
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 2, p->type1.channel, p->type1.data);
} else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_1) {
ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data);
}
#endif //#if CONFIG_IDF_TARGET_ESP32S2
#endif
}
//See `note 1`
vTaskDelay(1);
} else if (ret == ESP_ERR_TIMEOUT) {
/**
* ``ESP_ERR_TIMEOUT``: If ADC conversion is not finished until Timeout, you'll get this return error.
* Here we set Timeout ``portMAX_DELAY``, so you'll never reach this branch.
*/
ESP_LOGW(TAG, "No data, increase timeout or reduce conv_num_each_intr");
vTaskDelay(1000);
}
}
adc_digi_stop();
ret = adc_digi_deinitialize();
assert(ret == ESP_OK);
}

View File

@@ -3,4 +3,4 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(adc)
project(oneshot_read)

View File

@@ -0,0 +1,62 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- |
# 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 oneshot ADC reading from a GPIO pin using the ADC oneshot mode driver
- How to use the ADC Calibration functions to obtain a calibrated result (in mV)
## How to use example
### Hardware Required
* A development board with ESP SoC
* 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 `oneshot_read_main.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 (304) ADC_ONESHOT: calibration scheme version is Curve Fitting
I (304) ADC_ONESHOT: calibration scheme version is Curve Fitting
I (314) ADC_ONESHOT: ADC1 Channel[2] Raw Data: 0
I (314) ADC_ONESHOT: ADC1 Channel[2] Cali Voltage: 0 mV
I (1324) ADC_ONESHOT: ADC1 Channel[3] Raw Data: 664
I (1324) ADC_ONESHOT: ADC1 Channel[3] Cali Voltage: 559 mV
I (2324) ADC_ONESHOT: ADC2 Channel[0] Raw Data: 580
I (2324) ADC_ONESHOT: ADC2 Channel[0] Cali Voltage: 498 mV
I (3324) ADC_ONESHOT: ADC1 Channel[2] Raw Data: 0
I (3324) ADC_ONESHOT: ADC1 Channel[2] Cali Voltage: 0 mV
I (4324) ADC_ONESHOT: ADC1 Channel[3] Raw Data: 666
I (4324) ADC_ONESHOT: ADC1 Channel[3] Cali Voltage: 561 mV
I (5324) ADC_ONESHOT: ADC2 Channel[0] Raw Data: 575
I (5324) ADC_ONESHOT: ADC2 Channel[0] Cali Voltage: 495 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_ONESHOT: eFuse not burnt, skip calibration
I (1310) ADC_ONESHOT: ADC1 Channel[2] Raw Data: 0
```

View File

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

View File

@@ -0,0 +1,189 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "esp_log.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
const static char *TAG = "EXAMPLE";
/*---------------------------------------------------------------
ADC General Macros
---------------------------------------------------------------*/
//ADC1 Channels
#if CONFIG_IDF_TARGET_ESP32
#define EXAMPLE_ADC1_CHAN0 ADC_CHANNEL_4
#define EXAMPLE_ADC1_CHAN1 ADC_CHANNEL_5
#else
#define EXAMPLE_ADC1_CHAN0 ADC_CHANNEL_2
#define EXAMPLE_ADC1_CHAN1 ADC_CHANNEL_3
#endif
#if (SOC_ADC_PERIPH_NUM >= 2)
//ADC2 Channels
#if CONFIG_IDF_TARGET_ESP32
#define EXAMPLE_ADC2_CHAN0 ADC_CHANNEL_0
#else
#define EXAMPLE_ADC2_CHAN0 ADC_CHANNEL_0
#endif
#endif
static int adc_raw[2][10];
static int voltage[2][10];
static bool example_adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle);
static void example_adc_calibration_deinit(adc_cali_handle_t handle);
void app_main(void)
{
//-------------ADC1 Init---------------//
adc_oneshot_unit_handle_t adc1_handle;
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
//-------------ADC1 Config---------------//
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_DEFAULT,
.atten = ADC_ATTEN_DB_11,
};
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN0, &config));
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, EXAMPLE_ADC1_CHAN1, &config));
//-------------ADC1 Calibration Init---------------//
adc_cali_handle_t adc1_cali_handle = NULL;
bool do_calibration1 = example_adc_calibration_init(ADC_UNIT_1, ADC_ATTEN_DB_11, &adc1_cali_handle);
#if (SOC_ADC_PERIPH_NUM >= 2)
//-------------ADC2 Init---------------//
adc_oneshot_unit_handle_t adc2_handle;
adc_oneshot_unit_init_cfg_t init_config2 = {
.unit_id = ADC_UNIT_2,
.ulp_mode = false,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config2, &adc2_handle));
//-------------ADC2 Calibration Init---------------//
adc_cali_handle_t adc2_cali_handle = NULL;
bool do_calibration2 = example_adc_calibration_init(ADC_UNIT_2, ADC_ATTEN_DB_11, &adc2_cali_handle);
//-------------ADC2 Config---------------//
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc2_handle, EXAMPLE_ADC2_CHAN0, &config));
#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
while (1) {
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN0, &adc_raw[0][0]));
ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN0, adc_raw[0][0]);
if (do_calibration1) {
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle, adc_raw[0][0], &voltage[0][0]));
ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN0, voltage[0][0]);
}
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, EXAMPLE_ADC1_CHAN1, &adc_raw[0][1]));
ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN1, adc_raw[0][1]);
if (do_calibration1) {
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle, adc_raw[0][1], &voltage[0][1]));
ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_1 + 1, EXAMPLE_ADC1_CHAN1, voltage[0][1]);
}
vTaskDelay(pdMS_TO_TICKS(1000));
#if (SOC_ADC_PERIPH_NUM >= 2)
ESP_ERROR_CHECK(adc_oneshot_read(adc2_handle, EXAMPLE_ADC2_CHAN0, &adc_raw[1][0]));
ESP_LOGI(TAG, "ADC%d Channel[%d] Raw Data: %d", ADC_UNIT_2 + 1, EXAMPLE_ADC2_CHAN0, adc_raw[1][0]);
if (do_calibration2) {
ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc2_cali_handle, adc_raw[1][0], &voltage[1][0]));
ESP_LOGI(TAG, "ADC%d Channel[%d] Cali Voltage: %d mV", ADC_UNIT_2 + 1, EXAMPLE_ADC2_CHAN0, voltage[1][0]);
}
vTaskDelay(pdMS_TO_TICKS(1000));
#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
}
//Tear Down
ESP_ERROR_CHECK(adc_oneshot_del_unit(adc1_handle));
if (do_calibration1) {
example_adc_calibration_deinit(adc1_cali_handle);
}
#if (SOC_ADC_PERIPH_NUM >= 2)
ESP_ERROR_CHECK(adc_oneshot_del_unit(adc2_handle));
if (do_calibration2) {
example_adc_calibration_deinit(adc2_cali_handle);
}
#endif //#if (SOC_ADC_PERIPH_NUM >= 2)
}
/*---------------------------------------------------------------
ADC Calibration
---------------------------------------------------------------*/
static bool example_adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_handle_t *out_handle)
{
adc_cali_handle_t handle = NULL;
esp_err_t ret = ESP_FAIL;
bool calibrated = false;
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
if (!calibrated) {
ESP_LOGI(TAG, "calibration scheme version is %s", "Curve Fitting");
adc_cali_curve_fitting_config_t cali_config = {
.unit_id = unit,
.atten = atten,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle);
if (ret == ESP_OK) {
calibrated = true;
}
}
#endif
#if ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
if (!calibrated) {
ESP_LOGI(TAG, "calibration scheme version is %s", "Line Fitting");
adc_cali_line_fitting_config_t cali_config = {
.unit_id = unit,
.atten = atten,
.bitwidth = ADC_BITWIDTH_DEFAULT,
};
ret = adc_cali_create_scheme_line_fitting(&cali_config, &handle);
if (ret == ESP_OK) {
calibrated = true;
}
}
#endif
*out_handle = handle;
if (ret == ESP_OK) {
ESP_LOGI(TAG, "Calibration Success");
} else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) {
ESP_LOGW(TAG, "eFuse not burnt, skip software calibration");
} else {
ESP_LOGE(TAG, "Invalid arg or no memory");
}
return calibrated;
}
static void example_adc_calibration_deinit(adc_cali_handle_t handle)
{
#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
ESP_LOGI(TAG, "deregister %s calibration scheme", "Curve Fitting");
ESP_ERROR_CHECK(adc_cali_delete_scheme_curve_fitting(handle));
#elif ADC_CALI_SCHEME_LINE_FITTING_SUPPORTED
ESP_LOGI(TAG, "deregister %s calibration scheme", "Line Fitting");
ESP_ERROR_CHECK(adc_cali_delete_scheme_line_fitting(handle));
#endif
}

View File

@@ -0,0 +1,14 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded.dut import Dut
@pytest.mark.esp32
@pytest.mark.esp32s2
@pytest.mark.esp32s3
@pytest.mark.esp32c3
@pytest.mark.esp32c2
def test_adc_oneshot(dut: Dut) -> None:
dut.expect(r'ADC_ONESHOT: ADC1 Channel\[(\d+)]\ Raw Data: (\d+)', timeout=5)

View File

@@ -1,55 +0,0 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
# ADC1 Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example shows how to configure ADC1 and read the voltage connected to GPIO pin.
## 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, we use `ADC_UNIT_1` by default, we need to connect a voltage source (0 ~ 3.3v) to GPIO34. If another ADC unit is selected in your application, you need to change the GPIO pin (please refer to Chapter 4.11 of the `ESP32 Technical Reference Manual`).
### Configure the project
```
idf.py menuconfig
```
### 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:
```
Raw: 486 Voltage: 189mV
Raw: 435 Voltage: 177mV
Raw: 225 Voltage: 128mV
Raw: 18 Voltage: 79mV
```
## Troubleshooting
* program upload failure
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.

View File

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

View File

@@ -1,108 +0,0 @@
/* 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 "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#define DEFAULT_VREF 1100 //Use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_SAMPLES 64 //Multisampling
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
static const adc_channel_t channel = ADC_CHANNEL_6; // GPIO7 if ADC1, GPIO17 if ADC2
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;
#endif
static const adc_atten_t atten = ADC_ATTEN_DB_0;
static const adc_unit_t unit = ADC_UNIT_1;
static void check_efuse(void)
{
#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) {
printf("Characterized using Two Point Value\n");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
printf("Characterized using eFuse Vref\n");
} else {
printf("Characterized using Default Vref\n");
}
}
void app_main(void)
{
//Check if Two Point or Vref are burned into eFuse
check_efuse();
//Configure ADC
if (unit == ADC_UNIT_1) {
adc1_config_width(width);
adc1_config_channel_atten(channel, atten);
} else {
adc2_config_channel_atten((adc2_channel_t)channel, atten);
}
//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);
//Continuously sample ADC1
while (1) {
uint32_t adc_reading = 0;
//Multisampling
for (int i = 0; i < NO_OF_SAMPLES; i++) {
if (unit == ADC_UNIT_1) {
adc_reading += adc1_get_raw((adc1_channel_t)channel);
} else {
int raw;
adc2_get_raw((adc2_channel_t)channel, width, &raw);
adc_reading += raw;
}
}
adc_reading /= NO_OF_SAMPLES;
//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);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}

View File

@@ -1,6 +0,0 @@
# 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.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(adc2)

View File

@@ -1,96 +0,0 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
# ADC2 Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
In this example, we use ADC2 to measure the output of DAC.
## How to use example
### Hardware Required
#### ESP32 platform
* A development board with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
* A USB cable for power supply and programming
We use ADC1_CHANNEL_7 (GPIO27) and DAC_CHANNEL_1 (GPIO25) by default, you need to short the two GPIOs (if you have changed the ADC2 and DAC channel, please refer to Chapter 4.11 of the `ESP32 Technical Reference Manual` to get the pin number).
#### ESP32-S2 platform
* A development board with ESP32S2 SoC
* A USB cable for power supply and programming
We use ADC1_CHANNEL_7 (GPIO18) and DAC_CHANNEL_1 (GPIO17) by default, you need to short the two GPIOs (if you have changed the ADC2 and DAC channel, please refer to the `ESP32S2 Technical Reference Manual` to get the pin number).
### Configure the project
```
idf.py menuconfig
```
* Set ADC2 and DAC channel in "Example Configuration"
### 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:
### ESP32 platform
```
ADC channel 7 @ GPIO 27, DAC channel 1 @ GPIO 25.
adc2_init...
start conversion.
1: 150
2: 203
3: 250
4: 300
5: 351
6: 400
7: 441
8: 491
9: 547
10: 595
...
```
#### ESP32-S2 platform
```
ADC channel 7 @ GPIO 18, DAC channel 1 @ GPIO 17.
adc2_init...
start conversion.
1: 150
2: 203
3: 250
4: 300
5: 351
6: 400
7: 441
8: 491
9: 547
10: 595
...
```
## Troubleshooting
* program upload failure
* Hardware connection is not correct: run `idf.py -p PORT monitor`, and reboot your board to see if there are any output logs.
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.

View File

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

View File

@@ -1,105 +0,0 @@
menu "Example Configuration"
choice EXAMPLE_ADC2_CHANNEL
bool "ADC2 Channel Num"
depends on IDF_TARGET_ESP32
default EXAMPLE_ADC2_CHANNEL_7
help
The channel of ADC2 used in this example.
config EXAMPLE_ADC2_CHANNEL_0
bool "ADC2 Channel 0 (GPIO 4)"
config EXAMPLE_ADC2_CHANNEL_1
bool "ADC2 Channel 1 (GPIO 0)"
config EXAMPLE_ADC2_CHANNEL_2
bool "ADC2 Channel 2 (GPIO 2)"
config EXAMPLE_ADC2_CHANNEL_3
bool "ADC2 Channel 3 (GPIO 15)"
config EXAMPLE_ADC2_CHANNEL_4
bool "ADC2 Channel 4 (GPIO 13)"
config EXAMPLE_ADC2_CHANNEL_5
bool "ADC2 Channel 5 (GPIO 12)"
config EXAMPLE_ADC2_CHANNEL_6
bool "ADC2 Channel 6 (GPIO 14)"
config EXAMPLE_ADC2_CHANNEL_7
bool "ADC2 Channel 7 (GPIO 27)"
config EXAMPLE_ADC2_CHANNEL_8
bool "ADC2 Channel 8 (GPIO 25)"
config EXAMPLE_ADC2_CHANNEL_9
bool "ADC2 Channel 9 (GPIO 26)"
endchoice
choice EXAMPLE_ADC2_CHANNEL
bool "ADC2 Channel Num"
depends on IDF_TARGET_ESP32S2
default EXAMPLE_ADC2_CHANNEL_7
help
The channel of ADC2 used in this example.
config EXAMPLE_ADC2_CHANNEL_0
bool "ADC2 Channel 0 (GPIO 11)"
config EXAMPLE_ADC2_CHANNEL_1
bool "ADC2 Channel 1 (GPIO 12)"
config EXAMPLE_ADC2_CHANNEL_2
bool "ADC2 Channel 2 (GPIO 13)"
config EXAMPLE_ADC2_CHANNEL_3
bool "ADC2 Channel 3 (GPIO 14)"
config EXAMPLE_ADC2_CHANNEL_4
bool "ADC2 Channel 4 (GPIO 15)"
config EXAMPLE_ADC2_CHANNEL_5
bool "ADC2 Channel 5 (GPIO 16)"
config EXAMPLE_ADC2_CHANNEL_6
bool "ADC2 Channel 6 (GPIO 17)"
config EXAMPLE_ADC2_CHANNEL_7
bool "ADC2 Channel 7 (GPIO 18)"
config EXAMPLE_ADC2_CHANNEL_8
bool "ADC2 Channel 8 (GPIO 19)"
config EXAMPLE_ADC2_CHANNEL_9
bool "ADC2 Channel 9 (GPIO 20)"
endchoice
config EXAMPLE_ADC2_CHANNEL
int
default 0 if EXAMPLE_ADC2_CHANNEL_0
default 1 if EXAMPLE_ADC2_CHANNEL_1
default 2 if EXAMPLE_ADC2_CHANNEL_2
default 3 if EXAMPLE_ADC2_CHANNEL_3
default 4 if EXAMPLE_ADC2_CHANNEL_4
default 5 if EXAMPLE_ADC2_CHANNEL_5
default 6 if EXAMPLE_ADC2_CHANNEL_6
default 7 if EXAMPLE_ADC2_CHANNEL_7
default 8 if EXAMPLE_ADC2_CHANNEL_8
default 9 if EXAMPLE_ADC2_CHANNEL_9
choice EXAMPLE_DAC_CHANNEL
bool "DAC Channel Num"
depends on IDF_TARGET_ESP32
default EXAMPLE_DAC_CHANNEL_1
help
The channel of DAC used in this example.
config EXAMPLE_DAC_CHANNEL_1
bool "DAC Channel 1 (GPIO25)"
config EXAMPLE_DAC_CHANNEL_2
bool "DAC Channel 2 (GPIO26)"
endchoice
choice EXAMPLE_DAC_CHANNEL
bool "DAC Channel Num"
depends on IDF_TARGET_ESP32S2
default EXAMPLE_DAC_CHANNEL_1
help
The channel of DAC used in this example.
config EXAMPLE_DAC_CHANNEL_1
bool "DAC Channel 1 (GPIO17)"
config EXAMPLE_DAC_CHANNEL_2
bool "DAC Channel 2 (GPIO18)"
endchoice
config EXAMPLE_DAC_CHANNEL
int
default 0 if EXAMPLE_DAC_CHANNEL_1
default 1 if EXAMPLE_DAC_CHANNEL_2
endmenu

View File

@@ -1,69 +0,0 @@
/* ADC2 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 "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "driver/dac.h"
#include "esp_system.h"
#define DAC_EXAMPLE_CHANNEL CONFIG_EXAMPLE_DAC_CHANNEL
#define ADC2_EXAMPLE_CHANNEL CONFIG_EXAMPLE_ADC2_CHANNEL
#if CONFIG_IDF_TARGET_ESP32
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
#elif CONFIG_IDF_TARGET_ESP32S2
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;
#endif
void app_main(void)
{
uint8_t output_data=0;
int read_raw;
esp_err_t r;
gpio_num_t adc_gpio_num, dac_gpio_num;
r = adc2_pad_get_io_num( ADC2_EXAMPLE_CHANNEL, &adc_gpio_num );
assert( r == ESP_OK );
r = dac_pad_get_io_num( DAC_EXAMPLE_CHANNEL, &dac_gpio_num );
assert( r == ESP_OK );
printf("ADC2 channel %d @ GPIO %d, DAC channel %d @ GPIO %d.\n", ADC2_EXAMPLE_CHANNEL, adc_gpio_num,
DAC_EXAMPLE_CHANNEL + 1, dac_gpio_num );
dac_output_enable( DAC_EXAMPLE_CHANNEL );
//be sure to do the init before using adc2.
printf("adc2_init...\n");
adc2_config_channel_atten( ADC2_EXAMPLE_CHANNEL, ADC_ATTEN_11db );
vTaskDelay(2 * portTICK_PERIOD_MS);
printf("start conversion.\n");
while(1) {
dac_output_voltage( DAC_EXAMPLE_CHANNEL, output_data++ );
r = adc2_get_raw( ADC2_EXAMPLE_CHANNEL, width, &read_raw);
if ( r == ESP_OK ) {
printf("%d: %d\n", output_data, read_raw );
} else if ( r == ESP_ERR_INVALID_STATE ) {
printf("%s: ADC2 not initialized yet.\n", esp_err_to_name(r));
} else if ( r == ESP_ERR_TIMEOUT ) {
//This can not happen in this example. But if WiFi is in use, such error code could be returned.
printf("%s: ADC2 is in use by Wi-Fi.\n", esp_err_to_name(r));
} else {
printf("%s\n", esp_err_to_name(r));
}
vTaskDelay( 2 * portTICK_PERIOD_MS );
}
}

View File

@@ -1,6 +0,0 @@
# 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.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(single_read)

View File

@@ -1,58 +0,0 @@
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- |
# 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

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

View File

@@ -1,110 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* 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.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 software calibration");
} else if (ret == ESP_ERR_INVALID_VERSION) {
ESP_LOGW(TAG, "eFuse not burnt, skip software 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));
}
}

View File

@@ -17,10 +17,10 @@
#include "esp_log.h"
#include "esp_partition.h"
#include "driver/i2s.h"
#include "driver/adc.h"
#include "audio_example_file.h"
#include "esp_adc_cal.h"
#include "esp_rom_sys.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#if CONFIG_IDF_TARGET_ESP32
static const char* TAG = "ad/da";
@@ -280,8 +280,8 @@ void example_i2s_adc_dac(void*arg)
void adc_read_task(void* arg)
{
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_11db);
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_DB_11);
esp_adc_cal_characteristics_t characteristics;
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, V_REF, &characteristics);
while(1) {

View File

@@ -4,3 +4,4 @@ CONFIG_PARTITION_TABLE_FILENAME="partitions_adc_dac_example.csv"
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
# ADC/DAC are only supported in the legacy driver, suppress the warnings while using the legacy driver
CONFIG_I2S_SUPPRESS_DEPRECATE_WARN=y
CONFIG_ADC_SUPPRESS_DEPRECATE_WARN=y