На кристалле ESP32 MCU интегрировано 2 блока АЦП (ADC), работающих по принципу последовательного приближения (Successive Approximation Register, SAR). Эти два АЦП поддерживают до 18 каналов, которые могут быть направлены на определенные ножки MCU.
Примечание: в этой статье приведен перевод главы, посвященной ADC из документации [1]. Незнакомые термины и сокращения см. в Словарике, в конце статьи.
[Основные возможности ADC]
ADC1: поддерживает 8 каналов (GPIO32 - GPIO39). ADC2: поддерживает 10 каналов (GPIO0, GPIO2, GPIO4, GPIO12 - GPIO15, GOIO25 - GPIO27).
Таблица 1. Характеристики ADC.
Аттенюация
Условия
min
MAX
Ед.
DNL (дифференциальная нелинейность)
Контроллер RTC, ко входу ADC подключен конденсатор 100 нФ, сигнал на входе подается по постоянному току, температура окружающей среды 25°C, блоки Wi-Fi и Bluetooth выключены.
-7
7
LSB(1)
INL (интегральная нелинейность)
-12
12
Частота выборок (sample rate)
Контроллер RTC
-
200
ksps
Контроллер DIG
-
2
Msps
Примечание (1): вес младшего разряда.
Когда аттенюация == 3 (ADC_ATTEN_DB_11), и результат чтения АЦП больше 3000 (напряжение достигло 2450 mV), точность ADC будет хуже, чем представлено в таблице 1.
Чтобы получить лучшие параметры DNL, пользователь может произвести несколько измерений сигнала, пропущенных через входной фильтр, либо вычислить среднее значение от нескольких выборок сигнала.
Диапазон входного напряжения ножек GPIO в домене VDD3P3_RTC должно строго соответствовать уровням напряжения питания (например, от 0 до 3.3V). Иначе будут наблюдаться ошибки измерений, и может ухудшиться производительность чипа.
По умолчанию между разными экземплярами чипа могут быть ±6% различий в результатах чтения АЦП. Библиотеки ESP-IDF предоставляют набор методов калибровки для ADC1. В качестве примера в таблице 2 приведены результаты измерения с использованием коэффициентов калибровки eFuse Vref. Для повышения точности пользователи могут применить другие методы калибровки, предоставленные в ESP-IDF, либо реализовать собственные методы калибровки.
Таблица 2. Результаты калибровки ADC. В столбце "Ошибка" приведено значение отклонения в милливольтах результата измерения от действительного значения.
Аттенюация
Ошибка, mV
ADC_ATTEN_DB_0
±23
ADC_ATTEN_DB_2_5
±30
ADC_ATTEN_DB_6
±40
ADC_ATTEN_DB_11
±60
Ослабление по входу ADC. Входные уровни напряжений оцифровываются по отношению к внутреннему опорному напряжению Vref. Таким образом, диапазон входных измеряемых уровней напряжения составляет от 0V до Vref. На разных экземплярах кристаллов Vref может варьироваться, среднее значение Vref составляет 1.1V. Чтобы можно было преобразовывать входные напряжения, превышающие Vref, уровни на входе должны быть уменьшены. Существует 4 опции уменьшения уровней (attenuation), чем больше ослабление, тем больше может быть уровень измеряемого напряжения на входе АЦП.
Таблица 3. Опции ослабления (аттенюации) уровней на входе АЦП.
Аттенюация
Измеряемый диапазон входных уровней (mV)
ADC_ATTEN_DB_0
100 .. 950
ADC_ATTEN_DB_2_5
100 .. 1250
ADC_ATTEN_DB_6
150 .. 1750
ADC_ATTEN_DB_11
150 .. 2450
Преобразование ADC. Это процесс преобразования уровня сигнала в цифровое значение. Результаты преобразования предоставляются API-функциями драйвера ADC в виде сырых данных. Разрешающая способность ESP32 ADC в режиме Single Read составляет 12 бит. Для преобразования используются функции adc1_get_raw и adc2_get_raw.
Для вычисления реального напряжения на основе сырого результата, предоставленного ADC, можно использовать формулу:
Vout = Dout * Vmax / Dmax (Формула 1)
Здесь Vout это результат измерения напряжения (в милливольтах), Dout сырой цифровой результат преобразования АЦП, Vmax максимальное измеряемое напряжение на входе (см. выше секцию "Ослабление по входу ADC"). Dmax максимальный сырой результат преобразования АЦП (который в режима Single Read и Continuous Read равен 212 - 1 = 4095).
Для плат, у которых есть биты калибровки eFuse ADC, может использоваться функция esp_adc_cal_raw_to_voltage для получения калиброванных результатов преобразования. Это результаты будут реальным напряжением (в mV). Нет необходимости преобразовывать эти данные по формуле 1. Если API-функции калибровки используются на платах, где нет бит калибровки eFuse ADC, будут генерироваться предупреждения, см. секцию "Калибровка ADC".
Дополнительную информацию по использованию АЦП см. в главе "On-Chip Sensors and Analog Signal Processing" технического руководства ESP32 (ESP32 Technical Reference Manual, esp32_technical_reference_manual_en.pdf).
[Ограничения ADC]
Не могут свободно использоваться некоторые ножки ADC2, на которых совмещена функция управления загрузкой (strapping pins GPIO0, GPIO2, GPIO15). Такой случай имеет место на следующих официальных платах разработчика (Development Kits):
ESP32 DevKitC: GPIO0 не может использоваться из-за внешних схем автоматического программирования. ESP-WROVER-KIT: GPIO0, GPIO2, GPIO4 и GPIO15 не могут использоваться, потому что эти ножки используются внешними схемами для разных целей.
Поскольку модуль ADC2 также используется для Wi-Fi, одновременно можно использовать только одну из этих функций. Т. е. функция adc2_get_raw может блокировать выполнение до тех пор, пока не остановится использование Wi-Fi, и наоборот.
[Использование драйвера ADC]
Оба блока ADC поддерживают одиночный режим чтения (Single Read mode), который подойдет для низкочастотных оцифровок сигнала.
Примечание: чтение никуда не подключенных (висящих) входов ADC будут давать случайные результаты.
Single Read. Это режим одиночного чтения АЦП. Перед тем, как можно будет считывать результаты измерений, ADC должно быть сконфигурировано.
● Для ADC1 конфигурируется желаемая точность (precision) и ослабление (attenuation) с помощью вызова функций adc1_config_width и adc1_config_channel_atten. ● ADC2 конфигурируется ослабление с помощью функции adc2_config_channel_atten. Разрядность чтения (width) для ADC2 конфигурируется каждый раз при чтении результата.
Конфигурация ослабления осуществляется для каждого канала отдельно с помощью типов adc1_channel_t и adc2_channel_t, эти значения устанавливаются в качестве параметров для вышеупомянутых функций настройки ослабления.
Результаты преобразования считываются вызовами функций adc1_get_raw и adc2_get_raw. Ширина результата ADC2 должна быть установлена в параметре adc2_get_raw, вместо того, чтобы это настраивать функцией конфигурации.
Пример режима Single Read можно найти в папке peripherals/adc/single_read среди примеров ESP-IDF [4].
С помощью ADC1 также можно считывать внутренний датчик Холла (hall effect sensor) путем вызова специальной функции hall_sensor_read. Обратите внимание, что несмотря на то, чт датчик Холла внутренний для кристалла ESP32, для его чтения используются каналы 0 и 3 ADC1 (GPIO36 и GPIO39). Ничего не подключайте к этим выводам, и не меняйте их конфигурацию, иначе это может повлиять на измерение слабого сигнала от сенсора.
API предоставляет удобный способ конфигурирования ADC1 для чтения из режима ULP [5]. Для этого вызовите функцию adc1_ulp_enable, и затем установите точность (precision) и ослабление (attenuation), как обсуждалось выше.
Есть еще одна специальная функция adc_vref_to_gpio, которая используется для перенаправления внутреннего опорного напряжения Vref на ножку GPIO. Это удобно для калибровки ADC, и обсуждается в секции "Калибровка ADC".
Минимизация шума. ESP32 ADC может быть чувствителен к шуму, что приводит к большим расхождениям между отдельными результатами чтения ADC. В зависимости от сценария использования можно подключить на входную ножку ADC блокирующий конденсатор (например керамический конденсатор на 100 нФ). Кроме того, для уменьшения эффектов от шума может использоваться техника передискретизации и усреднения (multisampling, также см. [6]).
Рис. 1. График, иллюстрирующий уменьшение шума с помощью конденсатора на входе и усреднения 64 выборок.
[Калибровка ADC]
Заголовок esp_adc_cal/include/esp_adc_cal.h представляет API-функции для корректировки ошибок измерения из-за разброса уровня опорного напряжения (Vref) на разных кристаллах ESP32. Источник опорного напряжения был разработан на напряжение 1100 mV, однако в действительности этот уровень может быть в диапазоне от 1000 mV до 1200 mV.
Рис. 2. График, показывающий эффект влияния различного напряжения Vref на результат оцифровки АЦП.
Коррекция результатов чтения ADC с помощью этого API включает в себя один из ADC на определенной аттенюации, с целью получить кривую характеристики (зависимость результат ADC - напряжение), которая учитывает неточность опорного напряжения. Кривая характеристики представляется в форме y = coeff_a * x + coeff_b, и она используется для преобразования сырых результатов чтения ADC в напряжения в mV. Вычисление кривой характеристики основано на значениях калибровки, которые можно сохранить в энергонезависимую память eFuse [9], или они могут быть предоставлены пользователем.
Значения калибровки. Эти значения используются для генерации кривой характеристики ADC, которая учитывает погрешность опорного напряжения каждого конкретного кристалла ESP32. На ESP32 существует 3 источника значений калибровки. Доступность этих значений калибровки зависит от типа чипа/модуля ESP32 и даты его производства.
● Two Point. Это 2 значения (точки калибровки), каждое представляет собой результат чтения ADC для входных уровней 150 mV и 850 mV. Чтобы получить точные результаты калибровки, эти значения должны быть измерены пользователем и прошиты в eFuse BLOCK3. ● eFuse Vref. Это значение представляет реальное значение опорного напряжения ADC. Оно измеряется и прошивается в eFuse BLOCK0 при калибровке на заводе. ● Default Vref. Это опорное напряжение по умолчанию - оценка опорного напряжения ADC, предоставленная пользователем в качестве параметра во время вычисления характеристики. Если значения Two Point или eFuse Vref недоступны, то будет использоваться Default Vref.
Индивидуальное измерение и прошивка eFuse Vref было применено для чипов ESP32-D0WD и ESP32-D0WDQ6, которые произведены начиная с 1 недели 2018 года. Такие чипы можно распознать по кодам даты, которая равна или больше 012018, см. рис. 3. Здесь WW это код недели, YYYY код года изготовления.
Рис. 3. Маркировка чипа ESP32.
Если Вы хотите купить чипы или модули с калибровкой, свяжитесь с дистрибьютором или напрямую с Espressif (sales@espressif.com).
Если Вы не можете проверить код даты (например, когда чип закрыт крышкой модуля), то все еще можете проверить наличие eFuse Vref путем запуска espefuse.py с параметром adc_info. Пример командной строки запуска espefuse.py в среде Linux (замените /dev/ttyUSB0 реальным именем последовательного порта подключенной через USB платы ESP32):
Примечание: как запускать скрипты администрирования на языке Python *.py в операционной системе Windows см. врезку "Как запустить idf.py menuconfig" из статьи [10]. Скрипт espefuse.py и другие скрипты запускаются аналогично.
Чип, у которого есть запрограммированное значение eFuse Vref (в этом примере 1093 mV) покажет следующее сообщение:
ADC VRef calibration: 1093 mV
Другой пример сообщения, когда значение eFuse Vref не запрограммировано:
ADC VRef calibration: None (1100 mV nominal)
Для чипа, у которого есть 2 точки калибровки, сообщение будет выглядеть примерно так:
Типы, используемые в API-функциях ADC, определены в заголовочном файле components/hal/include/hal/adc_types.h.
Таблица 4. Общее описание API-функций ADC.
Функция
Описание
adc_power_on
Разрешает работу блоков ADC.
adc_power_off
Выключает блоки ADC.
adc_power_acquire
Инкрементирует счетчик использования модуля ADC. ADC остается активным и получает питание, пока счетчик больше 0. Вызовите adc_power_release, когда завершили использование ADC.
adc_power_release
Декрементирует счетчик использования модуля ADC. ADC остается активным и получает питание, пока счетчик больше 0. Вызовите эту функцию, когда завершили использование ADC.
adc1_pad_get_io_num
Получение номера ножки GPIO, соответствующей определенному каналу ADC1.
adc1_config_channel_atten
Устанавливает ослабление (attenuation) указанного канала ADC1, и конфигурирует его соответствующий вход GPIO. По умолчанию ослабление установлено 0 dB (ADC_ATTEN_DB_0).
adc1_config_width
Конфигурирует разрядность выборок ADC1. Эта конфигурация затрагивает все каналы ADC1.
adc1_get_raw
Считывает сырой результат преобразования ADC1 указанного канала.
adc_set_data_inv
Установка инверсии данных указанного блока ADC.
adc_set_clk_div
Установка источника тактирования ADC.
adc_set_data_width
Конфигурирует разрядность выборок ADC.
adc1_ulp_enable
Конфигурирует возможность использования ADC1 в режиме ULP.
adc2_pad_get_io_num
Получает номер ножки GPIO для указанного канала ADC2.
adc2_config_channel_atten
Конфигурирует канал ADC2, включая установку аттенюации. По умолчанию ослабление установлено 0 dB (ADC_ATTEN_DB_0).
adc2_get_raw
Считывает сырой результат преобразования ADC2 указанного канала.
adc_vref_to_gpio
Выводит опорное напряжение ADC1 или ADC2 на указанную ножку GPIO.
adc2_vref_to_gpio
Выводит опорное напряжение ADC2 на указанную ножку GPIO.
adc_digi_initialize
Инициализирует Digital ADC.
adc_digi_read_bytes
Считывает байты Digital ADC через DMA.
adc_digi_start
Запускает периферийные устройства Digital ADC и DMA. После этого начнет работать аппаратный опрос АЦП.
adc_digi_stop
Останавливает периферийные устройства Digital ADC и DMA. После этого перестает работать аппаратный опрос АЦП.
adc_digi_deinitialize
Отменяет инициализацию Digital ADC.
adc_digi_controller_configure
Конфигурирует контроллер Digital ADC.
adc_set_i2s_data_source
Устанавливает источник данных I2S.
adc_i2s_mode_init
Инициализирует режим I2S ADC.
esp_adc_cal_check_efuse
Проверяет, прошиты ли значения калибровки ADC в энергонезависимую память eFuse (опорное напряжение Vref или значения Two Point).
esp_adc_cal_characterize
Опрос способа корректировки считываемого значения ADC (characterization).
esp_adc_cal_raw_to_voltage
Преобразует результат чтения ADC в напряжение (единицы mV). Преобразование реализовано на основе характеристик ADC (см. функции esp_adc_cal_check_efuse и esp_adc_cal_characterize).
esp_adc_cal_get_voltage
Выполняет чтение ADC и преобразует результат чтения в милливольты (mV). Эта функция считывает АЦП, затем преобразует сырое считанное значение в mV на основе предоставленных характеристик. Считываемый АЦП также определяется характеристиками.
hall_sensor_read
Считывает значение с датчика Холла.
Полный справочник по API-функциям, макросам и структурам ADC см. в документации [1].
Эта функция используется для получения сырого значения из регистра ADC для указанной ножки/канала ADC. Параметр pin задает вывод порта GPIO.
uint16_tanalogRead (uint8_t pin);
analogReadMillivolts
Эта функция выдает значение в милливольтах на указанной ножке/канале ADC. Параметр pin задает вывод порта GPIO.
uint32_tanalogReadMilliVolts (uint8_t pin);
analogReadResolution
Эта функция используется для установки разрешающей способности возвращаемого значения функции analogRead (разрядности результата в битах).
voidanalogReadResolution (uint8_t bits);
Параметр bits задает разрядность считываемого значения, диапазон значений 1 .. 16. Если функция analogReadResolution не используется, то будет действовать разрядность по умолчанию 12 (диапазон значений 0 .. 4096) для всех чипов, кроме ESP32-S3, у которого по умолчанию 13 бит (диапазон от 0 до 8192). Когда устанавливается другая разрешающая способность, считанные значения будут подвергаться сдвигу для получения указанной разрешающей способности.
Примечание: для ESP32 разрешающая способность в диапазоне 9 .. 12 соответствует аппаратным возможностям ADC, в этом случае считываемое значение берется как есть, без сдвига. Если для разрешающей способности используется другое значение, то результат чтения ADC сдвигается.
analogSetClockDiv
Эта функция используется для установки коэффициента деления тактовой частоты ADC. Параметр clockDiv задает коэффициент деления, диапазон значений 1 .. 255. По умолчанию используется коэффициент деления 1.
voidanalogSetClockDiv (uint8_t clockDiv);
analogSetAttenuation
Эта функция используется для установки коэффициента ослабления (attenuation) для всех каналов ADC.
Входные напряжения могут быть уменьшены перед тем, как попадут на вход ADC. Существует 4 доступные опции ослабления. Чем больше ослабление, тем может быть измерен более высокий уровень входного напряжения.
Диапазоны измеряемых входных напряжений отличаются для каждого чипа, см. таблицу ниже для получения подробной информации.
Аттенюация
Диапазон входных напряжений (mV)
ESP32
ESP32-S2, ESP32-C3
ESP32-S3
ADC_ATTEN_DB_0
100 .. 950
0 .. 750
0 .. 950
ADC_ATTEN_DB_2_5
100 .. 1250
0 .. 1050
0 .. 1250
ADC_ATTEN_DB_6
150 .. 1750
0 .. 1300
0 .. 1750
ADC_ATTEN_DB_11
150 .. 2450
0 .. 2500
0 .. 3100
analogSetPinAttenuation
Эта функция используется для установки ослабления (attenuation) для определенной ножки / канала ADC. Для дополнительной информации см. выше описание функции analogSetAttenuation.
Эта функция используется для подсоединения ножки порта к ADC (она также очистит любой аналоговый режим, который мог быть включен). Функция вернет true, если конфигурация была успешной, иначе вернет false.
Используется для установки аппаратной разрешающей способности ADC. По умолчанию разрядность (разрешающая способность) ADC составляет 12 бит (диапазон считываемых значений 0 .. 4095). Параметр bits устанавливает разрядность в диапазоне 9 .. 12 бит.
voidanalogSetWidth (uint8_t bits);
analogSetVRefPin
Эта функция используется для установки ножки порта, используемой для калибровки ADC, если оно еще не было откалибровано (ножки 25, 26 или 27).
voidanalogSetVRefPin (uint8_t pin);
hallRead
Эта функция используется для получения значения ADC от датчика Холла, подключенного к выводам 36 (SVP) и 39 (SVN).
inthallRead ();
[Пример приложения]
Ниже приведен простой скетч Arduino, демонстрирующий работу с ADC.
voidsetup()
{
// Инициализация последовательного обмена данными на скорости 115200 бит/сек:
Serial.begin(115200);
// Установка разрешающей способности ADC на 12 бит (0 .. 4096):
analogReadResolution(12);
}
voidloop()
{
// Чтение сырого значения на ножке 2:int analogValue = analogRead(2);
Serial.printf("ADC analog value = %d\n", analogValue);
// Чтение значения напряжения в милливольтах на ножке 2:int analogVolts = analogReadMilliVolts(2);
Serial.printf("ADC millivolts value = %d\n", analogVolts);
// Задержка между измерениями для их комфортного чтения// через консоль Serial Monitor:
delay(100);
}
[Словарик]
ADC Analog to Digital Converter, аналого-цифровой преобразователь (АЦП).
DIG DIGital, цифровой. В контексте ADC имеется в виду специальный контроллер для управления АЦП (Digital ADC).