Наш магазин на eBay Наш магазин на AliExpress Наш канал в telegram

Измерение аналоговых величин микроконтроллером, на практике. Часть 2

Вольт-амперметр

О измерении силы тока я рассказывал в предыдущей части, поэтому уделять особого внимания этой теме здесь не буду.

Сделал я себе так называемый лабораторный источник питания на базе схемы из форума Microsmart.eu с некоторыми изменениями:

Схема лабораторного источника питания

Второй ОУ (на схеме IC2A), в отличии от оригинальной схемы, используется здесь в качестве нормирующего усилителя сигнала шунта RS1/RS2. Я думаю, стоит заострить на нём ваше внимание, поскольку в приведённом примере компенсация недостатков микросхемы ОУ реализована по-другому. В частности, из-за отсутствия вспомогательного источника отрицательного напряжения, я применил на выходе ОУ эмиттерный повторитель, роль которого в данном случае не усиление по току, а именно сдвиг потенциала на ~0,6 Вольта вниз. Тем самым, для получения на эмиттере нуля Вольт, ОУ будет регулировать на своём выходе +0,6 Вольта, что явно входит в диапазон возможностей этой МС.

Я думаю, что можно было бы обойтись и просто диодом с выхода ОУ к точке соединения R13 и R8, тем самым обеспечив этот сдвиг.

Удивление читателя, возможно, вызовут номиналы цепи ОС. В оправдание скажу: подстроечники из радиохлама, поэтому остальные резисторы высчитаны соответственно.

Вернёмся же к измерению выходного напряжения. На фото представлен подопытный БП в обвязке необходимых приборов. Справа от БП находится уже знакомая вам «электронная нагрузка».

Фото подопытного блока питания

В приведённой выше схеме нормирующим узлом для измерения напряжения служит делитель на элементах R3, R14 и R17. Номиналы резисторов подобраны так, чтобы при напряжении на выходе БП в 32 Вольта, — на на аналоговом входе МК были знакомые из прошлой части 2,86 Вольта. Да, оба МК из одной партии! Конечно же я предусмотрел подстройку этого делителя, чтобы компенсировать погрешности резисторов.

Всё было бы в порядке, если бы я опять не совершил ошибку! Дело в том, что схема измерения выходного напряжения мною не была доработана: шунт хоть и имеет низкое сопротивление (0,05 Ом), но всё же создаёт падение напряжения на выходе. По-хорошему, минусовой провод делителя, с которого снимается сигнал для измерения выходного напряжения (R17/R3,R14), нужно было подключить после шунта (к V-, а не к GND). Но понял я это поздно, а переделывать схему и печатную плату уже не захотел. Собственно, это незначительное падение напряжения само по себе не страшно и максимально составит 125 мВ. Но встроенный вольтметр ведь об этом не знает — он же меряет напряжение до шунта! Поэтому при изменении тока нагрузки он не будет показывать реального напряжения на выходе БП.

Поскольку «поезд ушел» пришлось компенсировать этот недостаток с помощью арифметики в программе МК. И это оказалось довольно просто, поскольку МК получает на своем «токовом» входе именно это падение напряжения, помноженное на известный коэффициент. Результат этой компенсации демонстрирует следующий снимок:

компенсация падения напряжения на шунте с помощью арифметики МК

Тут же заметна некоторая неточность показаний втроенного вольтамперметра. Однако при пересчете несоответствия увидим, что погрешность эта совсем невелика и составляет примерно 2% для амперметра. Вот вам яркий пример для предисловия в первой части статьи: на стрелочнике эти 2% были бы практически незаметны, а на цифровом индикаторе сразу же бросаются в глаза!

Преобразование

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

Что значит «удобный»? Это значит, что этот коэффициент имеет значение какой-то степени двойки, что даст возможность умножать и делить с помощью битовых сдвигов, которые выполняются очень быстро. На самом деле в приведенном примере МК работает даже слишком быстро, хоть и тактируется от настроенного на заводе внутреннего генератора на частоту 1 МГц, поэтому можно было применить и более сложную арифметику вплоть до плавающей десятичной точки.

Я не стал изменять эти настройки, просто вставил некоторые програмные задержки, благо ничего критичного программе выполнять не нужно. Даже регенерация ЖКИ выполняется специализированными контроллерами HC7211, спасенными вместе со стекляхами из радиохлама. А главное – я не стал заморачиваться с поиском готовых функций для вычислений многобайтных переменных. Вся моя арифметика сводится к вычислению целочисленных переменных размером не более 16 бит.

Ну вот, АЦП настроен на подходящую скорость и точность преобразования и запущен в работу с прерываниями по готовности данных. Практически ЦПУ большую часть времени ждет сигнала готовности АЦП, поскольку вычисления делает много быстрее, чем поступают новые данные преобразования. В моих обоих примерах АЦП настроен на 10-битное преобразование.

Я в курсе, что самые младшие разряды даже при очень «чистом» входном сигнале «пляшут», т.е. имеет место погрешность преобразования вызванная не только невысоким качеством самого АЦП, но еще и всяческими шумами самого процессора, питания и других компонентов схемы. Поэтому в программе реализовано усреднение нескольких замеров – своего рода цифровой фильтр НЧ. Для этого в оперативной памяти МК организован массив преобразованных значений, по которым производится усреднение. Поскольку применяемый МК (Tiny26L) не располагает большим ОЗУ, то и размер этих массивов не очень большой. Кстати, в электронной нагрузке необходим всего один массив, поэтому он вдвое больше, чем в вольтамперметре БП.

Из-за ограниченности этих массивов сумма всех 10-битных значений каждого из них не превышает 16368, т.е. укладывается в двухбайтную переменную. Исходя из этого я не стал ограничивать преобразование 8-ю битами, что теоретически снизило бы общую точность измерения, хотя и позволило удвоить размер массива. Т.е. для диапазона измерения в 32 вольта вес одного кванта 8-битного преобразования был бы 0.125 вольта против 0.03125 вольта при 10-битном преобразовании. Оба эти значения являются очень маленькой частью всего диапазона (десятые или даже сотые доли процента), но согласитесь, наблюдать скачкообразное изменение на ЖКИ, например, с 3.12 на 3.24 вольта куда менее приятно, чем изменение с 3.12 на 3.15 вольта.

Алгоритм усреднения довольно прост и известен нам со школьной скамьи: необходимо сложить все значения и поделить полученную сумму на количество этих значений. Поскольку количество значений в примененном мною массиве кратно степени двойки, то и деление, как я уже упоминал выше, сводится к побитному сдвигу переменной вправо. Собственно на этом алгоритме можно было бы и остановиться, поскольку при частоте преобразования АЦП (т.н. частота дискретизации) ок. 5 кГц для каждого из измеряемых входов ЦПУ сможет высчитать среднее значение много раз до появления нового занчения. Однако я выбрал другой алгоритм.

Плавающее окно

Что из себя представляет этот алгоритм? Не вдаваясь во все подробности, выглядит это так: ЦПУ высчитывает после каждого измерения (преобразования АЦП) новую сумму и соответствующее среднее значение последних 16 (в моем случае) замеров. Это похоже на видимую через вагонное окно часть всего, что за ним проносится мимо. Наверное поэтому алгоритм и получил такое название. Для его реализации массивы данных в ОЗУ представлены в виде кольцевого буфера, в котором самое старое значение заменяется самым свежим. Естественно, чем больше размер этого буфера, тем лучше получается фильтрация шумов.

Казалось бы, при этом нагрузка на ЦПУ выросла в 16 раз, поскольку считать сумму и среднее значение приходится после каждого замера. Это не совсем так, поскольку сумму пересчитывать по новому нет необходимости. Достаточно вычесть из имеющейся суммы старое удаляемое значение и прибавить новопоступившее. А вот среднее значение нужно пересчитывать каждый раз. Но, как я уже говорил, это происходит очень быстро – всего за дюжину микросекунд.

Падение напряжения на шунте, измеренное и усредненное в «токовой» ветке программы, учитывается в сумме значений напряжения при каждом новом замере, после чего производится усреднение и нормализация значений для преобразования в десятичное представление и вывод на ЖКИ. Что из себя представляет нормализация покажу на примере измерения напряжения.

Как я уже заметил выше, для упрощения арифметики напряжению 32.736 вольта соответствует числовое значение 1023. Это граница измерения напряжения. Сумма 16-ти замеров этого напряжения имеет значение 16368 единиц. Если сумму умножить на два, то получим «удобное» число 32736. Поставив в нужном месте десятичную точку и отбросив лишние младшие десятичные разряды можно это число (32.7) сразу выводить на ЖКИ. Для этого мне понадобилась функция BIN16_BCD5, складывающая результат в 5 регистров в распакованном виде.

Поскольку объем ОЗУ в этом МК всего лишь 128 байт и значения в буферах приходится хранить в двух байтах, то получить размер буфера в 32 значения (64 байта) без отказа от стека не получится. А усложнять весь алгоритм из-за некратности двум я не хотел. Вернее не сам алгоритм, а его реализацию на ассемблере.

В заключение скажу, что многие идеи и примененные алгоритмы подсмотрены мною в технической литературе, на форумах и публикациях в интернете. Конкретно указывать, что откуда взято, не стану из-за дополнительного раздутия объема.

Я более, чем уверен, что после прочтения у многих останутся вопросы. Готов на них ответить в форуме.

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