image


Основные тезисы или о чем эта статья


Продолжение серии статей о ShIoTiny — визуально программируемом контроллере на базе чипа ESP8266. Ключевой особенностью данного контроллера является возможность его программирования путем рисования программы в браузере.


В данной статье описана краткая теория аналого-цифрового преобразования и практическое применение АЦП контроллера ShIoTiny.


Предыдущие статьи серии.


ShIoTiny: малая автоматизация, интернет вещей или «за полгода до отпуска»


ShIoTiny: узлы, связи и события или особенности рисования программ


ShIoTiny: вентиляция влажного помещения (проект-пример)


ShIoTiny и окружающий мир: подключение датчиков к бинарным входам, дребезг контактов и другие вопросы


Бинарные прошивки, схема контроллера и документация тут


Вступление или вместо серьезной теории


В предыдущей статье мы рассмотрели подключение основных типов датчиков с бинарным выходом к бинарным входам контроллера ShIoTiny.


Но, как известно большей части людей, а также школьников и студентов, основная часть информации об окружающем мире — это аналоговые величины различной физической природы: сила света и звука, скорость движения, давление воздуха, уровень жидкости и так далее.


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


Для тех, кто еще не знает чем отличается аналоговая величина от дискретной напишу краткие пояснения. Кто уже все и так знает — может их пропустить. Сразу оговорюсь — аналогии и упрощения имеют место быть. Это не диссертация, а скорее краткие объяснения на пальцах.


Аналоговые и дискретные величины (профессорам, академикам и вундеркиндам можно не читать)


Математику в школе изучали все. Поэтому обратимся к ней и проведем аналогии между аналоговыми и дискретными величинами и числами.


С точки зрения математики — аналоговая величина есть число вещественное, определенное в любой точке заданного отрезка числовой прямой.


Дискретная величина с точки зрения математики есть число целое. И определено оно только в определенных точках заданного отрезка числовой прямой.


На рисунке ниже схематично представлено расположение аналоговых и дискретных величин-чисел на числовой прямой.


image


Для примера рассмотрим отрезок числовой прямой от -4 до 3. Как видим, дискретных величин, обозначенных красными точками — целых чисел на нем всего 8 штук. Аналоговых величин, показанных зеленой линией на рисунке — бесконечное множество.


Например, у нас есть некая величина X, имеющая диапазон значений от 0 до 127. Если мы представляем эту величину как аналоговую, то теоретически мы можем представить ее с любой точностью — например 12.123455454980 или 126.00000000007 или вообще с миллионом знаков после запятой.


Но как только в дело вступает микроконтроллер и величина X обретает дискретное представление — то ни о какой «бесконечной точности» и речи идти не может даже теоретически. Точность ограничена числом двоичных разрядов, которое мы отводим под представление величины Х.


Например, мы возьмем 7 двоичных разрядов. В этом случае мы можем представить величину Х с точностью единица. То есть можно будет указать X=1 или X=112. А вот Х=112.5 уже указать не получится — разрядности не хватит. Если мы возьмем для представления той же величины Х не 7, а 10 разрядов, то точность представления будет уже не единица, а 0.125. И в таком виде можно представить Х=95.125 или X=112.5. Но точнее, например в виде X=112.13 — уже представить эту величину нельзя.


Если вас смущает то, что я пишу дробные значения и при этом говорю о них как о целых числах то вспомните, что «дискретные точки» можно расставить на числовой прямой не через единицу, а например через 0.5 или 0.125 единицы. Но их как было, так и останется конечное значение на любом отрезке. И все свойства дискретной величины сохранятся.


Ключевое отличие дискретной величины от аналоговой — это то, что на любом конечном отрезке числовой прямой будет конечное число дискретных (целых) значений и бесконечное число значений аналоговых (вещественных). Соответственно получаем, что дискретное представление величин всегда обладает конечной точностью.


В итоге всего выше сказанного получаем тривиальный вывод. Большая часть измеримых величин реального мира — аналоговые. Микроконтроллеры работают только с дискретными числовыми представлениями величин. Поэтому, прежде, чем обрабатывать какую-нибудь аналоговую величину с помощью микроконтроллера — эту величину необходимо представить в виде дискретной. Да еще и в двоичном виде.


Такое преобразование из аналогового представления в дискретное называется аналого-цифровым преобразованием.


Аналого-цифровой преобразователь


Устройство для преобразования аналогового сигнала в цифровой называется АЦП (аналого-цифровой преобразователь).


Обычно такое устройство имеет один или несколько аналоговых входов, на которые подается аналоговый сигнал и цифровой выход с заданной разрядностью (обычно — от 8 до 16 разрядов).


В современных микроконтроллерах, в том числе и в нашем ESP8266, имеются встроенные блоки АЦП.


Какие характеристики имеют АЦП вообще и АЦП ESP8266 в частности?


Первая характеристика — это какую именно входную аналоговую величину АЦП преобразует в выходной цифровой код. Чаще всего эта величина — напряжение на аналоговом входе АЦП. Так будет и в нашем случае. Но в природе существуют и АЦП с токовым входом.


Вторая характеристика АЦП, которая нужна на практике — это диапазон значений входной величины АЦП. В нашем случае — это минимальное и максимальное значения напряжения на входе АЦП. Эти значения будут и соответственно. Диапазон входных значений кажется небольшим, но большие напряжения всегда можно поделить и уменьшить, а малые напряжения — усилить.


Третья и, пожалуй, самая важная характеристика АЦП это его разрядность. Эта величина определяет точность преобразования или (по нашей аналогии) — как часто расставлены "дискретные" точки на "вещественной" числовой прямой. В нашем случае АЦП имеет разрядность 10. Что это значит? А это значит, что выходной цифровой код представлен 10 двоичными разрядами и имеет 1024 значения — от 0 до 1023.
Строго говоря, стоит помнить, что точность преобразования зависит не только от разрядности, но и от ряда других параметров, например линейности АЦП. Но об этом уже много написано очень умными дядями в очень умных книгах, поэтому в этой статье я оставлю читателя без подробностей.


Кроме того АЦП ESP8266 умеет определять переполнение, то есть ситуацию, когда на вход подано напряжение больше .


Если вы возьмете умный справочник по АЦП и загляните туда — то там будут еще десятки характеристик. Все они нужные и важные, но так далеко мы углубляться не будем. Например, мы не будем касаться в временных параметров АЦП, так как считаем, что в нашем случае измеряемые величины изменяются достаточно медленно и АЦП их преобразует в цифровое представление «мгновенно».


Подведем предварительный итог.
В контроллере ShIoTiny имеется АЦП, встроенный в ESP8266.


На вход АЦП ESP8266 подается напряжение в диапазоне от 0 до .


На выходе АЦП ESP8266 мы получаем число, пропорциональное входному напряжению в диапазоне от 0 до 1023. Напряжению соответствует код 0 на выходе АЦП, напряжению соответствует код 1023 на выходе АЦП.


Считывание данных с АЦП в ShIoTiny производятся со скоростью примерно 10 раз в секунду.


Аппаратно вход АЦП защищен от перенапряжения, аналогично тому, как защищены бинарные входы Input1,2,3 (см. тут).


Вот и все, что касается аппаратного обеспечения АЦП ShIoTiny.


Займемся теперь узлом ADC1, который обрабатывает данные с аппаратного АЦП ESP8266.


Программные навороты или узел ADC1


На схеме-программе в редакторе ElDraw, узел аналого-цифрового преобразователя называется ADC1.



Как уже упоминалось, узел ADC1 примерно 10 раз в секунду получает данные с аппаратного АЦП ESP8266. Но на этом указанный узел не успокаивается, а начинает эти данные обрабатывать и даже чуть-чуть анализировать.


Во-первых, проверяется — а не было ли переполнения АЦП? То есть — а не подали ли на вход АЦП больше ? Если такая ситуация обнаружена — то на выход узла ADC1 выставляется значение NAN (не число).


Во-вторых, если не было переполнения, то выходное значение АЦП 0..1023 преобразуется в величину напряжения на входе АЦП $u_{вх}$ — число с плавающей точкой в диапазоне 0..1.


В-третьих, это преобразованное значение 0..1 пересчитывается по формуле $X=k \cdot u_{вх} +b$, где $u_{вх}$ — напряжение на входе АЦП (от 0 до ); k — диапазон (ADC range) и b — смещение (ADC offset). И, наконец, полученное значение X выставляется на выход узла ADC1.


И, наконец в пятых. Если значение величины Х изменилось на заданный процент (от 1 до 100%), то узел АЦП генерирует события, вызывая пересчет значений подключенных к нему узлов. Это по сути параметр «чувствительности АЦП» (ADC changes, range %). Ведь обычно нет смысла реагировать «на каждый чих», то есть на мизерные изменения в младших разрядах АЦП — они часто «шумят». Поэтому параметр чувствительности имеет большое практическое значение.


Встает законный вопрос — как нам настроить эти параметры? Ткните указателем мыши в узел ADC1 на схеме и тут же у вас появится окно настройки.


В нем можете выставить все, что вам нужно. Для нашего случая это будет такое окно, как на рисунке.


image


В этом окне можно задать все параметры, о которых говорилось выше — диапазон, смещение и чувствительность АЦП.


Если вы ничего не задали, то диапазон будет равен 1. Смещение — ноль. И чувствительность — 1%.


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


Как видим, узел ADC1 довольно сложен. Зачем все это сделано? Да для вас, дорогие мои пользователи! Шучу, конечно, как злобный эгоист я учел предыдущий опыт и постарался облегчить себе жизнь.


Нам, как простым инженерам, хочется чтобы величины были представлены не в «попугаях», а в нормальных и понятных значениях — вольтах, амперах, килограммах или метрах.


Многие датчики выдают значение именно «в попугаях», надеясь на то, что умный микроконтроллер пересчитает их в нужные величины.


Именно для этого и был введен пересчет измеренного АЦП значения по функции заданной.


Но, как водится, лучше один раз увидеть, чем десять раз услышать. Так же как лучше один раз попробовать, чем десять раз увидеть… Но не о том речь.
Потому приведу пару не сложных примеров: систему контроля питающей сети и систему измерения температуры на основе датчика с токовым выходом 4-20мА.


Контроль питающей сети


Измерение напряжения — часто возникающая задача. Например, мы хотим измерить напряжение питающей сети ~220В. Если у нас плохо с электросетью — задача очень реальная. Нам не нужно очень-очень точного изменения. Достаточно чтобы при превышении напряжения на 15% от нормы на ShIoTiny срабатывало реле Relay1, а при понижении напряжения на 15% от нормы срабатывало реле Relay2.


Разумеется, воткнуть вход ADC1 контролера ShIoTIny в розетку мы не можем. Что делать? Во-первых напряжение надо понизить до приемлемого уровня — 0..1В. И, во-вторых его надо выпрямить: переменное напряжение наш АЦП измерить не может.


Напряжение в сети может быть как ниже нормы, так и выше нормы. Для простоты положим, что 220В сетевого напряжения будет соответствовать 0.5В напряжения на входе АЦП.


Далее — ищем любой понижающий трансформатор, который при ~220В входного напряжения выдаст нам, скажем ~3В выходного напряжения и собираем такую схему, как на рисунке ниже.



Тут несведущего в электронике может поджидать сюрприз. На выходе выпрямителя неожиданно появляется не постоянного напряжения, а какие-то с лишним! На самом деле все просто объясняется. Когда мы измеряем переменное напряжение, то вольтметр показывает нам действующее значение напряжения. А когда мы это напряжение выпрямляем — то на выходе выпрямителя получаем пиковое значение напряжения, которое для синусоидального сигнала примерно в 1.41, а точно в $\sqrt 2$ раз больше действующего. Отсюда и "непонятные" 4.23В на выходе выпрямителя.


Ну и наконец, нам надо рассчитать делитель напряжения, то есть сопротивления R1 и R2. Нам необходимо получить на выходе делителя 0.5В при напряжении на его входе 4.23В. Значит выпрямленное напряжение 4.23В надо поделить в 8.46 раз. Для этого надо установить резистор R2=100 Ом, а резистор R1=746 Ом. Но это в идеале. Реально резисторов сопротивлением 746 Ом не бывает. Да и трансформаторы особой точностью не отличаются. Поэтому, если кто рискнет попробовать это решение, я настоятельно советую поставить резистор R1=760 Ом, а резистор R2 взять подстроечный, сопротивлением 180 Ом или на 220 Ом. Тогда вы сможете, вооружившись вольтметром, отрегулировать R2 так, что при ~220В напряжения на первичной обмотке трансформатор, на выходе делителя (или, что то же самое, на входе ADC1) будет =0.5В.


Мы измеряем напряжение не просто так, а чтобы по его превышению или понижению от нормы что-то делать. Например, включать резервное питание, чтобы какое-то устройство не сгорело и не отключилось.


Поэтому нарисуем простейшую схему-программу, которая при превышении напряжения на 15% от нормы заставляет срабатывать реле Relay1, а при понижении напряжения на 15% от нормы заставляет срабатывать реле Relay2. Кроме того, повышенное или пониженное напряжение должны продержаться в сети не менее 1 минуты, чтобы вызвать срабатывание реле. Этим мы избежим ложных срабатываний при коротких пиках напряжения, которые часто возникают в сети. Схема-программа, реализующая нашу задумку, показана на рисунке.


image


Чтобы эта схема работала, надо в настройках параметров АЦП выставить коэффициент k (диапазон) равный 440, как показано на рисунке.


image


При коэффициенте 440 и напряжении напряжении на входе АЦП 0.5В на выходе узла ADC1 будет значение 220. То есть реальное сетевое напряжение!


Это очень удобно, потому что позволяет задать константы сразу в вольтах: 220В+15% это 253В и 220В-15% это 187В. При необходимости эти значения можно легко изменить, не тратя время на расчет и перевод напряжения в «попугаи».


Датчик температуры 4-20мА


Датчики, имеющие токовый выход 4-20мА очень распространены в промышленности. В быту их встретишь не часто. Но тем не менее у кого-то они есть и этот кто-то хочет приспособить их к делу.


АЦП позволяет использовать такие датчики совместно с контролером ShIoTiny.


Почему выход датчика токовый и именно 4-20мА? Поясню.


Токовые выходы хорошо работают на длинных линиях. Скажем километр. Им плевать на сопротивление проводов: ток одинаков по всей длине провода вне зависимости от сопротивления проводников.


Начальное значение тока 4мА, а не просто отсутствие тока позволяет легко обнаружить обрыв провода. Если датчик целый и провод не оборван — то ток всегда есть. Хотя бы 4мА. А если оборвался провод — тока нет (0мА).


Предположим, у нас есть датчик температуры с токовым выходом 4-20мА и диапазоном измеряемой температуры от -40С до +125С. Мы хотим его подключить к ShIoTinу. Первое, что нам нужно сделать — это преобразовать ток в напряжение. Идеальным средством для такого преобразования является обычный резистор.


Так как максимальное напряжение на входе АЦП , а максимальный ток в линии — 20мА, то несложно посчитать, что резистор, преобразующий 20мА в будет иметь сопротивление 50 Ом. (Не знаешь закон Ома — сиди дома!).


Мы подключим наш датчик так, как показано на рисунке.


image


Датчик является генератором тока, пропорционального измеренной температуре. При сопротивлении 50 Ом, подключенном параллельно входу ADC1, на входе АЦП будут следующие значения напряжения, в зависимости от тока, создаваемого в цепи датчика:


  • ток менее 4мА, напряжение на входе АЦП менее 0.2В — обрыв линии;
  • ток от 4мА до 20мА, напряжение от 0.2В до 1В — датчик исправен;
  • ток больше 20мА, напряжение на входе больше 1В — датчик неисправен. При коротком замыкании в датчике возможно выгорание резистора 50 Ом, если он менее 2Вт мощностью.

Предположим, мы хотим измерить температуру и опубликовать ее по MQTT. Кроме того мы будем публиковать состояние датчика (обрыв линии, КЗ или все в порядке).


Первое, что нам надо сделать — пересчитать значение из «попугаев» в градусы. Зная, что температуре -40С соответствует ток 4мА и напряжение на входе АЦП 0.2В, а температуре +125С соответствует ток 20мА и напряжение на входе АЦП , получаем коэффициенты: k=206.25 и b=-81.25. Вводим эти коэффициенты в окне настройки АЦП, как показано на рисунке.


image


Кто хочет сам проверить правильность расчета k и b — решите сами простейшую систему систему уравнений:


$\begin{cases} 0.2 \cdot k + b = -40 \\ 1 \cdot k + b = 125 \end{cases}$


Ну а схема-программа будет совсем не сложной и приведена на рисунке ниже.


image


В случае, когда все хорошо и датчик температуры 4-20мА исправен — температура публикуется на MQTT сервере под именем /t_sens. Признаки аварии так же публикуются под именами /sens_short и /sens_break. Если все хорошо, то признаки аварии — нулевые.


Если произошел обрыв линии, то значение температуры будет меньше -40С. В этом случае параметр /sens_break на MQTT брокере будет опубликован как единица.


Если произошло КЗ в линии, то значение температуры будет больше +125С. В этом случае у нас на входе АЦП будет напряжение больше и узел АЦП выставит на своем выходе значение NAN (не-число). В этом случае параметр /sens_short на MQTT брокере будет опубликован как единица.


При возникновении любой из аварий сработает реле Relay3, которое может, например, отключить питание датчика.


Получился вполне себе «умный» датчик, который можно вынести, например, за 200 метров от контроллера и измерять температуру.


Заключение


Закончив обзор примеров АЦП на ShIoTiny я понял, что его можно продолжать и продолжать. Но это будет уже на статья, а учебник.


Прошу снисхождения, если кому-то материал показался излишне «детским» и подробным, а кому-то напротив, что-то осталось не ясно.


Как обычно — конструктивная критика и предложения приветствуются. Кроме этого приветствуются замечания и предложения.


Отправлять все это можно как обычно в комментарии или на почту: shiotiny@yandex.ru.


Ссылки


Так как в статье есть масса стороннего материал, который требует пояснения, то без ссылок не обойтись.


Как происходит преобразование аналогового сигнала в цифровой


Аналого-цифровой преобразователь


Аналоговый и цифровой сигнал. Типы сигналов и как это действует


Список параметров напряжения и силы электрического тока


Аналоговые полевые интерфейсы: токовая петля 4-20 мА – от простого к сложному


НАСТРОЙКА ОБЛАЧНОГО УПРАВЛЕНИЯ ESPPOWER ЧЕРЕЗ ИНТЕРНЕТ С ПОМОЩЬЮ ANDROID

Комментарии (17)


  1. Serge78rus
    07.09.2019 11:51
    +1

    Точность АЦП отнюдь не определяется лишь его разрядностью.


    1. shiotiny Автор
      07.09.2019 11:59
      -1

      Согласен. Но я написал, что все «на пальцах и упрощенно».
      Если начать расписывать шумы, погрешности и усреднения всякие — то выйдет очень много и очень скучно и очень непонятно.

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


      1. Serge78rus
        07.09.2019 12:11
        +1

        Это все понятно, но «на пальцах и упрощенно» не должно приводить к принципиальным заблуждениям. Иначе подобные ошибочные представления могут крепко засесть в памяти начинающих и сильно мешать при дальнейшем их развитии.
        К сожалению, заблуждение о том, что разрядность однозначно определяет точность АЦП — довольно распространенное.


        1. shiotiny Автор
          07.09.2019 12:14
          -1

          Сергей, я буду благодарен, если вы предложите что дополнить. Мне нетрудно поправить будет статью дельным материалом.
          Стоит дополнить о линейности? шумах?


          1. Serge78rus
            07.09.2019 12:29
            -1

            При данном уровне изложения и предполагаемой целевой аудитории написанного вполне достаточно. Просто, на Вашем месте, я бы убрал фразы:

            Отсюда можно без труда прикинуть точность измерений:
            Точность преобразования АЦП ESP8266 примерно 0.1%.
            Пожалуйста, не воспринимайте это как придирки, просто действительно наболело. Увы, подобные утверждения не раз слышал от вполне состоявшихся инженеров.


            1. shiotiny Автор
              07.09.2019 12:36

              Сделал.

              Пожалуйста, не воспринимайте это как придирки, просто действительно наболело. Увы, подобные утверждения не раз слышал от вполне состоявшихся инженеров.


              Нисколечко и не воспринимаю. Спасибо.


        1. FDA
          07.09.2019 14:13

          Просто надо различать понятия «точность» и «разрешающая способность». К примеру, при помощи 24-битного сигма-дельта АЦП можно получить разрешение по температуре с обычного термистора в тысячные доли градуса. Но сам термистор при этом имеет погрешность в 3%. То есть около 2-3 градусов. При этом в сигиа-дельта последние разряды обычно не используют. Так, для 24-битного АЦП реально можно брать только старшием 18-19 разрядов. Для АЦП последовательного приближения, которые часто в МК используются, обычно откидывают младший разряд. А вообще измерения это целая наука. Но автор статьи прав в том, что для простых применений этим можно не заморачиваться. С точностью в 3-4 градуса температуру можно измерить копеешным термистором при помощи 10-битного АЦП.


          1. shiotiny Автор
            07.09.2019 14:20

            Вы правы. Различать стоит.
            Но мне кажется, что в примере с термистором это вопрос не к ацп, а к термистору. Или нет?


            Статья то не об ацп как таковом, а о том как работать с по и железом конкретного контроллера.
            На пальцах и упрощенно.


            1. FDA
              07.09.2019 14:33

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

              А к статье у меня лично вопросов нет. Всё хорошо и понятно изложено!


  1. sav13
    07.09.2019 12:06
    +1

    АЦП на ESP8266 просто ужас


    1. shiotiny Автор
      07.09.2019 12:15
      -1

      АЦП на ESP8266 просто ужас


      Вы его готовить не умеете :)
      А если серьёзно — то для контроля питания или освещенности — пойдёт. Для тех применений, что он используется.

      Встроенные АЦП микроконтроллеров вообще имеют много недостатков.


      1. sav13
        09.09.2019 05:53

        АЦП у ESP8266 имеет только внутренний ИОН, крайне нестабильный, сильно зависящий от температуры и от конкретного чипа. Кроме того, имеет место его нелинейность, которая частично лечится калибровкой.
        Использовать его для измерения чего бы то ни было — крайне затруднительно. Ну для контроля освещения на уровне «есть свет»/«нету света» — можно. Контроль батареи с точностью 10-15% наверное тоже можно.
        У «нормальных» микроконтроллеров типа AVR можно подключить внешний ИОН необходимой точности и получить желаемый результат.


        1. shiotiny Автор
          09.09.2019 05:59

          Ну я примерно так, как вы описали его и использую:) Плюс-минус километр. :)

          Кстати, ваши статьи очень мне понравились.


        1. sav13
          09.09.2019 06:00

          Встроенные АЦП микроконтроллеров вообще имеют много недостатков.

          А что, ваша прошивка поддерживает что то кроме этого?


          1. shiotiny Автор
            09.09.2019 07:19

            Dht11/22
            Ds1820 или или.
            Три дискретных входа на сухой контакт и три реле на 220


            Обмен по mqtt и udp multicast


            Да там по ссылкам подробное описание в pdf


    1. shiotiny Автор
      07.09.2019 13:23

      Кстати, а что вы пробовали измерять этим АЦП?
      Поделитесь опытом, если можете, пожалуйста.


      1. sav13
        09.09.2019 05:58

        Из серьезных проектов — датчик EMG (мерит передачу нервных импульсов к мышце) с аналоговым выходом. Получив на выходе неплохой генератор случайных чисел перешел на внешние АЦП MCP3421/MCP3422 с более/менее стабильным результатом
        ESP8266 — вообще одна головная боль: нестабильный WiFi, частые перезагрузки при использовании внешних прерываний, невозможность рулить внутренним WDT, выход из режима сна через заднее место и прочие ужасы.
        ESP32 в этом отношении получше намного.