yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
ESP32 Core Board📖
1. ESP32 Introduction
  • 1. ESP32S3 Overview
  • 2. Environment Setup Introduction
  • 3. Dev Board Introduction
2. ESP-IDF Development Tutorial
1. Before Development
  • 1. Environment Setup (Windows)
  • 2. Environment Setup (Linux)
  • 3. Build and Flash
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. ESP_TIMER
  • 5. GPTIMER
  • 6. Watchdog Timer
  • 7. DMA
  • 8. ADC
  • 9. PWM Breathing LED
  • 10. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication Experiment
  • 2. I2C_OLED Display Experiment
  • 3. SPI Bus Communication Experiment
  • 4. PSRAM External Memory Experiment
  • 5. Flash Read and Write Experiment
  • 6. USB Emulated Mass Storage Experiment
4. FreeRTOS operating system
  • 1.FreeRTOS Core Concepts Theory
  • 2.Task Creation and Management
  • 3.Queue
  • 4.Binary Semaphore
  • 5.Mutex
  • 6.Event Groups
  • 7.Software Timer
  • 8.Task Scheduler
  • 9.Low Power Mode
  • 10.Deadlock
  • 11.Priority Inversion
5. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Client Experiment
  • 5. UDP Server Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. Socket Programming Basics
  • 9. HTTP Client Experiment
  • 10. HTTP Server Experiment
  • 11. MQTT IoT Communication Protocol
  • 12. WIFI OTA Upgrade
  • 13. Bluetooth Fundamentals
  • 14. Bluetooth Slave Mode
  • 15. Bluetooth Master Mode
6. Audio Applications
  • 1.I2S Microphone Recording and U-Disk Playback
  • 2.I2S Audio Playback Experiment
  • 3.Repeater Experiment
7. Xiaozhi AI Voice
  • 1. Burn Xiaozhi Firmware
  • 2. Network and Configuration
  • 3. AI Agent Settings
  • 4. Program Analysis
  • 5. Free Chat
3. Arduino Development Course
1. Before Development
  • 1. Environment Setup
  • 2. Build and Flash
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. ESP_TIMER
  • 5. GPTIMER
  • 6. Watchdog Timer
  • 7. ADC
  • 8. PWM Breathing LED
  • 9. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication
  • 2. I2C OLED Display
  • 3. SPI Bus Communication
  • 4. Flash Read and Write
  • 5. USB Emulated Mass Storage
4. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Server Experiment
  • 5. UDP Client Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. HTTP Client Experiment
  • 9. HTTP Server Experiment
  • 10. MQTT IoT Communication Protocol
  • 11. WIFI OTA Upgrade
  • 12. Bluetooth Fundamentals
  • 13. Bluetooth Slave Mode
  • 14. Bluetooth Master Mode
5. Audio Applications
  • 1.I2S Microphone Recording and U-Disk Playback
  • 2.I2S Audio Playback Experiment
  • 3.Repeater Experiment
4. MicroPython Development Course
1. Before Development
  • 1. Environment Setup
  • 2. Build and Flash
  • 3. Thonny IDE
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. TIMER_IT
  • 5. Watchdog Timer
  • 6. ADC
  • 7. PWM Breathing LED
  • 8. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication Experiment
  • 2. I2C_OLED Display Experiment
  • 3. SPI Bus Communication Experiment
  • 4. Flash Read and Write Experiment
  • 5. Print Storage
4. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Client Experiment
  • 5. UDP Server Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. HTTP Client Experiment
  • 9. HTTP Server Experiment
  • 10. MQTT
  • 11. Bluetooth Fundamentals
  • 12. Bluetooth Slave Mode
  • 13. Bluetooth Master Mode
5. Audio Applications
  • 1. I2S Audio Playback Experiment
  • 2. Repeater Experiment
Download
  • Code
  • Hardware_Info
  • 3D_Model_File
  • Software_Tools
  • VMware
  • VM_File
Download ZIP

Welcome to ESP32 Core Board repository

8. ADC

ADC


ADC1. ADC Overview2. Core Concepts2.1 ADC Conversion Principle2.2 Bit Width and Resolution2.3 Attenuation Configuration2.4 Two Driver Modes3. ESP32-S3 ADC Hardware Characteristics4. Project Architecture and Flow5. Hardware Dependencies6. Source Code Analysis6.1 Header Files and Macro Configuration6.2 adc_init() — Initialization6.3 adc_read_loop() — Acquisition Loop6.4 app_main() — Main Entry7. Operation Flow7.1 Build and Flash7.2 Normal Acquisition7.2 Boundary Cases8. Common Issues

 

 


1. ADC Overview

ADC (Analog-to-Digital Converter) converts continuously varying analog voltage (from potentiometers, sensor outputs) into digital values that MCUs can process.

Typical sensor scenarios:

Sensor TypeApplication
PhotoresistorLight intensity detection
VaristorWeight sensor, electronic scale
Potentiometer / Level sensorWater level, oil level detection
Voltage divider networkBattery voltage detection

MCU can then perform threshold judgment to trigger control actions, such as low oil level alarm, low battery alarm, over-temperature protection, etc.


2. Core Concepts

2.1 ADC Conversion Principle

ADC uses Successive Approximation (SAR), mapping input voltage to digital code based on reference voltage and bit width.

Example with 12-bit resolution, Vref+ = 3.3V, Vref- = 0V, full scale 4096 levels (0x000 ~ 0x0FFF), minimum resolution ≈ 0.8mV.

Voltage formula without attenuation:

Vdata = (data / (2^bitwidth - 1)) × Vref

img

 

Voltage formula with attenuation:

xxxxxxxxxx
Vdata = (data / (2^bitwidth - 1)) × Vref / k

img

 

Parameter meanings:

ParameterMeaning
dataADC raw output code (12-bit: 0 ~ 4095)
bitwidthResolution bit width (default 12)
VrefReference voltage (3.3V)
kAttenuation coefficient (0dB=1, 2.5dB≈0.75, 6dB=0.5, 12dB=0.25)

Calculation example — Input 2.2V, 12dB attenuation (k=0.25):

xxxxxxxxxx
raw = (2.2V × 4095) / (3.3V / 0.25) ≈ 683

2.2 Bit Width and Resolution

xxxxxxxxxx
typedef enum {
    // Default, auto max bit width
    ADC_BITWIDTH_DEFAULT = 0,
    ADC_BITWIDTH_9  = 9,      // 9-bit, 0~511
    ADC_BITWIDTH_10 = 10,     // 10-bit, 0~1023
    ADC_BITWIDTH_11 = 11,     // 11-bit, 0~2047
    ADC_BITWIDTH_12 = 12,     // 12-bit, 0~4095 (common)
    ADC_BITWIDTH_13 = 13,     // 13-bit, 0~8191
} adc_bitwidth_t;
Bit WidthMax CodeMin Resolution (Vref=3.3V)
9 bit511~6.5 mV
10 bit1023~3.2 mV
11 bit2047~1.6 mV
12 bit (default)4095~0.8 mV
13 bit8191~0.4 mV

2.3 Attenuation Configuration

Attenuation determines the measurable voltage upper limit. Greater attenuation means larger range but lower effective resolution.

xxxxxxxxxx
typedef enum {
    ADC_ATTEN_DB_0   = 0,  // No atten, range~1.1V
    ADC_ATTEN_DB_2_5 = 1,  // 2.5dB atten, range~1.5V
    ADC_ATTEN_DB_6   = 2,  // 6dB atten, range~2.2V
    ADC_ATTEN_DB_12  = 3,  // 12dB atten, range~3.3V
} adc_atten_t;
Attenuation LevelCoefficient kRange (Vref=3.3V)
ADC_ATTEN_DB_0 (0 dB)~1.000 ~ 1.1 V
ADC_ATTEN_DB_2_5 (2.5 dB)~0.750 ~ 1.5 V
ADC_ATTEN_DB_6 (6 dB)~0.500 ~ 2.2 V
ADC_ATTEN_DB_12 (12 dB)~0.250 ~ 3.3 V

2.4 Two Driver Modes

FeatureOne-shot ModeContinuous + DMA Mode
Trigger MethodManual single readAuto continuous sampling
Data TransferCPU polling readDMA auto-transfer
SpeedLow frequency (≤1kHz)High frequency (up to MHz)
CPU UsageHighLow
Use CaseButtons, potentiometers, slow sensorsAudio, FFT, high-speed acquisition
Core APIadc_oneshot_read()adc_continuous_start()

This project uses one-shot mode, 16 times per second sampling and averaging, balancing response speed and stability.


3. ESP32-S3 ADC Hardware Characteristics

FeatureParameter
SAR ADC units2 (ADC1, ADC2)
Dedicated controllers5 (different scenarios: high performance/low power/power detection/peak detection)
Analog input pins18
Internal channels1×VDD33, 2×PA_PKDET (some controllers)
Resolution9 / 10 / 11 / 12 / 13 bit configurable
DMA support1 controller supports
Multi-channel scan2 controllers support
Deep-sleep operation1 controller supports
ULP coprocessor2 controllers support

Note: ADC2 shares resources with Wi-Fi. When Wi-Fi is enabled, ADC1 takes priority.


4. Project Architecture and Flow

xxxxxxxxxx
app_main()
  ├─ adc_init()         ← Initialize ADC handle & channel
  │   ├─ adc_oneshot_new_unit()        Create ADC1 unit
  │   └─ adc_oneshot_config_channel()  Configure channel: 12dB atten + 12-bit width
  │
  └─ adc_read_loop()    ← Main loop (never returns)
      while(1):
        ├─ for(16 times) adc_oneshot_read()  → accumulate raw to sum
        ├─ avg_raw = sum / 16            → calculate average
        ├─ avg_mv = avg_raw × 3300 / 4095 → convert to mV
        ├─ ESP_LOGI() print               → avg_raw + mV
        └─ vTaskDelay(1000ms)            → delay 1s

5. Hardware Dependencies

Hardware Connection: GPIO4 (ADC1_CH3) —待测电压 source (0~3.3V)

Dependencies: esp_adc, FreeRTOS, esp_log

6. Source Code Analysis

6.1 Header Files and Macro Configuration

​x
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_adc/adc_oneshot.h"
#define ADC_UNIT           ADC_UNIT_1
// 12dB atten→0~3.3V range
#define ADC_ATTEN          ADC_ATTEN_DB_12
#define ADC_CHAN           ADC_CHANNEL_3                        // CH3 (GPIO4)
#define SAMPLE_COUNT       16                                    // Samples per batch
#define ADC_VREF_MV        3300                                 // Reference voltage (mV)
#define ADC_MAX_COUNT      4095                                 // 12-bit full scale

// Log tag
static const char *TAG = "ADC_DEMO";
static adc_oneshot_unit_handle_t adc_handle;

Why GPIO4 instead of GPIO3? ESP32-S3's GPIO3 is JTAG/USB-Serial-JTAG strapping pin, chip has internal pull-up resistor, ADC always reads 4095. Using GPIO4 (CH3) works normally.

6.2 adc_init() — Initialization

adc_init() does two things: Create ADC unit → Configure channel parameters.

  1. adc_oneshot_new_unit() instantiates an ADC1 one-shot acquisition unit, returns handle adc_handle. All subsequent operations reference this unit through it.

  2. adc_oneshot_config_channel() binds GPIO4 (CH3) to this unit, while setting 12dB atten (range 0~3.3V) and default bit width (12-bit).

Called once, repeated calls don't reinitialize.

xxxxxxxxxx
static void adc_init(void)
{
    adc_oneshot_unit_init_cfg_t init_config = {
        .unit_id = ADC_UNIT,                                    // ADC1
    };
    ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle));

    adc_oneshot_chan_cfg_t chan_cfg = {
        // 12dB atten
        .atten = ADC_ATTEN,
        // Default 12-bit
        .bitwidth = ADC_BITWIDTH_DEFAULT,
    };
    ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle, ADC_CHAN, &chan_cfg));
}

6.3 adc_read_loop() — Acquisition Loop

adc_read_loop() is an infinite loop completing one sample → filter → print per second:

  1. for loop calls adc_oneshot_read() 16 times, each raw value accumulated to sum.

  2. sum / 16 gets average avg_raw, filtering high-frequency random noise.

  3. Formula avg_raw × 3300 / 4095 converts to millivolt value avg_mv.

  4. ESP_LOGI() prints average raw and mV.

  5. vTaskDelay(1000ms) delays 1 second then next round.

This function has no return value (while(1) never exits), it's the program's main loop.

xxxxxxxxxx
static void adc_read_loop(void)
{
    while (1)
    {
        // Accumulated sum
        int sum = 0;

        for (int i = 0; i < SAMPLE_COUNT; i++)
        {
            int raw;
            ESP_ERROR_CHECK(adc_oneshot_read(adc_handle, ADC_CHAN, &raw));
            sum += raw;
        }

        // Average
        int avg_raw = sum / SAMPLE_COUNT;
        int avg_mv = (avg_raw * ADC_VREF_MV) / ADC_MAX_COUNT;   // mV = raw × 3300 / 4095

        // Print: ADC raw value + voltage (mV)
        ESP_LOGI(TAG, "ADC_Value=%4d, Voltage=%4d mV", avg_raw, avg_mv);

        // 1 second interval
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

Mean filtering is the simplest digital filtering. No need for complex algorithms like EMA/Kalman. After 16-time averaging, ±3~5 LSB inherent noise is compressed to ±1 LSB, with only 1 second response delay.

6.4 app_main() — Main Entry

xxxxxxxxxx
Function signature: void app_main(void)
Input:  None
Output: None
xxxxxxxxxx
void app_main(void)
{
  adc_init()       → Initialize ADC
  adc_read_loop()  → Loop acquisition and print
}

7. Operation Flow

7.1 Build and Flash

For detailed flashing process, see: 1. Before Development → 3. Build and Flash

7.2 Normal Acquisition

Log field meanings:

FieldExampleMeaning
IIINFO level log
(1263)1263Milliseconds since system startup (timestamp)
ADC_DEMOADC_DEMOLog tag (TAG macro defined in code)
ADC_Value=37773777ADC raw value average of 16 samples (0~4095)
Voltage=30433043Converted measured voltage in mV (i.e., 3.043V)

Conversion: mV = ADC_Value × 3300 / 4095. When ADC_Value=3777, Voltage=3300 × 3777 / 4095 ≈ 3043mV.

xxxxxxxxxx
I (1263) ADC_DEMO: ADC_Value=3777, Voltage=3043 mV
I (2263) ADC_DEMO: ADC_Value=4095, Voltage=3300 mV
I (3263) ADC_DEMO: ADC_Value=3617, Voltage=2914 mV
I (4263) ADC_DEMO: ADC_Value=3550, Voltage=2860 mV
I (5263) ADC_DEMO: ADC_Value=3289, Voltage=2650 mV
I (6263) ADC_DEMO: ADC_Value=2759, Voltage=2223 mV

悬空状态下ADC值

7.2 Boundary Cases

Boundary cases are quick self-checks to verify ADC hardware and code are normal:

  • Connect GND → reads 0: Pin pulled to 0V, ADC reads minimum code 0, indicates ADC zero point is normal.

  • Connect 3.3V → reads 4094: Pin connected to reference voltage, reads near full scale (±1 LSB error is normal), indicates ADC full scale is normal.

  • Pin floating → readings jump randomly: Floating pin acts like an antenna, couples surrounding EM fields (50Hz mains, Wi-Fi signals, etc.). SAR ADC sampling injects charge into pin without release path, readings drift randomly—this is normal phenomenon, not a hardware fault.

Verification method: Zero point normal + full scale normal = hardware and code are fine. Floating readings are physical phenomenon, not a bug.

xxxxxxxxxx
// Pin connected to GND
I (144263) ADC_DEMO: ADC_Value=0, Voltage=0 mV

// Pin to 3.3V
I (285263) ADC_DEMO: ADC_Value=4095, Voltage=3300 mV

// Pin floating, antenna effect, random
I (6263) ADC_DEMO: ADC_Value=2759, Voltage=2223 mV   // Drifting
I (7263) ADC_DEMO: ADC_Value=2041, Voltage=1644 mV   // Continue drifting

接GND状态下ADC值

0值连线

接3.3V状态下ADC值

3.3峰值连线

Floating pin readings first increase then decrease is normal phenomenon, reason:

  1. SAR ADC injects charge into pin during sampling, floating has no release path, parasitic capacitor voltage accumulates

  2. 50Hz mains electric field coupling, manifests as low-frequency sinusoidal drift

  3. Solution: Connecting to GND returns to zero = code is fine


8. Common Issues

PhenomenonCauseSolution
Reading always 4095Pin floating / using strapping pins (GPIO0/3/45/46)Connect to GND to verify zero → use GPIO4 or other normal pins
Reading always 0Pin shorted to GND / atten configuration errorCheck wiring, confirm input voltage within range
Reading ±3~5mV jitterNormal, ADC inherent quantization noiseAverage multiple samples (built-in 16-time average)
Large reading driftPin floatingConnect pull-down resistor (10kΩ→GND) or actual signal
ADC2 + Wi-Fi abnormalADC2 shares resources with Wi-FiUse ADC1 instead
Strapping pins read 4095Internal pull-up raises levelAvoid GPIO0, GPIO3, GPIO45, GPIO46

DMA
PWM Breathing LED

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文