Измеритель индуктивности на ESP32

«Когда коту нечего делать,
он обязательно начнет … чем-то меряться!»
(c) unknown

Посетила меня идея собрать себе т.н. «buck converter». В принципе, в эпоху повальных отключений, идея ни капли не оригинальная, и тем не менее…

Любой, кто хоть раз видел схему подобного преобразователя, в курсе, что там используется катушка индуктивности. И расчетов этих катушек — в интернете хоть пруд пруди! И какая у этой катушки д.б. индуктивность, и сколько витков и какого провода для этого нужно намотать на сердечник — все есть! Отсутствовала только лишь маркировка … магнитной проницаемости на тех кольцах (сердечниках), которые валялись у меня в «закромах родины» с «назапамятных времен» 🙁 . Но даже и для таких случаев в интернете имеются рекомендации, которые сводятся к простому действу — намотать на сердечник несколько витков и измерить полученную индуктивность, после чего, исходя из полученного результата — скорректировать число витков. Все просто, ясно и понятно! Не пишут лишь одно — где взять этот самый измеритель индуктивности, если его вдруг не оказалось под рукой 🙂 ?!

Имея дома некий «стратегический запас» всяких электронных компонентов, решил я попробовать собрать эту штуку самостоятельно. Причем, хотелось не какой-то там «показометр со стрелкой», а что-то более точное. С учетом того, что, с одной стороны, этому измерителю обязательно нужно будет «что-то вычислять», а с другой стороны, у меня «в закромах родины» валялись без дела несколько модулей ESP32-Devkit, то и схему для повторения я начал искать на базе именно такого модуля:

Модуль ESP32-Devkit1

«Первый блин — комом!»

В числе первых мне попалась схема, опубликованная про ссылке, приведенной ниже (правда, мне пришлось установить Eagle, чтобы увидеть именно схему, «но то такое» 🙂 ):

https://github.com/YordanYanakiev/LC-Fr-Meter-for-ESP32

К повторению данной конструкции меня подтолкнул еще и тот факт, что в ней использовался графический дисплей, похожий на вот такой 1,8-дюймовый, который совершенно случайно валялся у меня в «закромах родины» абсолютно без дела и каких либо дальнейших планов:

Графический ЖК дисплей 1,8 дюйма

Схема была мною взята за основу и повторена на «макетке», с той лишь разницей, что дисплей был переподключен на «стандартные» выходы шины SPI процессора ESP32. Но, справедливости ради, нужно сказать, что этот факт абсолютно никак не повлиял на работу устройства. Единственное, что это дало лично мне — избавило от нескольких строк в исходном коде, в которых ранее было указано, на какие пины были перенесены сигналы MOSI, SCK и SS процессора. В моем случае дисплей оказался подключен к процессору следующим образом:

Вывод дисплея Вывод ESP32
LED выход 3,3 Вольта
SCK GPIO18 (VSPI_SCK)
SDA GPIO23 (VSPI_MOSI)
A0 / DC GPIO17
RESET GPIO16
CS GPIO5 (VSPI_SS)
GND GND
VCC выход 3,3 Вольта

Несколько слов по самой схеме и принципу работы прибора. Фактически он представляет собой LC-контур с т.н. «ударным возбуждением», одним из компонентов которого как раз и является измеряемая катушка индуктивности. Процессор подает на контур короткие импульсы напряжения (те самые «удары для возбуждения» 🙂 ), в результате чего в нем возникают свободные колебания на резонансной частоте.  Сигнал с контура подается на вход компаратора, который слабые колебания контура усиливает до уровней логических нолей и единиц, чтобы они стали достаточными для восприятия цифровыми входами процессора. Процессор измеряет частоту колебаний и затем вычисляет значение индуктивности (т.к. значение установленной в контуре емкости известно заранее, и жестко вписано в код программы). Результат вычислений выводится на дисплей. Все четко, просто и понятно. (Причем, разновидностей этой схемы в интернете было найдено мной немало, и наиболее радикальным отличием было использование других типов дисплеев, чаще всего — «символьных» ЖКИ с организацией «2 строки Х 16 символов», как это сделано, например, тут).

Прибор заработал «с пол-пинка» и я им был доволен ровно первые несколько минут. После чего закралось сомнение в том, а насколько правдивы те показания, которые я вижу на экране? И подтолкнула меня к этому вопросу явно заметная ДИСКРЕТНОСТЬ отображаемых величин. Был прочитан код управляющей программы на предмет того, как именно выполняется измерение частоты. Оказалось, что для этого используется функция pulseIn() от Arduino. С ее помощью процессор измеряет длительность одного импульса колебаний, возникших в контуре! И все бы ничего, если бы не то обстоятельство, что свой результат измерений продолжительности импульса функция pulseIn() выдает в виде именно ЦЕЛОГО ЧИСЛА МИКРОСЕКУНД (без каких-либо дробных значений!!!). На скорую руку я создал в Excel лист, в котором рассчитал возможные результаты измерений индуктивности в зависимости от длительности импульса (в диапазоне от 1 до 30 мксек). Результат оказался подтверждением моих сомнений:

Левый столбец цифр — это длительность импульса в микросекундах, а в правом — вычисленная индуктивность катушки в мкГн (с учетом того, что мной в контуре был использован конденсатор емкостью 213 нФ). То есть, чтоб было совсем уж понятно — мой прибор показывал бы ТОЛЬКО ТЕ ЗНАЧЕНИЯ индуктивности, которые присутствуют в правом столбце! Промежуточных значений между приведенными в нем цифрами для него ПРОСТО НЕ СУЩЕСТВОВАЛО БЫ! Например, катушку в 15 мкГн прибор отображал бы либо как 17,12 мкГн, либо как 11,89 мкГн (в зависимости от того, куда и насколько «промазал» ее изготовитель).

В итоге я решил, что так не пойдет, и надо искать иные варианты! Точнее сказать, «вариантов» этих было совсем не много, аж целый один — сделать измеряемый контур таким, который задает частоту генерации для «обычного» генератора и затем просто измерять эту частоту.

Окончательный вариант

После этого был проведен поиск схемы генератора, частота колебаний которого задается LC-контуром. При этом, в фоновом режиме приходилось учитывать тот факт, что сигнал данного генератора должен быть подан на цифровой вход процессора (который собственно и будет подсчитывать частоту колебаний)! В итоге, попалась на глаза схема генератора, использованная вот в этом проекте:

https://www.sites.google.com/site/vk3bhr/home/lcm1

Как показали дальнейшие поиски, идея данного генератора была клонирована много раз, многими людьми в множестве других проектов (например тут)! На основании этого факта был сделан вывод — «раз у других оно 100500 раз получилось, то и у тебя тоже должно получиться». А в добавок, еще и изменения в схеме получались минимальными по сравнению с (уже спаянным мною ранее) «прибором с ударным возбуждением» 🙂 .

Что ж, паяю я быстро, и поэтому, уже в скором времени наблюдал сигнал обновленного генератора на экране осцилографа. Не могу сказать, что он мне сильно понравился, равно как и «частотомеру», который был уже прошит в процессор. Генерация была не стабильной, с лишним «мусором» помимо основного сигнала. Сравнивая со схемами упоминавшихся 100500 примеров, я подумал, а может дело в питании? Суть данного предположения заключалась в том, что использованный мною процессор ESP32 — «3-х вольтовый» (точнее, использует напряжение питания 3,3 Вольта, и как следствие — цифровые входы с таким же максимально допустимым уровнем единицы»). По этому, в моем случае резистор «подтяжки» ОК-выхода компаратора я подключал к выходу встроенного в модуль стабилизатора напряжения 3,3 Вольта, в то время как для питания самого компаратора использовались «обычные» 5 Вольт.

Пришлось снова лезть в свои «закрома родины» и искать альтернативу компаратору. «Закрома» не подвели — в них завалялся (спаренный) операционник AD812. PDF-ник гордо вещал, что это «супер-пупер классный низковольтный видео-усилитель, оптимизированный  для работы непосредственно на видео-кабель», ну и так далее, и тому подобное…  Увидев в описании возможность работы чипа при питающем напряжении от 3 Вольт, я смело водрузил его в свой прибор. А так как в одном корпусе было сразу два операционника, то второй был задействован как дополнительный компаратор, на один вход которого подавался сигнал с генератора, а на второй — смещение с подстроечного резистора (устанавливающее «порог» компаратора), вращая который я рассчитывал дополнительно побороться «за чистоту сигнала»!

То есть, теперь у меня сам генератор был тоже подключен к цепи питания 3,3 Вольта, а в добавок ко всему, ему еще и подтягивающий резистор был не нужен! Генерация с использованием AD812 стала стабильной, «мусор» на выходе тоже пропал. Из найденных в интернете схем дополнительно был почерпнут переключатель измерительного входа, благодаря чему (а также добавлению соответствующего кода в прошивку) у прибора появилась возможность измерения и емкости тоже. Итоговая схема стала выглядеть вот таким образом:

принципиальная схема прибора

Что мы тут видим? На операционном усилителе U2a собран генератор с измерительным контуром.  Измеряемый компонент подключается к гнезду XS1. В зависимости от состояния реле RE1, он может быть подключен либо последовательно с индуктивностью L1 («режим изменения индуктивности»; суммарная индуктивность контура будет равна L1 + Lx), либо параллельно конденсатору C1 («режим измерения емкости»; суммарная емкость контура будет равна C1 + Cx). Сигнал с выхода генератора через компаратор U2b подается на один из входов ESP32. Программа процессора измеряет частоту поступающего на вход сигнала и из нее вычисляет значение параметра измеряемого компонента.

Исходные компоненты измерительного контура (конденсатор C1 и индуктивность L1) непосредственно влияют на точность измерений. Так как найти конденсатор с высокой точностью (малым допуском) намного проще, чем индуктивность, было решено считать емкость C1 «непогрешимой», а  индуктивность L1 — просто измерять! Для этого в программу была добавлена возможность «калибровки прибора». Для этого нужно отключить любые измеряемые компоненты от входа XS1 и нажать кнопку S1 («Калибровка»). Прибор измерит частоту колебаний генератора без дополнительных компонентов (в контуре будут включены только C1 и L1) после чего рассчитает значение индуктивности L1 и сохранит его в памяти. Как вы, надеюсь, уже поняли, при повторении устройства вам нужно будет максимально точно измерить емкость конденсатора C1 (каким-то иным измерительным прибором), а потом вписать полученное значение в исходный код программы! В коде за это отвечает строка:

double ref_capacitance = 1E-9;

Выбор того, что именно будет измерять прибор (индуктивность или емкость), осуществляется кнопкой S2 («L/C»). При каждом ее нажатии происходит переключение режима на противоположный. Защита от дребезга контактов в программе реализована самая примитивная — после обнаружения факта нажатия кнопки, ее обработка блокируется на 3 секунды. Сразу после включения прибор находится в режиме измерения индуктивности. Какой-либо «специальной» индикации выбранного режима измерений нет — понять, что именно сейчас пытается измерять прибор, можно по единицам измерения, выводимым на экране (Генри или Фарады).

Несмотря на то, что реальную индуктивность катушки L1 прибор измеряет в ходе «калибровки», в исходном коде программы предусмотрена возможность вписать для нее какое-то «базовое» значение. Это сделано потому, что индуктивность катушки L1, измеренную во время «калибровки», процессор потом хранит в ОЗУ, и она сбрасывается при каждом выключении питания прибора. Вы можете провести несколько «калибровок», сохранить полученное значение вашей индуктивности и затем вписать его в исходный код программы в строку:

double ref_inductance = 79.5E-6;

В дальнейшем, это значение прибор будет использовать при каждом включении до момента проведения непосредственно процедуры «калибровки».

Ну и последнее, что считаю нужным сказать. В процессоре ESP32 есть встроенный WiFi-модуль, и он был задействован в программе прибора. Прибор запускает свою собственную точку доступа, и при подключении к ней перебрасывает на страницу OTA («обновление прошивки по воздуху»). И сама точка доступа, и страница обновления прошивки запаролены! Значения, используемые для авторизации, указаны прямо в исходном коде прошивки. Параметры точки доступа:

String ap_ssid = "L-Meter"; // имя беспроводной сети, вещаемое точкой доступа
String ap_password = "12345678"; // пароль для подключения к точке доступа

Параметры страницы обновления прошивки:

const char* ota_username = "firmware"; // имя пользователя для беспроводного обновления прошивки
const char* ota_password = "firmware"; // пароль для беспроводного обновления прошивки

Можете оставить эти значения, можете указать свои собственные, решайте сами…

Вот и все. Разве что, осталось добавить вот это:

ИСХОДНЫЙ КОД ПРОГРАММЫ

Ну и пару картинок на прощанье (а как же без них?).

Раз:

Два:

Три:

Четыре:

ps. Уж не знаю, что там в итоге вышло с точностью (ну нет у меня другого прибора, меряющего индуктивность!), но это однозначно лучше, чем тот список из пары-тройки возможных значений (для «ударного контура»), который был приведен мной выше…

Обновление от февраля 2024

Управляющая программа была переписана. Изменения были внесены такие:

  1. Использовано прерывание таймера. Зачем — смотрите ниже.
  2. Изменена работа с клавиатурой — по прерыванию таймера считывается состояние кнопок и сравнивается с предыдущим. Если сканкоды совпали несколько раз подряд — кнопка считается нажатой. Так реализована защита от дребезга.
  3. Библиотека FreqCountESP.h больше не используется. Теперь измерение частоты реализовано «классическим» способом — для входа GPIO_34 настроено прерывание, по которому просто подсчитывается число его срабатываний. После чего, раз в секунду (по «прерыванию таймера») это число срабатываний «прерывания по входу» переносится в текущее значение измеренной частоты. Проще говоря, программа просто подсчитывает число импульсов, поступивших на вход GPIO_34 в течение одной секунды.

Увы, но третий пункт повлек за собой необходимость внесения изменения в схему прибора! Дело в том, что при таком «тупом» методе измерения частоты ESP32 не справлялся с частотами выше 200 кГц. Поэтому, пришлось изменить емкость эталонного конденсатора (C1). Я установил конденсатор емкостью 10 нФ, что, собственно,  теперь и отражается в исходном коде:

double ref_capacitance = 10.185E-9;

Никаких других изменений в аппаратной части больше не выполнялось!

Архив с новой версией исходного кода прошивки вы можете скачать по ссылке:

ИСХОДНЫЙ КОД (версия 2)

Измеритель индуктивности на ESP32: 6 комментариев

  1. C:\Users\���\Documents\Arduino\libraries\FreqCountESP-master\src\FreqCountESP.cpp: In function 'intr_handle_data_t* setupPcnt(uint8_t, volatile uint32_t*)':
    C:\Users\���\Documents\Arduino\libraries\FreqCountESP-master\src\FreqCountESP.cpp:34:17: error: 'PCNT_CHANNEL_EDGE_ACTION_INCREASE' was not declared in this scope
    .pos_mode = PCNT_CHANNEL_EDGE_ACTION_INCREASE,
    ^
    C:\Users\���\Documents\Arduino\libraries\FreqCountESP-master\src\FreqCountESP.cpp:35:17: error: 'PCNT_CHANNEL_EDGE_ACTION_HOLD' was not declared in this scope
    .neg_mode = PCNT_CHANNEL_EDGE_ACTION_HOLD,
    ^
    C:\Users\���\Documents\Arduino\libraries\FreqCountESP-master\src\FreqCountESP.cpp: In function 'void teardownPcnt(pcnt_isr_handle_t)':
    C:\Users\���\Documents\Arduino\libraries\FreqCountESP-master\src\FreqCountESP.cpp:73:32: error: 'pcnt_isr_unregister' was not declared in this scope
    pcnt_isr_unregister(isrHandle);
    ^
    exit status 1

    Ошибка компиляции для платы ESP32 Dev Module.

  2. Дмитрий!!!
    Относительно ударного возбуждения-возникают вопросы.
    Что касается Вашего скетча —

    /* процедура вычисления измеренной индуктивности */
    void calculateL()
    {
    inductance = ( 1. / ( ref_capacitance * sq(frequency) * 4. * sq(M_PI) )) — ref_inductance;
    inductance *= 1E6;
    }
    //Здесь всё законно.
    /* процедура вычисления измеренной емкости */
    void calculateC()
    {
    // а здесь?
    inductance = (1. / ( ref_inductance * sq(frequency) * 4. * sq(M_PI) )) — ref_capacitance;
    inductance *= 1E12;
    }
    Ну, да мы все измерения индуктивностей смотрели.
    Мггу сказать одно-
    Википедия Вам подскажет.
    Сложность заключается в том, что от соотношения L и C- определяется добротность контура.
    Собрал по вашей схеме, ну, не совсем по Вашей, но суть в песок.
    Собрана TL082 с дух сторонним питанием. +8в и -8в. (это для для дальнейшей разработки. На TL082 осциллографы до 20мГц работают .
    Хорошо, что поставил подстроечник в цепи возбуждения.
    Теперь, если частота показывает НУЛЬ-крути потенциометр, пока не возбудится. И снова калибруй.
    Причём, о точности измерений уже говорить не приходится.
    Осциллограф наготове всегда.
    Подклуюив, добиваюсь к синусу, а потом колебрую.
    Не удобно.
    Что касается библиотек «#include «FreqCountESP.h» // установка с сайта github -> https://github.com/kapraran/FreqCountESP
    Дело в том, что последние версии поддерживают систему 64 бит.
    И У многих возникают проблемы.
    Скачал другой, но там тоже хрень какая то.
    Переполнение счётчика pcont задана 32767.на прерывание за 0,1 сек.
    При счёте более 30000 -уже мультиплексирует.
    Не понятно, но здорово.
    В виду того, что наш измеритель LC работает на максимум 500-600 кц поставил Д триггер, что было под рукой с делением на 2.
    И убрал \тот мультипликатор.
    Теперь переполнения не возникает. 32768 за 0,1 сек < чем 600,000 / 2*0,1.
    Вот как-то так.
    А вообще подумываю об изменении RLC с тригонометрией.
    Там образцового(эталонного) ничего не нужно.
    Успехов!!! .

    .

  3. // а здесь?

    а там написано (все что нужно). и если вы не поняли, что там происходит, чтож, скажу — там вычисляется ЕМКОСТЬ, на что косвенно намекает имя функции (капельку отличающееся от той, в которой вас все устроило). 🙂

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *