Основы ESP32: Аналого-цифровой преобразователь (АЦП)

Основы ESP32: Аналого-цифровой преобразователь (АЦП)

Эта статья из нашей серии «Основы ESP32» демонстрирует, как считывать аналоговые значения с помощью ESP32 в Arduino IDE.

Это полезно для считывания данных с самых разных датчиков и переменных компонентов, включая, помимо прочего, подстроечные резисторы, джойстики, ползунки и датчики силы нажатия (FSR).

Выводы АЦП ESP32

ESP32 включает два 12-битных АЦП типа SAR — ADC1 и ADC2 — и поддерживает измерения на 18 каналах (выводы с поддержкой аналогового входа). ADC1 доступен на восьми GPIO (32–39), а ADC2 — на десяти GPIO (0, 2, 4, 12–15 и 25–27).

Однако плата DEVKIT V1 DOIT (версия с 30 GPIO) имеет только 15 каналов АЦП, как показано на рисунке ниже.

Выводы АЦП ESP32

АЦП в вашем ESP32 имеет разрешение 12 бит, что означает, что он может определять 4096 (2^12) дискретных аналоговых уровней. Другими словами, он преобразует входные напряжения в диапазоне от 0 до 3,3 В (рабочее напряжение) в целые числа в диапазоне от 0 до 4095. Это даёт разрешение 3,3 вольта / 4096 единиц, или 0,0008 вольт (0,8 мВ) на единицу.

Кроме того, разрешение АЦП и диапазон канала могут быть настроены программно.

Ограничения АЦП ESP32

Если быть честным, АЦП — не самая сильная сторона ESP32. Существует несколько ограничений, о которых следует знать.

Невозможность использования при включённом WiFi

Выводы ADC2 нельзя использовать, когда включён Wi-Fi. Поскольку велика вероятность использования WiFi на микроконтроллере, предназначенном для этого, фактически можно использовать только ADC1.

Диапазон входного напряжения АЦП

АЦП ESP32 может измерять напряжения только в диапазоне от 0 до 3,3 В. Вы не можете напрямую измерять аналоговое напряжение в диапазоне от 0 до 5 В.

Точность АЦП

В идеале вы ожидаете линейное поведение при использовании АЦП, но это не так. Преобразователи АЦП на ESP32 имеют нелинейную природу. Более подробную информацию об этом можно найти в обсуждении на GitHub.

На графике ниже отчётливо видны нелинейности на нижнем и верхнем концах диапазона входного напряжения.

Нелинейность АЦП ESP32

По сути, это означает, что ESP32 не может отличить 3,2 В от 3,3 В; измеренное значение будет одинаковым (4095). Точно так же он не может различить сигналы 0 В и 0,13 В; измеренное значение будет одинаковым (0).

Электрический шум

Электрический шум АЦП подразумевает небольшие колебания измерений.

Электрический шум АЦП ESP32

Однако это можно скорректировать, добавив конденсатор на выходе и применив передискретизацию (oversampling).

Функция analogRead()

Считывание аналоговых значений с вывода GPIO выполняется просто. В Arduino IDE для этого используется функция analogRead(), которая принимает в качестве аргумента номер GPIO-вывода, который вы хотите прочитать.

analogRead(GPIO);

Считывание потенциометра

Чтобы продемонстрировать использование АЦП на ESP32, мы воспользуемся простым примером — считыванием аналогового значения с потенциометра.

Подключение оборудования

Давайте соберём простую схему с потенциометром для этого примера.

Начните с установки потенциометра на макетную плату. Подключите средний вывод к GPIO 34 на вашем ESP32. Наконец, подключите один из крайних выводов потенциометра — неважно какой — к выводу 3V3 ESP32, а другой — к земле (GND).

Подключение потенциометра к АЦП ESP32

Пример кода

Загрузите следующий скетч на ваш ESP32. Этот скетч просто считывает значение потенциометра и выводит результаты в монитор последовательного порта.

// Potentiometer is connected to GPIO 34 (Analog ADC1_CH6)
const int potPin = 34;

// variable for storing the potentiometer value
int potValue = 0;

void setup() {
  Serial.begin(115200);
  delay(1000);
}

void loop() {
  // Reading potentiometer value
  potValue = analogRead(potPin);
  Serial.print("Analog value: ");
  Serial.println(potValue);
  delay(500);
}

После загрузки скетча откройте монитор последовательного порта со скоростью 115200 бод и нажмите кнопку EN на ESP32.

Вы должны увидеть значение от 0 до 4095, зависящее от текущего положения ручки потенциометра, выводимое в монитор последовательного порта. Попробуйте повернуть ручку потенциометра, чтобы увидеть, как меняются значения.

Вывод АЦП ESP32

Объяснение кода

Скетч начинается с определения GPIO-вывода, к которому подключён потенциометр, — в данном случае это GPIO 34.

const int potPin = 34;

Также определяется переменная для хранения значений потенциометра.

int potValue = 0;

В функции setup() мы инициализируем последовательную связь с ПК.

Serial.begin(115200);

В цикле loop() функция analogRead() используется для считывания напряжения на выводе potPin. Возвращённое значение сохраняется в переменной potValue.

potValue = analogRead(potPin);

Наконец, значения, считанные с потенциометра, выводятся в монитор последовательного порта.

Serial.print("Analog value: ");
Serial.println(potValue);

Примечание

potPin не нужно устанавливать как вход. Это делается автоматически каждый раз, когда вы вызываете analogRead().

Другие функции АЦП

Существуют и другие функции АЦП, которые могут быть полезны в других проектах:

  • analogReadMilliVolts(pin): получает значение АЦП для заданного вывода/канала АЦП в милливольтах.

  • analogReadResolution(bits): устанавливает разрядность и разрешение считывания. По умолчанию — 12 бит. Диапазон: от 9 (0–511) до 12 бит (0–4095).

  • analogSetWidth(bits): устанавливает аппаратную разрядность и разрешение считывания. По умолчанию — 12 бит. Диапазон: от 9 до 12 бит. 9 бит = 0–511, 10 бит = 0–1023, 11 бит = 0–2047 и 12 бит = 0–4095.

  • analogSetCycles(cycles): устанавливает количество циклов на выборку. По умолчанию — 8. Диапазон: от 1 до 255.

  • analogSetSamples(samples): устанавливает количество выборок в диапазоне. По умолчанию — 1 выборка. Увеличение количества повышает чувствительность.

  • analogSetClockDiv(clockDiv): устанавливает делитель тактовой частоты АЦП. По умолчанию — 1. Диапазон: от 1 до 255.

  • analogSetAttenuation(attenuation): устанавливает входное ослабление для всех выводов АЦП. По умолчанию — ADC_11db. Допустимые значения:

    • ADC_0db: без ослабления (диапазон измеряемого входного напряжения = 100 мВ ~ 950 мВ).

    • ADC_2_5db: ослабление 1,34 (диапазон измеряемого входного напряжения = 100 мВ ~ 1250 мВ).

    • ADC_6db: ослабление 1,5 (диапазон измеряемого входного напряжения = 150 мВ ~ 1750 мВ).

    • ADC_11db: ослабление 3,6 (диапазон измеряемого входного напряжения = 150 мВ ~ 2450 мВ).

  • analogSetPinAttenuation(pin, attenuation): эта функция аналогична предыдущей, за исключением того, что устанавливает входное ослабление для указанного вывода.

  • adcAttachPin(pin): подключает вывод к АЦП (а также очищает любой другой аналоговый режим, который может быть активен) и возвращает true в случае успешной настройки, иначе возвращает false.

  • adcStart(pin): запускает преобразование АЦП на шине подключённого вывода.

  • adcBusy(pin): проверяет, выполняется ли в данный момент преобразование на шине АЦП вывода (возвращает TRUE или FALSE).

  • resultadcEnd(pin): получает результат преобразования (ожидает, если АЦП ещё не завершил работу), возвращает 16-битное целое число.

Более подробную информацию можно найти на readthedocs.