Найти тему
Электроника, ESP32, Arduino

Зачем для работы с АЦП ESP32 нужна ГЗМ

На борту ESP32 находится два 12-bit АЦП-а, поддерживающих суммарно 18 каналов аналоговых измерений. Классно ведь или нет?

В отличии от 10 битного АЦП Arduino в ESP32 АЦП 12 битный:
В отличии от 10 битного АЦП Arduino в ESP32 АЦП 12 битный:

Будем разбираться по порядку.

АЦП драйвера поддерживает ADC1 (8 каналов — GPIOs 32 — 39), и ADC2 (10 каналов — GPIOs 0, 2, 4, 12 — 15 и 25 — 27). Однако ADC2 имеет определенные ограничения по использованию:

  • ADC2 используется Wi-Fi драйвером, поэтому приложение может использовать ADC2 только когда он не используется.
  • Некоторые пины ADC2 используются также для других целей (GPIO 0, 2, 4, 15) поэтому есть ограничения по их использованию.

У меня плата ESP-WROOM-32 DevKit v1. Выводы ADC1 которые можно использовать без каких-либо ограничений отмечены на схеме фиолетовым цветом (3 колонка с права) - не так уж и много.

ESP-WROOM-32 DevKit v1 pinout
ESP-WROOM-32 DevKit v1 pinout

Необходимо также учитывать, что в ESP32 есть внутренний датчик Холла, данные с которого можно получить с ADC1, вызвав функцию hall_sensor_read(). Хотя датчик Холла внутренний, в ESP32, чтение данных с него задействует каналы 0 и 3 ADC1 (GPIO 36 и 39). Не нужно использовать эти контакты и изменять их конфигурацию в противном случае это может сказаться на измерении сигналов с низким уровнем напряжения, получаемых с датчика (это в том случае, если он конечно вообще нуж0н в конкретном проекте).

Точность измерений определяется в первую очередь, уровнем (Vref) и стабильностью источника опорного напряжения.

Для ESP32 Vref = 1.1V Естественно, что все платы ESP32 имеют некоторый разброс точного значения этого напряжения - однако все платформы ESP32 выпущенные после 2018 года откалиброваны прямо на заводе (значение было измерено и прошито во фьюзы). В папке с примерами к этой статье вы найдете скетч 01_VREF_Fuse, в котором это можно проверить.

Загрузите его в вашу ESP32, откройте монитор порта на скорости 115200 и клацните кнопку перезагрузки:

ADC number: 1
ADC attenuation: ADC_ATTEN_DB_11. The input voltage will be reduced to about 1/3.6
ADC bit width: ADC_WIDTH_BIT_12. ADC capture width is 12Bit
ADC coeff_a: 52126
ADC coeff_b: 142
ADC VRef: 1086
Characterized using eFuse Vref

"Characterized using eFuse Vref" говорит о том, что плата уже откалибрована, и для всех аналоговых измерений будет использоваться именно значение 1086мВ.

Из среды Aduino IDE, можно прокинуть напряжение опорного источника на некоторые выводы (например 27) и померять его вольтметром.

Проброс значения источника опорного напряжения Vref на ножку 27.
Проброс значения источника опорного напряжения Vref на ножку 27.

Подключив к 27 ноге высокоточный (ага, Китайский, ага не поверенный и ага не Ц-шку) вольтметр видим:

-4

что значения совпадают, а посему всю "копипсату" из Интернет про калибровку Vref можно выкинуть ф корзину - производитель уже все померял и сделал за нас.

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

analogSetAttenuation(attenuation);

  • ADC_0db
  • ADC_2_5db
  • ADC_6db
  • ADC_11db

Диапазоны измеряемых напряжений при этом будут составлять:

  • 0dB ослабление (ADC_ATTEN_DB_0) дает диапазон до 1.1V.
  • 2.5dB ослабление (ADC_ATTEN_DB_2_5) дает диапазон до 1.5V.
  • 6dB ослабление (ADC_ATTEN_DB_6) дает диапазон до 2.2V.
  • 11dB ослабление (ADC_ATTEN_DB_11) дает диапазон до 3.3V.

Однако из-за характеристики АЦП наиболее точные результаты измерений получаются в более узком диапазоне, о чем заявлено в документации. На начальном и конечном участке более или менее линейная характеристика АЦП изгибается и становится более пологой, поэтому измерения очень неточные. В документации указаны рекомендуемые диапазоны измерений:

То, что на самом деле можно измерять.
То, что на самом деле можно измерять.

Таким образом первая причина для приобретения ГЗМ - измерять напряжения менее 100mV и более 3200mV ESP32 не умеет в принципе.

Вторая причина - точность измерений при разных уровнях аттенюации.

Стырено отсюда http://microsin.net/programming/arm/esp32-adc.html
Стырено отсюда http://microsin.net/programming/arm/esp32-adc.html

При измерении напряжений от 0.1 до 3.2V приемлемая точность будет до 0,01V. (ага 12 битный говорили они....)

Третья причина приобретения ГЗМ при работе с ESP32 - АЦП не линейный:

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

Из графика понятно, что пересчитать значение полученное с АЦП в вольты по формуле voltage_value = (ADC_VALUE * 3.3 ) / (4095); не получится.

С нелинейностью есть народные методы борьбы. Оперативки в ESP32 пруд пруди. Берем регулируемый источник напряжения (например встроенный в ESP32 ЦАП), подаем с этого источника напряжение с шагом 3,3/4095 и на каждом шагу записываем в массив чему равно значение с АЦП при определенном напряжении. На GitHub есть даже библиотека на эту тему:

GitHub - e-tinkers/esp32-adc-calibrate

после создания набора
значение АЦП <-> значение напряжения на входе АЦП
подгружаем этот набор в оперативную память на этапе загрузки скетча и пользуемся им как эталоном. Главный минус тут - эту процедуру придется делать для каждой новой платы ESP32.

Однако, все не так плохо - для получения значения напряжения в среде Arduino IDE производителем предусмотрена специальная функция:

uint32_t analogReadMilliVolts (uint8_t pin);

её исходный текст можно посмотреть тут (очень многа букаф):

arduino-esp32/esp32-hal-adc.c at 2cb664eeec4b2483b29bed00c5996f0502032d68 · espressif/arduino-esp32

Пример работы можно найти в примерах:

Где искать пример работы с АЦП
Где искать пример работы с АЦП
Пример работы с АЦП ESP32
Пример работы с АЦП ESP32

Для тестирования соберём аналог Китайского вольтметра с ТОЧНОСТЬЮ диапазона 0....20V (0.01V). На вход будем подавать напряжение от 0....3.3V с самодельного ЛБП.

Самодельный Китайский вольтметр
Самодельный Китайский вольтметр

Напряжение подаётся через резистор 10кОм. На входе керамика 0.1мкф.

Если у вас нет дисплея - в папке с примерами к этой статье будет пример для передачи показаний в монитор порта.

Объявление переменных и секция установок
Объявление переменных и секция установок
Код основной программы
Код основной программы

Каждые 50мс производится чтение напряжения на ножке 36 и их суммирование. Каждые 0.5с производится усреднение всех накопленных значений измерений.

Осталось вывести результаты на дисплей и самодельный аналог Китайского вольтметра готов.

Тест вольтметра на ESP32
Тест вольтметра на ESP32
Тест вольтметра на ESP32
Тест вольтметра на ESP32
Тест вольтметра на ESP32
Тест вольтметра на ESP32

Резюме: АЦП в ESP32 полная шляпа имеет некоторые особенности, которые необходимо учитывать при работе с ним. Для передачи в сеть показаний о состоянии батарей, цепей питания или других грубых измерений - подойдет.

Картинка для обложки
Картинка для обложки

Для работы с аналоговыми датчиками, либо придется докупить ГЗМ и довольствоваться некими пороговыми значениями, либо прикрутить внешний АЦП.

ГЗМ можно купить тут:

NOBRAND Губозакаточная машинка — купить по выгодной цене на Яндекс Маркете

Работа с внешним АЦП будет разобрана в одной из следующих статей.

Ссылка на официальную документацию тут.

Примеры кода из статьи тут:

CODE_FINAL_END.zip

Оглавление канала доступно тут:

Всем удачи!