Embedded HandbookПриложения
Все разделы › XVIII. ESP32: второй микроконтроллер
ESP32 · уровень средний · 14 мин чтения
Открыть в интерактивном справочнике

154. АЦП и ЦАП ESP32: затухание, калибровка, ADC2 и Wi-Fi, непрерывный режим, ЦАП и косинус

АЦП STM32 из раздела 14 — 12 бит, опора равна питанию, точность порядка младшего разряда, и формула «код × 3,3 / 4096» работает. АЦП ESP32 — тоже 12 бит и тоже поразрядного уравновешивания, но опора у него внутренняя и своя у каждого кристалла, вход не покрывает весь диапазон питания, а линейность такая, что без калибровки ошибка измеряется десятками милливольт. Отсюда всё в этом разделе: четыре окна затухания, калибровка по eFuse, второй АЦП, который отключается вместе с Wi-Fi, и два восьмибитных ЦАП с генератором косинуса. Логику драйверов проверяет QEMU (_verify/esp154/), числа — даташит (выписка datasheet_adc.txt) и заголовки ESP-IDF, арифметику — модель на Python.

Как это называется в документации

Оригинал Перевод
SAR ADC АЦП поразрядного уравновешивания
attenuation (0 / 2.5 / 6 / 12 dB) затухание на входе: расширяет измеряемое окно
effective measurement range окно, где обещана точность
calibration, line fitting, two point калибровка: по прямой или по двум точкам
Vref, eFuse Vref опора АЦП и её значение, записанное в eFuse
DNL, INL дифференциальная и интегральная нелинейность
total error полная ошибка после калибровки
oneshot / continuous mode одиночное чтение / поток через DMA
RTC controller / DIG controller контроллер АЦП для одиночных чтений / для потока
conversion frame кадр результатов DMA
DAC, cosine wave generator ЦАП, генератор косинуса

154.1 Два блока, 18 каналов, и где они

ADC1: ch0=GPIO36 ch1=GPIO37 ch2=GPIO38 ch3=GPIO39 ch4=GPIO32 ch5=GPIO33 ch6=GPIO34 ch7=GPIO35
ADC2: ch0=GPIO4 ch1=GPIO0 ch2=GPIO2 ch3=GPIO15 ch4=GPIO13 ch5=GPIO12 ch6=GPIO14 ch7=GPIO27 ch8=GPIO25 ch9=GPIO26

Каналы привязаны к выводам жёстко — матрица GPIO из раздела 153 на аналоговые сигналы не распространяется. ADC1 сидит на входах 32–39: шесть из них только входы, что для АЦП и нужно. ADC2 разбросан по выводам 0–27, среди них три strapping-вывода (0, 2, 15) и оба выхода ЦАП (25, 26). И главное: ADC2 не работает, пока включён Wi-Fi — радио использует тот же блок для измерения своей мощности. Для изделия с Wi-Fi остаётся ADC1: у голого чипа восемь каналов, а у модуля WROOM-32 — шесть (GPIO32–36 и 39): выводов 37 и 38 на модуле нет.

АЦП ESP32: входное окно выбирает затухание, 12-битный SAR даёт код, калибровка по Vref из eFuse превращает код в милливольты; ADC2 отключается радио


154.2 Затухание: четыре окна

Опора АЦП — около 1,1 В внутри чипа, и без ослабления вход измеряет примерно до 1 В. Чтобы измерять до 3,3 В, перед АЦП ставят делитель с затуханием 2,5, 6 или 12 дБ. Даташит (таблица 4-4) обещает точность только внутри окон:

Затухание Окно Полная ошибка после калибровки
0 дБ 100 … 950 мВ ±23 мВ
2,5 дБ 100 … 1250 мВ ±30 мВ
6 дБ 150 … 1750 мВ ±40 мВ
12 дБ 150 … 2450 мВ ±60 мВ

Ниже 100–150 мВ и выше верхней границы АЦП работает, но точности не обещано; при 12 дБ выше кода 3000 (около 2450 мВ) она заметно хуже — это отдельная оговорка таблицы 4-3. Значит, «3,3 В на входе» ESP32 не измеряет вовсе: делитель нужен и снаружи. Нелинейность по той же таблице — DNL до ±7 и INL до ±12 младших разрядов, поэтому советуют усреднять несколько выборок. Шаг квантования у каждого окна свой — это наклон прямой калибровки из 154.3 на кодах 0…2048 (при 12 дБ выше кода 2880 драйвер переходит на таблицу, и кривая загибается). Окно точности уже, чем весь размах кодов, поэтому делить окно на 4096 нельзя:

3,3 В / 4096 = 0.806 мВ — так считать нельзя: шаг у окон разный, а прямая не проходит через ноль
0 дБ    окно  100… 950 мВ: шаг 0.235 мВ, ошибка после калибровки ±23 мВ = ±98 шагов
2,5 дБ  окно  100…1250 мВ: шаг 0.312 мВ, ошибка после калибровки ±30 мВ = ±96 шагов
6 дБ    окно  150…1750 мВ: шаг 0.432 мВ, ошибка после калибровки ±40 мВ = ±93 шагов
12 дБ   окно  150…2450 мВ: шаг 0.806 мВ, ошибка после калибровки ±60 мВ = ±74 шагов

При 12 дБ шаг совпал с 3,3 В / 4096, но прямая сдвинута на 142 мВ, так что формула «код × 0,806» врёт и там.

Ошибка в 75–100 шагов при 12 битах означает: разрядов 12, но больше шести из них съедает ошибка, и по абсолютному значению доверять можно примерно пяти — это ±2,5…2,7 % окна. Для термистора и потенциометра этого достаточно, для измерителя напряжения — нет; там ставят внешний АЦП по I²C или SPI. В ESP-IDF 5 затухание 11 дБ переименовано в 12 дБ, старое имя ADC_ATTEN_DB_11 помечено устаревшим и означает то же самое.

Четыре окна затухания АЦП ESP32 на шкале до 3,3 В: границы, ошибка после калибровки и шаг квантования


154.3 Калибровка: код → милливольты

Опора у каждого кристалла своя, и на заводе её измеряют и записывают в eFuse. Драйвер калибровки читает eFuse и строит прямую код → напряжение; если в eFuse пусто, берёт 1100 мВ:

        adc_cali_line_fitting_config_t cfg = { .unit_id = ADC_UNIT_1, .atten = att, .bitwidth = ADC_BITWIDTH_12, .default_vref = 1100 };
        adc_cali_handle_t h = NULL;
        esp_err_t e = adc_cali_create_scheme_line_fitting(&cfg, &h);
калибровка 0 дБ ESP_OK:    0→  75 мВ 1000→ 310 мВ 2048→ 557 мВ 3000→ 781 мВ 4095→1039 мВ
калибровка 2,5 дБ ESP_OK:    0→  78 мВ 1000→ 390 мВ 2048→ 718 мВ 3000→1015 мВ 4095→1357 мВ
калибровка 6 дБ ESP_OK:    0→ 107 мВ 1000→ 539 мВ 2048→ 992 мВ 3000→1404 мВ 4095→1877 мВ
калибровка 12 дБ ESP_OK:    0→ 142 мВ 1000→ 948 мВ 2048→1792 мВ 3000→2543 мВ 4095→3134 мВ
eFuse калибровки: нет — Vref по умолчанию 1100 мВ

Прямая не проходит через ноль: код 0 при 12 дБ — это уже 142 мВ, а 4095 — 3134 мВ. Так драйвер учитывает смещение и наклон АЦП; своя формула «код × шаг» дала бы ошибку на сотни милливольт. Полный диапазон 12 дБ доходит до 3,1 В, но обещанная точность кончается на 2450 мВ. adc_cali_raw_to_voltage — единственный правильный способ получить вольты; adc_cali_scheme_line_fitting_check_efuse говорит, записан ли Vref или две точки. В эмуляторе eFuse пуст, и ответ «нет».


154.4 Одиночное чтение и поток

Одиночное чтение — три вызова: adc_oneshot_new_unit, adc_oneshot_config_channel с затуханием и разрядностью, adc_oneshot_read. Первые два в эмуляторе проходят, третье — нет:

adc_oneshot: блок и канал ADC1 ch6 (GPIO34) настроены; чтение ждёт флага готовности, которого в эмуляторе нет

QEMU не моделирует АЦП: чтение ждёт флага «готово» вечно и через 300 мс срабатывает сторож прерываний (раздел 152). Поэтому уровни — только на плате, а в эмуляторе проверяется всё остальное.

Непрерывный режим гонит выборки через DMA без участия процессора — на ESP32 через контроллер I²S, поэтому и ограничения его:

непрерывный режим: 20000 … 2000000 Гц, 9…12 бит, кадр результата 2 байта
adc_continuous_config 10 кГц: ESP_ERR_INVALID_ARG
adc_continuous_config 20 кГц: ESP_OK
adc_continuous_config 2 МГц: ESP_OK
adc_continuous_config ADC2: ESP_ERR_INVALID_ARG

Медленнее 20 кГц поток не бывает: кто хочет 1 кГц, тот читает одиночно по таймеру. Быстрее 2 МГц — тоже нет, а на 2 МГц это 4 МБ/с:

  20000 Гц × 2 байта = 40000 байт/с, кадр 256 байт — раз в 6.40 мс
2000000 Гц × 2 байта = 4000000 байт/с, кадр 256 байт — раз в 0.06 мс

Кадр в 256 байт при 2 МГц заканчивается каждые 64 мкс — обработчик должен успевать. ADC2 в поток не берётся вовсе (ESP_ERR_INVALID_ARG): DMA есть только у первого блока. Даташит называет пределы: 200 квыб/с через контроллер RTC (одиночные чтения) и 2 Мвыб/с через цифровой.


154.5 Что делает АЦП за 12 шагов

Поразрядное уравновешивание — 12 сравнений, по одному на бит: модель на Python для входа 1730 мВ при условной опоре 2450 мВ:

шаг  1: пробуем 2048 ( 1225.0 мВ) — оставляем
шаг  2: пробуем 3072 ( 1837.5 мВ) — сбрасываем
шаг  3: пробуем 2560 ( 1531.2 мВ) — оставляем
шаг 12: пробуем 2893 ( 1730.4 мВ) — сбрасываем
код 2892 = 0b101101001100, 1729.8 мВ, ошибка 0.17 мВ

Двенадцать шагов поразрядного уравновешивания для входа 1730 мВ: пробное напряжение скачет вокруг входа и сужается вдвое; итог — код 2892

Каждый шаг ставит очередной бит, сравнивает с входом и оставляет или сбрасывает; 12 шагов — 12 тактов АЦП, отсюда и предел скорости. Для входа 1730 мВ ошибка — 0,17 мВ, 0,28 шага (шаг 0,598 мВ). Идеальный АЦП, который, как здесь, отбрасывает остаток, ошибается от нуля до шага, а разброс ошибки по многим входам — шаг/√12 ≈ 0,29 шага; настоящий, как видно из 154.2, ошибается почти на сотню шагов. Идеальный предел отношения сигнал/шум — 6,02·N + 1,76 дБ:

 8 бит: SNR = 49.92 дБ
12 бит: SNR = 74.00 дБ

154.6 ЦАП: два канала и косинус

dac_oneshot_output_voltage 128 (половина VDD): ESP_OK
dac_cosine 100 Гц: ESP_ERR_NOT_SUPPORTED
dac_cosine 1000 Гц: ESP_OK

Два ЦАП по 8 бит на GPIO25 и GPIO26 — резистивная цепочка с буфером, опора — питание, то есть шаг 3,3 В / 256 ≈ 13 мВ и никакой точности выше процента. Три режима: постоянный уровень (dac_oneshot), поток из памяти через DMA (dac_continuous) и встроенный генератор косинуса, которому не нужен ни DMA, ни процессор: частота от примерно 130 Гц при штатном тактировании (100 Гц драйвер отвергает), фаза 0 или 180°, смещение и четыре ступени амплитуды. Для звука и произвольных форм — DMA, для проверки АЦП или простого генератора — косинус. Замечание из раздела 15 остаётся в силе: встроенный буфер слабый, выход ЦАП годится для высокоомного входа, а всё, что берёт заметный ток (наушники, длинный кабель, низкоомный делитель), подключают через внешний ОУ.


154.7 Практика: как измерять правильно

Задача Решение
датчик 0–3,3 В делитель до 2,4 В, затухание 12 дБ, калибровка
термистор, потенциометр 12 дБ, усреднение 16–64 выборок
сигнал 0–1 В 0 дБ — лучшая точность
измеритель напряжения ±0,5 % внешний АЦП по I²C или SPI, встроенный не годится
звук, вибрация непрерывный режим ADC1, 20 кГц и выше
изделие с Wi-Fi только ADC1; ADC2 — лишь при выключенном радио
осциллограф 1 МГц непрерывный режим до 2 МГц, 4 МБ/с в ОЗУ

154.8 Грабли

Симптом Причина
ADC2 … ESP_ERR_TIMEOUT при включённом Wi-Fi ADC2 занят радио; переставить на ADC1
код 4095 при 2,6 В окно 12 дБ кончается на 2450 мВ; нужен делитель
«код × 0,806 мВ» врёт на 100–300 мВ опора не 3,3 В и прямая не через ноль; adc_cali_raw_to_voltage
результат прыгает на десятки кодов шум: собственный шум АЦП, провалы питания на пиках тока Wi-Fi (раздел 161), высокоомный источник; 100 нФ на входе, усреднять 16–64 выборки
показания ровные, но ложатся не на прямую DNL/INL: ошибка у каждого кода своя и постоянная; поправляет калибровка по нескольким точкам
adc_continuous_config → ESP_ERR_INVALID_ARG частота ниже 20 кГц или блок ADC2
ADC_ATTEN_DB_11 — предупреждение об устаревшем в ESP-IDF 5 это ADC_ATTEN_DB_12, поведение то же
dac_cosine → ESP_ERR_NOT_SUPPORTED частота ниже ≈130 Гц при штатном тактировании
АЦП на GPIO25/26 «не работает» это выходы ЦАП, а по АЦП — ADC2
adc_oneshot_read в QEMU — сторож прерываний эмулятор не моделирует АЦП

154.9 Итоги

Полные исходники

main.c — АЦП и ЦАП ESP32: каналы, калибровка по прямой, непрерывный режим, генератор косинуса.

/* Раздел 154: АЦП и ЦАП ESP32 — каналы и выводы, калибровка «по прямой» без eFuse,
 * пределы непрерывного режима, ЦАП и генератор косинуса. Уровни на входах эмулятор не моделирует. */
#include <stdio.h>
#include "driver/dac_cosine.h"
#include "driver/dac_oneshot.h"
#include "esp_adc/adc_cali.h"
#include "esp_adc/adc_cali_scheme.h"
#include "esp_adc/adc_continuous.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_err.h"
#include "esp_log.h"
#include "soc/soc_caps.h"

static const char *TAG = "adc154";

void app_main(void)
{
    /* какой канал на каком выводе */
    for (int unit = 0; unit < SOC_ADC_PERIPH_NUM; unit++) {
        printf("ADC%d:", unit + 1);
        for (int ch = 0; ch < SOC_ADC_CHANNEL_NUM(unit); ch++) {
            int io = -1;
            adc_oneshot_channel_to_io(unit, ch, &io);
            printf(" ch%d=GPIO%d", ch, io);
        }
        printf("\n");
    }

    /* калибровка по прямой: без записи Vref в eFuse берётся 1100 мВ */
    static const char *att_name[] = { "0 дБ", "2,5 дБ", "6 дБ", "12 дБ" };
    static const int raws[] = { 0, 1000, 2048, 3000, 4095 };
    for (int att = 0; att < SOC_ADC_ATTEN_NUM; att++) {
        adc_cali_line_fitting_config_t cfg = { .unit_id = ADC_UNIT_1, .atten = att, .bitwidth = ADC_BITWIDTH_12, .default_vref = 1100 };
        adc_cali_handle_t h = NULL;
        esp_err_t e = adc_cali_create_scheme_line_fitting(&cfg, &h);
        printf("калибровка %-6s %s:", att_name[att], esp_err_to_name(e));
        for (size_t i = 0; i < sizeof raws / sizeof raws[0]; i++) {
            int mv = -1;
            adc_cali_raw_to_voltage(h, raws[i], &mv);
            printf(" %4d→%4d мВ", raws[i], mv);
        }
        printf("\n");
        adc_cali_delete_scheme_line_fitting(h);
    }
    adc_cali_line_fitting_efuse_val_t ev;
    adc_cali_scheme_line_fitting_check_efuse(&ev);
    printf("eFuse калибровки: %s\n", ev == ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_VREF ? "Vref" : ev == ADC_CALI_LINE_FITTING_EFUSE_VAL_EFUSE_TP ? "две точки" : "нет — Vref по умолчанию 1100 мВ");

    /* одиночное чтение: в эмуляторе входа нет */
    adc_oneshot_unit_handle_t adc1;
    adc_oneshot_unit_init_cfg_t ucfg = { .unit_id = ADC_UNIT_1 };
    ESP_ERROR_CHECK(adc_oneshot_new_unit(&ucfg, &adc1));
    adc_oneshot_chan_cfg_t ccfg = { .atten = ADC_ATTEN_DB_12, .bitwidth = ADC_BITWIDTH_12 };
    ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1, ADC_CHANNEL_6, &ccfg));
    printf("adc_oneshot: блок и канал ADC1 ch6 (GPIO34) настроены; чтение ждёт флага готовности, которого в эмуляторе нет\n");
    esp_err_t e;
    adc_oneshot_del_unit(adc1);

    /* непрерывный режим: пределы частоты дискретизации из soc_caps */
    printf("непрерывный режим: %d … %d Гц, 9…12 бит, кадр результата %d байта\n", SOC_ADC_SAMPLE_FREQ_THRES_LOW,
           SOC_ADC_SAMPLE_FREQ_THRES_HIGH, SOC_ADC_DIGI_RESULT_BYTES);
    adc_continuous_handle_t ch = NULL;
    adc_continuous_handle_cfg_t hcfg = { .max_store_buf_size = 1024, .conv_frame_size = 256 };
    ESP_ERROR_CHECK(adc_continuous_new_handle(&hcfg, &ch));
    adc_digi_pattern_config_t pat = { .atten = ADC_ATTEN_DB_12, .channel = ADC_CHANNEL_6, .unit = ADC_UNIT_1, .bit_width = ADC_BITWIDTH_12 };
    adc_continuous_config_t dcfg = { .pattern_num = 1, .adc_pattern = &pat, .sample_freq_hz = 10000,
                                     .conv_mode = ADC_CONV_SINGLE_UNIT_1, .format = ADC_DIGI_OUTPUT_FORMAT_TYPE1 };
    esp_log_level_set("adc_continuous", ESP_LOG_NONE);
    printf("adc_continuous_config 10 кГц: %s\n", esp_err_to_name(adc_continuous_config(ch, &dcfg)));
    dcfg.sample_freq_hz = 20000;
    printf("adc_continuous_config 20 кГц: %s\n", esp_err_to_name(adc_continuous_config(ch, &dcfg)));
    dcfg.sample_freq_hz = 2000000;
    printf("adc_continuous_config 2 МГц: %s\n", esp_err_to_name(adc_continuous_config(ch, &dcfg)));
    pat.unit = ADC_UNIT_2;
    dcfg.conv_mode = ADC_CONV_SINGLE_UNIT_2;
    printf("adc_continuous_config ADC2: %s\n", esp_err_to_name(adc_continuous_config(ch, &dcfg)));
    adc_continuous_deinit(ch);

    /* ЦАП: два канала по 8 бит на GPIO25/26, генератор косинуса */
    dac_oneshot_handle_t dac;
    dac_oneshot_config_t ocfg = { .chan_id = DAC_CHAN_0 };
    ESP_ERROR_CHECK(dac_oneshot_new_channel(&ocfg, &dac));
    printf("dac_oneshot_output_voltage 128 (половина VDD): %s\n", esp_err_to_name(dac_oneshot_output_voltage(dac, 128)));
    dac_oneshot_del_channel(dac);
    dac_cosine_handle_t cos;
    dac_cosine_config_t cc = { .chan_id = DAC_CHAN_1, .freq_hz = 100, .clk_src = DAC_COSINE_CLK_SRC_DEFAULT, .offset = 0, .phase = DAC_COSINE_PHASE_0,
                               .atten = DAC_COSINE_ATTEN_DEFAULT, .flags.force_set_freq = false };
    esp_log_level_set("dac_cosine", ESP_LOG_NONE);
    printf("dac_cosine 100 Гц: %s\n", esp_err_to_name(dac_cosine_new_channel(&cc, &cos)));
    cc.freq_hz = 1000;
    e = dac_cosine_new_channel(&cc, &cos);
    printf("dac_cosine 1000 Гц: %s\n", esp_err_to_name(e));
    if (e == ESP_OK) dac_cosine_del_channel(cos);
    ESP_LOGI(TAG, "done");
}

Дальше: раздел 155 — хранение: NVS, SPIFFS, FAT, таблица разделов.

Открыть в интерактивном справочнике