Секретный вольтметр в Arduino — измерение напряжения батареи средствами микроконтроллера. Создание зарядного устройства, управляемого Arduino

06.07.2019

Arduino и добавленная к ней схема заряда могут быть использованы для мониторинга и управления зарядкой никель-металл-гидридных аккумуляторов, например, так:

Законченное устройство

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

Во-первых, важно отметить, что не существует универсального способа зарядки, который подходил бы для всех аккумуляторов. Разные типы аккумуляторов используют разные химические процессы, обеспечивающие их работу. В результате, разные типы аккумуляторов необходимо заряжать по-разному. В этой статье мы не сможем охватить все типы аккумуляторных батарей и методы зарядки. Поэтому для простоты мы сосредоточим внимание на наиболее распространенном типе аккумуляторных батарей размера AA, на никель-металл-гидридных аккумуляторах (NiMH).

Комплектующие

Список комплектующих слева направо:

  • мощный резистор 10 Ом (минимум 5 ватт);
  • резистор 1 МОм;
  • конденсатор 1 мкФ;
  • MOSFET транзистор IRF510;
  • датчик температуры TMP36;
  • источник питания 5 вольт;

Как заряжать NiMH AA аккумуляторы

Увеличение скорости заряда увеличивает риск повреждения аккумулятора.

Существует много способов зарядки NiMH аккумуляторов. Выбор используемого вами метода главным образом зависит от того, как быстро вы хотите зарядить аккумулятор. Скорость заряда измеряется по отношению к емкости батареи. Если ваша батарея обладает емкостью 2500 мАч, и вы заряжаете ее током 2500 мА, то вы заряжаете ее со скоростью 1C. Если вы заряжаете этот же аккумулятор током 250 мА, то вы заряжаете его со скоростью C/10.

Во время быстрой зарядки аккумулятора (со скоростью выше C/10), вам необходимо тщательно контролировать напряжение на батарее и ее температуру, чтобы не перезарядить ее. Это может серьезно повредить аккумулятор. Тем не менее, когда вы заряжаете аккумулятор медленно (со скоростью ниже C/10), у вас гораздо меньше шансов повредить батарею, если случайно перезарядите ее. Поэтому медленные методы зарядки, как правило, считаются более безопасными и помогут вам увеличить срок службы батареи. Поэтому в нашем самодельном зарядном устройстве мы будем использовать скорость заряда C/10.

Цепь заряда

Для данного зарядного устройства основой является схема для управления источником питания с помощью Arduino. Схема питается от источника напряжения 5 вольт, например, от адаптера переменного тока или компьютерного блока питания. Большинство USB портов не подходит для данного проекта из-за ограничений по току. Источник 5В заряжает батарею через мощный резистор 10 Ом и мощный MOSFET транзистор. MOSFET транзистор устанавливает величину тока, протекающего через батарею. Резистор добавлен как простой способ контроля тока. Контроль величины тока выполняется подключением каждого вывода резистора к аналоговым входным выводам Arduino и измерением напряжения с каждой стороны. MOSFET транзистор управляется выходным ШИМ выводом Arduino. Импульсы сигнала широтно-импульсной модуляции сглаживаются до постоянного напряжения фильтром на резисторе 1 МОм и конденсаторе 1 мкФ. Данная схема позволяет Arduino отслеживать и управлять током, протекающим через батарею.


Датчик температуры

Датчик температуры служит для предотвращения перезаряда батареи и обеспечения безопасности.

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

Держатель AA батареи перед и после установки на макетную плату

Код


Код для данного проекта довольно прост. Переменные в начале исходного кода позволяют настроить зарядное устройство путем ввода значений емкости батареи и точного сопротивления мощного резистора. Также добавлены и переменные безопасных порогов. Максимально допустимое напряжение на батарее устанавливается в значение 1,6 вольта. Максимальная температура батареи установлена на 35 градусов по Цельсию. Максимальное время заряда установлено на 13 часов. Если какой-либо из этих порогов безопасности будет превышен, зарядное устройство выключается.

В теле программы вы можете увидеть, что система постоянно измеряет напряжения на выводах мощного резистора. Это используется для расчета значений напряжения на батарее и протекающего через нее тока. Ток сравнивается с целевым значением, которое составляет C/10. Если рассчитанный ток отличается от целевого значения более, чем на 10 мА, система автоматически подстраивает выходное значение, чтобы подкорректировать его.

Arduino использует последовательный интерфейс для отображения всех текущих данных. Если вы хотите проконтролировать работу вашего зарядного устройства, то можете подключить Arduino к USB порту компьютера, но это необязательно, так как Arduino питается от источника напряжения 5В зарядного устройства.

Int batteryCapacity = 2500; // значение емкости батареи в мАч float resistance = 10.0; // измеренное сопротивление мощного резистора int cutoffVoltage = 1600; // максимальное напряжение на батарее (в мВ), которое не должно быть превышено float cutoffTemperatureC = 35; // максимальная температура батареи, которая не должна быть превышена (в градусах C) //float cutoffTemperatureF = 95; // максимальная температура батареи, которая не должна быть превышена (в градусах F) long cutoffTime = 46800000; // максимальное время заряда в 13 часов, которое не должно быть превышено int outputPin = 9; // провод выходного сигнала подключен к цифровому выводу 9 int outputValue = 150; // значение выходного ШИМ сигнала int analogPinOne = 0; // первый датчик напряжения подключен к аналоговому выводу 0 float valueProbeOne = 0; // переменная для хранения значения на analogPinOne float voltageProbeOne = 0; // рассчитанное напряжение на analogPinOne int analogPinTwo = 1; // второй датчик напряжения подключен к аналоговому выводу 1 float valueProbeTwo = 0; // переменная для хранения значения на analogPinTwo float voltageProbeTwo = 0; // рассчитанное напряжение на analogPinTwo int analogPinThree = 2; // третий датчик напряжения подключен к аналоговому выводу 2 float valueProbeThree = 0; // переменная для хранения значения на analogPinThree float tmp36Voltage = 0; // рассчитанное напряжение на analogPinThree float temperatureC = 0; // рассчитанная температура датчика в градусах C //float temperatureF = 0; // рассчитанная температура датчика в градусах F float voltageDifference = 0; // разница между напряжениями на analogPinOne и analogPinTwo float batteryVoltage = 0; // рассчитанное напряжение на батарее float current = 0; // рассчитанный ток, протекающий через нагрузку в (мА) float targetCurrent = batteryCapacity / 10; // целевой выходной ток (в мА) устанавливается в значение // C/10 или 1/10 от емкости батареи float currentError = 0; // разница между целевым и фактическим токами (в мА) void setup() { Serial.begin(9600); // настройка последовательного интерфейса pinMode(outputPin, OUTPUT); // установить вывод, как выход } void loop() { analogWrite(outputPin, outputValue); // записать выходное значение в выходной вывод Serial.print("Output: "); // показать выходные значения для контроля на компьютере Serial.println(outputValue); valueProbeOne = analogRead(analogPinOne); // считать входное значение на первом пробнике voltageProbeOne = (valueProbeOne*5000)/1023; // рассчитать напряжение на первом пробнике в милливольтах Serial.print("Voltage Probe One (mV): "); // показать напряжение на первом пробнике Serial.println(voltageProbeOne); valueProbeTwo = analogRead(analogPinTwo); // считать входное значение на втором пробнике voltageProbeTwo = (valueProbeTwo*5000)/1023; // рассчитать напряжение на втором пробнике в милливольтах Serial.print("Voltage Probe Two (mV): "); // показать напряжение на втором пробнике Serial.println(voltageProbeTwo); batteryVoltage = 5000 - voltageProbeTwo; // рассчитать напряжение на батарее Serial.print("Battery Voltage (mV): "); // показать напряжение на батарее Serial.println(batteryVoltage); current = (voltageProbeTwo - voltageProbeOne) / resistance; // рассчитать ток заряда Serial.print("Target Current (mA): "); // показать целевой ток Serial.println(targetCurrent); Serial.print("Battery Current (mA): "); // показать фактический ток Serial.println(current); currentError = targetCurrent - current; // разница между целевым и измеренным токами Serial.print("Current Error (mA): "); // показать ошибку установки тока Serial.println(currentError); valueProbeThree = analogRead(analogPinThree); // считать входное значение третьего пробника, tmp36Voltage = valueProbeThree * 5.0; // преобразуя его в напряжение tmp36Voltage /= 1024.0; temperatureC = (tmp36Voltage - 0.5) * 100 ; // преобразование, исходя из зависимости в 10 мВ на градус со сдвиком в 500 мВ // ((напряжение - 500 мВ) умножить на 100) Serial.print("Temperature (degrees C) "); // показать температуру в градусах Цельсия Serial.println(temperatureC); /* temperatureF = (temperatureC * 9.0 / 5.0) + 32.0; //преобразовать в градусы Фаренгейта Serial.print("Temperature (degrees F) "); Serial.println(temperatureF); */ Serial.println(); // дополнительные пустые строки, чтобы облегчить чтение данных при отладке Serial.println(); if(abs(currentError) > 10) // если ошибка установки тока достаточно велика, то подстроить выходное напряжение { outputValue = outputValue + currentError / 10; if(outputValue < 1) // выходное значение никогда не может быть ниже 0 { outputValue = 0; } if(outputValue > 254) // выходное значение никогда не может быть выше 255 { outputValue = 255; } analogWrite(outputPin, outputValue); // записать новое выходное значение } if(temperatureC > cutoffTemperatureC) // остановить зарядку, если температура батареи превысила безопасный порог { outputValue = 0; Serial.print("Max Temperature Exceeded"); } /* if(temperatureF > cutoffTemperatureF) // остановить зарядку, если температура батареи превысила безопасный порог { outputValue = 0; } */ if(batteryVoltage > cutoffVoltage) // остановить зарядку, если напряжение на батарее превысило безопасный порог { outputValue = 0; Serial.print("Max Voltage Exceeded"); } if(millis() > cutoffTime) // остановить зарядку, если время заряда превысило порог { outputValue = 0; Serial.print("Max Charge Time Exceeded"); } delay(10000); // задержка в 10 секунд перед следующей итерацией цикла }

Скачиваемую версию исходного кода вы можете найти по ссылке, приведенной ниже.

Простое решение для систем охраны и автоматики!

BM8039D , MP8036 , MA3401

Есть в наличии

Купить оптом

Данный модуль разработан специально для устройств из каталога Мастер Кит BM8039D , MP8036 , MA3401 и т.п. Но с успехом может использоваться с любой домашней автоматикой и сигнализацией.

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

Модуль будет полезен для проектов пользователей на базе микроконтроллеров и Arduino и Raspberry.

Технические характеристики

Напряжение питания (В) 220
Количество встроенных реле управления (шт) 1
Тип питания переменный
Количество входов (шт) 1
Количество выходов (шт) 1
Рекомендованная температура эксплуатации (°С) -30...+60
Длина (мм) 42
Ширина (мм) 25
Высота (мм) 17
Вес, не более (г) 20
Напряжение коммутации (В) 220
Мощность подключаемой нагрузки, максимальная (Вт) 1
Вес 38

Особенности

Принцип работы

При наличии на входе модуля переменного напряжения 220V происходит замыкание контактов реле. Благодаря применению оптореле модуль может напрямую подключаться к линиям контроля микроконтроллера.

Конструкция устройства

Модуль выполнен в виде встраиваемого датчика. Модуль имеет небольшие размеры 40х25х15 мм. При необходимости, модуль может выполнять роль бестрансформаторного источника питания, с рабочим напряжением 5В/12В и током до 80 мА.

Схемы

Подключение

Комплект поставки

  • Модуль MP220V - 1 шт.
  • Инструкция - 1 шт.

Что потребуется для сборки

  • Для подключения понадобится: провод, отвертка, бокорезы.

Подготовка к эксплуатации

  • Включите мультиметр в режим измерения сопротивления. Подключите щупы к линии контроля модуля.
  • Подключите к клеммам «IN 220V» сетевой шнур с вилкой.
  • Включите вилку в сеть 220В.
  • На плате должен зажжется индикатор, а мультиметр должен показать 0 Ом.
  • Проверка завершена. Приятной эксплуатации

Условия эксплуатации

  • Температура -30С до +50С.
  • Относительная влажность 20-80% без образования конденсата.
  • Tutorial

Введение

Всем привет! После завершения цикла по датчикам были вопросы различного плана по измерению параметров потребления бытовых и не очень электроприборов. Кто сколько потребляет, как что подключать чтобы измерить, какие бывают тонкости и так далее. Пришло время раскрыть все карты в этой области.
В этом цикле статей мы рассмотрим тему измерения параметров электроэнергии. Этих параметров на самом деле очень даже большое количество, о которых я постараюсь постепенно рассказать небольшими сериями.
Пока в планах три серии:
  • Измерение электроэнергии.
  • Качество электроэнергии.
  • Устройства измерения параметров электроэнергии.
В процессе разбора будем решать те или иные практические задачи на микроконтроллерах до достижения результата. Разумеется, большая часть данного цикла будет посвящена измерению переменного напряжения и может пригодиться всем любителям контролировать электроприборы своего умного дома.
По итогам всего цикла мы изготовим некий умный электросчетчик с выходом в интернет. Совсем отъявленные любители контролировать электроприборы своего умного дома могут оказать посильную помощь в реализации коммуникационной части на базе, например MajorDomo. Сделаем OpenSource умный дом лучше, так сказать.
В этой серии в двух частях мы разберем следующие вопросы:
  • Подключение датчиков тока и напряжения в устройствах постоянного тока, а также однофазных и трехфазных цепей переменного тока;
  • Измерение действующих значений тока и напряжения;
  • Измерение коэффициента мощности;
  • Полная, активная и реактивная мощность;
  • Потребление электроэнергии;
Подкатом вы найдете ответы на первые два вопроса данного списка. Я намеренно не затрагиваю вопросы точности измерения показателей и с данной серии лишь радуюсь полученным результатам с точностью плюс-минус лапоть. Этому вопросу я обязательно посвящу отдельную статью в третьей серии.

1. Подключение датчиков


В прошлом цикле про датчики напряжения и тока я рассказал о видах датчиков, но не рассказал о том как ими пользоваться и куда их ставить. Пришло время это исправить
Подключение датчиков постоянного тока
Понятно что весь цикл будет посвящён системам переменного тока, но быстро пробежимся и по цепям постоянного тока, так как это может нам пригодиться при разработке источников питания постоянного тока. Возьмем к примеру классический понижающий преобразователь с ШИМ :


Рис 1. Понижающий преобразователь с ШИМ
Нашей задачей является обеспечение стабилизированного выходного напряжения. Кроме того, на основании информации с датчика тока возможно контролировать режим работы дросселя L1, не допуская его насыщения, а также реализовывать токовую защиту преобразователя. И честно говоря, вариантов установки датчиков особо и нет.
Датчик напряжения в виде резистивного делителя R1-R2, который единственный способен работать на постоянном токе, устанавливается на выходе преобразователя. Как правило специализированная микросхема преобразователя имеет вход обратной связи, и прилагает все усилия для того, чтобы на этом входе (3) оказался определённый уровень напряжения, прописанный в документации на микросхему. Например 1,25В. Если наше выходное напряжение с этим уровнем совпадает - все хорошо - мы напрямую подаем выходное напряжение на этот вход. Если нет, то устанавливаем делитель. Если нам надо обеспечить выходное напряжение в 5В, то делитель должен обеспечивать коэффициент деления 4, т. е. Например R1 = 30к, R2 = 10к.
Датчик тока обычно устанавливается между источником питания и преобразователем и на микросхему. По разности потенциалов между точками 1 и 2, и при известном сопротивлении резисторы Rs возможно определить текущее значение тока нашего дросселя. Устанавливать датчик тока между источников и нагрузкой не самая хорошая идея, так как конденсатор фильтра будет отрезан резистором от потребителей импульсных токов. Установка резистора в разрыв общего провода тоже нге сулит ничего хорошего - будет два земляных уровня с которыми возиться то еще удовольствие.
Проблемы падения напряжения можно избежать путем использования бесконтактных датчиков тока - например датчиков холла:


Рис 2. Бесконтактный датчик тока
Однако есть более хитрый способ измерения тока. Ведь на транзисторе точно также падает напряжение и через него течет тот же самый ток что и индуктивность. Следовательно, по падению напряжения на нем можно также определить текущее значение тока. Честно говоря, если посмотреть на внутреннюю структуру микросхем преобразователей, например, от Texas Instruments - то такой способ встречается так же часто как и предыдущие. Точность такого способа конечно не самая высокая, но для работы токовой отсечки этого вполне достаточно.


Рис 3. Транзистор в качестве датчика тока
Аналогично поступаем в других схемах подобных преобразователей, будь то повышающий или инвертирующий.
Однако необходимо отдельно упомянуть о трансформаторных прямоходовом и обратноходовом преобразователях.


Рис 4. Подключение датчиков тока в обратноходовых преобразователях
В них точно также может использоваться либо внешнее сопротивление, либо транзистор в его роли.
На этом с подключением датчиков в преобразователи постоянного тока мы закончили. Если у вас есть предложения по другим вариантам - с удовольствием дополню ими статью.
1.2 Подключение датчиков в однофазные цепи переменного тока
В цепях переменного тока у нас гораздо больший выбор возможных датчиков. Рассмотрим несколько вариантов.
Самый простой - использование резистивного делителя напряжения и токового шунта.


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


Рис 6.Подключение трансформаторных и бесконтактных датчиков тока и напряжения
1.3 Подключение датчиков в многофазные цепи сетей переменного тока
В многофазных сетях наши возможности по подключению датчиков тока немного меньше. Связано это с тем, что токовый шунт использовать совсем не получится, так как разность потенциалов между шунтами фаз будет колебаться в пределах сотен вольт и мне не известен ни один контроллер общего применения, аналоговые входы которого способны выдержать такое издевательство.
Один способ использовать токовые шунты конечно есть - для каждого канала необходимо сделать гальванически развязанный аналоговый вход. Но гораздо проще и надежнее использовать другие датчики.
В своем анализаторе качества я использую резистивные делители напряжения и выносные датчики тока на эффекте холла.

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


Рис 8.Использование трансформаторов напряжения в трехфазной сети

2 Действующее значение тока и напряжения


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


Рис 9. Серия мгновенных значений напряжения
Наша задача - произвести подсчет действующего значения. Для начала воспользуемся формулой интеграла:
(1)
В цифровой системе приходится ограничиваться неким квантом времени, так что мы переходим к сумме:
(2)
Где - период дискретизации нашего сигнала, а - число отсчетов за период измерения. Где-то здесь я в видео начинаю втирать дичь про равенство площадей. Надо было выспаться в тот день. =)
В микроконтроллерах MSP430FE4252, которые применяются в однофазных электросчетчиках Меркурий, за период измерения равный 1, 2 или 4 секунд производится 4096 отсчетов. На T=1с и N=4096 мы и будем опираться в дальшейнем. Более того, 4096 точек в секунду позволят нам использовать алгоритмы быстрого преобразования фурье для определения гармонического спектра вплоть до 40 гармоники, как того требует ГОСТ. Но об этом в следующей серии.
Набросаем алгоритм для нашей программы. Нам требуется обеспечить стабильный запуск АЦП каждую 1/8192 секунды, так как у нас два канал и измерять мы будем эти данные попеременно. Для этого настроим таймер и сигнал прерывания будет автоматически перезапускать АЦП. Все АЦП так умеют.
Писать будущую программу будем на arduino, так как она у многих под рукой. У нас пока чисто академический интерес.
Имея частоту системного кварца 16МГц и 8-разрядный таймер (чтобы жизнь медом не казалась) нам необходимо обеспечить частоту срабатывания хоть какого прерывания таймера с частотой 8192Гц.
Печалимся по поводу того что 16МГц цело не делится как нам надо и итоговая частота работы таймера 8198Гц. Закрываем глаза на погрешность в 0,04% и все равно считываем по 4096 выборок на канал.
Печалимся по поводу того, что прерывание по переполнению в arduino занято расчетом времени (отвечает за millis и delay, так что это работать нормально перестанет), так что пользуемся прерыванием по сравнению.
А еще внезапно понимаем, что сигнал к нам приходит биполярный, и что msp430fe4252 с ним прекрасно справляется. Мы же довольствуемся униполярным АЦП, поэтому на операционном усилителе собираем простой преобразователь биполярного сигнала в униполярный:


Рис 10.Преобразователь биполярного сигнала в униполярный
Причем наша задача обеспечить колебание нашей синусоиды относительно половины опорного напряжения - тогда мы либо отнимем половину диапазона либо активируем опцию в настройках АЦП и получим знаковые значения.
В Arduino 10-разрядный АЦП, поэтому из беззнакового результата в пределах 0-1023 будем вычитать половину и получим -512- 511.
Проверяем модель, собранную в LTSpiceIV и убеждаемся, что все работает как надо. В видеоматериале дополнительно убеждаемся экспериментально.


Рис 11.результат моделирования. Зеленым исходный сигнал, синим - выходной

Скетч для Arduino для одного канала

void setup() { autoadcsetup(); DDRD |=(1<

Программа написана в среде Arduino IDE для микроконтроллера ATmega1280. На моей отладочной плате первые 8 каналов разведены для внутренних нужд платы поэтому используется канал ADC8. Возможно использовать данный скетч и для платы с ATmega168, однако необходимо выбрать правильный канал.
Внутри прерываний передергиваем пару служебных пинов чтобы наглядно видеть рабочую частоту оцифровки.
Пару слов о том, откуда взялся коэффициент 102. При первом запуске с генератора подавался сигнал различной амплитуды, с осциллографа считывалось показание действующего значения напряжения, а из консоли забиралось рассчитанное значение в абсолютных единицах АЦП.

Umax, В Urms, В Counted
3 2,08 212
2,5 1,73 176
2 1,38 141
1,5 1,03 106
1 0,684 71
0,5 0,358 36
0,25 0,179 19

Разделив значения третьего столбца на значения второго получаем в среднем 102. Это и будет наш «калибровочный» коэффициент. Однако можно заметить, что при снижении напряжения точность резко падает. Это происходит из-за низкой чувствительности нашего АЦП. Фактически 10 разрядов для точных расчётов катастрофически мало и если напряжение в розетке измерить таким образом вполне получится, то поставить 10-разрядный АЦП на измерение потребляемого нагрузкой тока будет преступлением против метрологии.

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

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

  • Tutorial

Введение

Всем привет! После завершения цикла по датчикам были вопросы различного плана по измерению параметров потребления бытовых и не очень электроприборов. Кто сколько потребляет, как что подключать чтобы измерить, какие бывают тонкости и так далее. Пришло время раскрыть все карты в этой области.
В этом цикле статей мы рассмотрим тему измерения параметров электроэнергии. Этих параметров на самом деле очень даже большое количество, о которых я постараюсь постепенно рассказать небольшими сериями.
Пока в планах три серии:
  • Измерение электроэнергии.
  • Качество электроэнергии.
  • Устройства измерения параметров электроэнергии.
В процессе разбора будем решать те или иные практические задачи на микроконтроллерах до достижения результата. Разумеется, большая часть данного цикла будет посвящена измерению переменного напряжения и может пригодиться всем любителям контролировать электроприборы своего умного дома.
По итогам всего цикла мы изготовим некий умный электросчетчик с выходом в интернет. Совсем отъявленные любители контролировать электроприборы своего умного дома могут оказать посильную помощь в реализации коммуникационной части на базе, например MajorDomo. Сделаем OpenSource умный дом лучше, так сказать.
В этой серии в двух частях мы разберем следующие вопросы:
  • Подключение датчиков тока и напряжения в устройствах постоянного тока, а также однофазных и трехфазных цепей переменного тока;
  • Измерение действующих значений тока и напряжения;
  • Измерение коэффициента мощности;
  • Полная, активная и реактивная мощность;
  • Потребление электроэнергии;
Подкатом вы найдете ответы на первые два вопроса данного списка. Я намеренно не затрагиваю вопросы точности измерения показателей и с данной серии лишь радуюсь полученным результатам с точностью плюс-минус лапоть. Этому вопросу я обязательно посвящу отдельную статью в третьей серии.

1. Подключение датчиков


В прошлом цикле про датчики напряжения и тока я рассказал о видах датчиков, но не рассказал о том как ими пользоваться и куда их ставить. Пришло время это исправить
Подключение датчиков постоянного тока
Понятно что весь цикл будет посвящён системам переменного тока, но быстро пробежимся и по цепям постоянного тока, так как это может нам пригодиться при разработке источников питания постоянного тока. Возьмем к примеру классический понижающий преобразователь с ШИМ :


Рис 1. Понижающий преобразователь с ШИМ
Нашей задачей является обеспечение стабилизированного выходного напряжения. Кроме того, на основании информации с датчика тока возможно контролировать режим работы дросселя L1, не допуская его насыщения, а также реализовывать токовую защиту преобразователя. И честно говоря, вариантов установки датчиков особо и нет.
Датчик напряжения в виде резистивного делителя R1-R2, который единственный способен работать на постоянном токе, устанавливается на выходе преобразователя. Как правило специализированная микросхема преобразователя имеет вход обратной связи, и прилагает все усилия для того, чтобы на этом входе (3) оказался определённый уровень напряжения, прописанный в документации на микросхему. Например 1,25В. Если наше выходное напряжение с этим уровнем совпадает - все хорошо - мы напрямую подаем выходное напряжение на этот вход. Если нет, то устанавливаем делитель. Если нам надо обеспечить выходное напряжение в 5В, то делитель должен обеспечивать коэффициент деления 4, т. е. Например R1 = 30к, R2 = 10к.
Датчик тока обычно устанавливается между источником питания и преобразователем и на микросхему. По разности потенциалов между точками 1 и 2, и при известном сопротивлении резисторы Rs возможно определить текущее значение тока нашего дросселя. Устанавливать датчик тока между источников и нагрузкой не самая хорошая идея, так как конденсатор фильтра будет отрезан резистором от потребителей импульсных токов. Установка резистора в разрыв общего провода тоже нге сулит ничего хорошего - будет два земляных уровня с которыми возиться то еще удовольствие.
Проблемы падения напряжения можно избежать путем использования бесконтактных датчиков тока - например датчиков холла:


Рис 2. Бесконтактный датчик тока
Однако есть более хитрый способ измерения тока. Ведь на транзисторе точно также падает напряжение и через него течет тот же самый ток что и индуктивность. Следовательно, по падению напряжения на нем можно также определить текущее значение тока. Честно говоря, если посмотреть на внутреннюю структуру микросхем преобразователей, например, от Texas Instruments - то такой способ встречается так же часто как и предыдущие. Точность такого способа конечно не самая высокая, но для работы токовой отсечки этого вполне достаточно.


Рис 3. Транзистор в качестве датчика тока
Аналогично поступаем в других схемах подобных преобразователей, будь то повышающий или инвертирующий.
Однако необходимо отдельно упомянуть о трансформаторных прямоходовом и обратноходовом преобразователях.


Рис 4. Подключение датчиков тока в обратноходовых преобразователях
В них точно также может использоваться либо внешнее сопротивление, либо транзистор в его роли.
На этом с подключением датчиков в преобразователи постоянного тока мы закончили. Если у вас есть предложения по другим вариантам - с удовольствием дополню ими статью.
1.2 Подключение датчиков в однофазные цепи переменного тока
В цепях переменного тока у нас гораздо больший выбор возможных датчиков. Рассмотрим несколько вариантов.
Самый простой - использование резистивного делителя напряжения и токового шунта.


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


Рис 6.Подключение трансформаторных и бесконтактных датчиков тока и напряжения
1.3 Подключение датчиков в многофазные цепи сетей переменного тока
В многофазных сетях наши возможности по подключению датчиков тока немного меньше. Связано это с тем, что токовый шунт использовать совсем не получится, так как разность потенциалов между шунтами фаз будет колебаться в пределах сотен вольт и мне не известен ни один контроллер общего применения, аналоговые входы которого способны выдержать такое издевательство.
Один способ использовать токовые шунты конечно есть - для каждого канала необходимо сделать гальванически развязанный аналоговый вход. Но гораздо проще и надежнее использовать другие датчики.
В своем анализаторе качества я использую резистивные делители напряжения и выносные датчики тока на эффекте холла.

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


Рис 8.Использование трансформаторов напряжения в трехфазной сети

2 Действующее значение тока и напряжения


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


Рис 9. Серия мгновенных значений напряжения
Наша задача - произвести подсчет действующего значения. Для начала воспользуемся формулой интеграла:
(1)
В цифровой системе приходится ограничиваться неким квантом времени, так что мы переходим к сумме:
(2)
Где - период дискретизации нашего сигнала, а - число отсчетов за период измерения. Где-то здесь я в видео начинаю втирать дичь про равенство площадей. Надо было выспаться в тот день. =)
В микроконтроллерах MSP430FE4252, которые применяются в однофазных электросчетчиках Меркурий, за период измерения равный 1, 2 или 4 секунд производится 4096 отсчетов. На T=1с и N=4096 мы и будем опираться в дальшейнем. Более того, 4096 точек в секунду позволят нам использовать алгоритмы быстрого преобразования фурье для определения гармонического спектра вплоть до 40 гармоники, как того требует ГОСТ. Но об этом в следующей серии.
Набросаем алгоритм для нашей программы. Нам требуется обеспечить стабильный запуск АЦП каждую 1/8192 секунды, так как у нас два канал и измерять мы будем эти данные попеременно. Для этого настроим таймер и сигнал прерывания будет автоматически перезапускать АЦП. Все АЦП так умеют.
Писать будущую программу будем на arduino, так как она у многих под рукой. У нас пока чисто академический интерес.
Имея частоту системного кварца 16МГц и 8-разрядный таймер (чтобы жизнь медом не казалась) нам необходимо обеспечить частоту срабатывания хоть какого прерывания таймера с частотой 8192Гц.
Печалимся по поводу того что 16МГц цело не делится как нам надо и итоговая частота работы таймера 8198Гц. Закрываем глаза на погрешность в 0,04% и все равно считываем по 4096 выборок на канал.
Печалимся по поводу того, что прерывание по переполнению в arduino занято расчетом времени (отвечает за millis и delay, так что это работать нормально перестанет), так что пользуемся прерыванием по сравнению.
А еще внезапно понимаем, что сигнал к нам приходит биполярный, и что msp430fe4252 с ним прекрасно справляется. Мы же довольствуемся униполярным АЦП, поэтому на операционном усилителе собираем простой преобразователь биполярного сигнала в униполярный:


Рис 10.Преобразователь биполярного сигнала в униполярный
Причем наша задача обеспечить колебание нашей синусоиды относительно половины опорного напряжения - тогда мы либо отнимем половину диапазона либо активируем опцию в настройках АЦП и получим знаковые значения.
В Arduino 10-разрядный АЦП, поэтому из беззнакового результата в пределах 0-1023 будем вычитать половину и получим -512- 511.
Проверяем модель, собранную в LTSpiceIV и убеждаемся, что все работает как надо. В видеоматериале дополнительно убеждаемся экспериментально.


Рис 11.результат моделирования. Зеленым исходный сигнал, синим - выходной

Скетч для Arduino для одного канала

void setup() { autoadcsetup(); DDRD |=(1<

Программа написана в среде Arduino IDE для микроконтроллера ATmega1280. На моей отладочной плате первые 8 каналов разведены для внутренних нужд платы поэтому используется канал ADC8. Возможно использовать данный скетч и для платы с ATmega168, однако необходимо выбрать правильный канал.
Внутри прерываний передергиваем пару служебных пинов чтобы наглядно видеть рабочую частоту оцифровки.
Пару слов о том, откуда взялся коэффициент 102. При первом запуске с генератора подавался сигнал различной амплитуды, с осциллографа считывалось показание действующего значения напряжения, а из консоли забиралось рассчитанное значение в абсолютных единицах АЦП.

Umax, В Urms, В Counted
3 2,08 212
2,5 1,73 176
2 1,38 141
1,5 1,03 106
1 0,684 71
0,5 0,358 36
0,25 0,179 19

Разделив значения третьего столбца на значения второго получаем в среднем 102. Это и будет наш «калибровочный» коэффициент. Однако можно заметить, что при снижении напряжения точность резко падает. Это происходит из-за низкой чувствительности нашего АЦП. Фактически 10 разрядов для точных расчётов катастрофически мало и если напряжение в розетке измерить таким образом вполне получится, то поставить 10-разрядный АЦП на измерение потребляемого нагрузкой тока будет преступлением против метрологии.

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

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

С некоторыми дополнениями.

Мало известная фишка Ардуино и многих других AVR чипов это возможность измерить внутренний источник опорного напряжения 1.1 В. Эта функция может быть использована для повышения точности функции Arduino — analogRead при использовании стандартного опорного напряжения 5 В (на платформах с напряжением питания 5 В) или 3.3 В (на платформах с напряжением питания 3.3 В). Она также может быть использована для измерения Vcc , поданного на чип , обеспечивая средство контроля напряжения батареи без использования драгоценных аналоговый выводов .

Мотивация

Есть, по крайней мере, две причины для измерения напряжения, питающего наш Arduino (Vcc). Одним из них является наш проект, питающийся от батареи, если мы хотим следить за уровнем напряжения батареи. Кроме того, когда питание от батареи (Vcc) не может быть 5,0 вольт(например питание от 3-х элементов 1.5 В), а мы хотим сделать аналоговые измерения более точными - мы должны использовать либо внутренний источник опорного напряжения 1,1 В либо внешний источник опорного напряжения. Почему?

Обычно предполагают при использовании analogRead () то, что аналоговое напряжение питания контроллера составляет 5.0 вольт, когда в действительности это может быть совсем не так(например питание от 3-х элементов 1.5 В). Официальная документация Arduino даже может привести нас к этому неправильному предположению. Дело в том, что питание не обязательно 5,0 вольт, независимо от текущего уровня это питание подано на Vcc чипа. Если наше питание не стабилизировано или если мы работаем от аккумулятора, это напряжение может меняться совсем немного. Вот пример кода, иллюстрирующий эту проблему:

Double Vcc = 5.0; // не обязательно правда int value = analogRead(0); / читаем показания с А0 double volt = (value / 1023.0) * Vcc; // верно только если Vcc = 5.0 вольт Для того чтобы измерить напряжение точно, необходимо точное опорное напряжение. Большинство чипов AVR обеспечивает три источника опорного напряжения:

  • 1,1 в от внутреннего источника, в документации он проходит как bandgap reference (некоторые из них 2,56 В, например ATMega 2560). Выбор осуществляется функцией analogReference() с параметром INTERNAL : analogReference(INTERNAL) ;
  • внешний источник опорного наптяжения, на ардуинке подписан AREF. Выбор: analogReference(EXTERNAL);
  • Vcc - источник питания самого контроллера. Выбор: analogReference(DEFAULT).

В Arduino нельзя просто взять и подключить Vcc к аналоговому пину напрямую - по умолчанию AREF связан с Vcc и вы всегда будете получать максимальное значение 1023, от какого бы напряжения вы не питались. Спасает подключение к AREF источника напряжения с заранее известным, стабильным напряжением, но это - лишний элемент в схеме.

Еще можно соединить Vcc с AREF через диод : падение напряжение на диоде заранее известно, поэтому вычислить Vcc не составит труда. Однако, при такой схеме через диод постоянно протекает ток , сокращая жизнь батареи, что тоже не очень удачно.

Источник внешнего опорного напряжения является наиболее точным, но требует дополнительных аппаратных средств. Внутренний ИОН стабильным, но не точен + / - 10% отклонение. Vcc является абсолютно ненадежен в большинстве случаев. Выбор внутреннего источника опорного напряжения является недорогим и стабильным, но большую часть времени, мы хотели бы измеряет большее напряжение чем 1.1 В, так что использование Vcc является наиболее практичным, но потенциально наименее точным. В некоторых случаях оно может быть очень ненадежным!

Как это сделать

Многие чипы AVR включая серию ATmega и ATtiny обеспечивают средства для измерения внутреннего опорного напряжения. Зачем это нужно? Причина проста - путем измерения внутреннего напряжения, мы можем определить значение Vcc. Вот как:

  1. Установить источник опорного напряжения по умолчанию: analogReference(DEFAULT); . Используем как источник - Vcc.
  2. Снять показания АЦП для внутреннего источника 1.1 В.
  3. Расчитать значение Vcc основываясь на измерении 1.1 В по формуле:

Vcc * (Показания АЦП) / 1023 = 1.1 В

Из чего следует:

Vcc = 1,1 В * 1023 / (Показания АЦП)

Собираем все вместе и получаем код:

long readVcc() { // Read 1.1V reference against AVcc // set the reference to Vcc and the measurement to the internal 1.1V reference #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV(MUX0); #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #endif delay(75); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }

Использование

Проверка напряжения Vcc или батареи

Вы можете назвать эту функцию – readVcc(), если Вы хотите мониторить Vcc. Примером может служить для проверка уровня заряда батареи. Вы также можете использовать её для определения подключены ли Вы к источнику питания или работаете от батареи.

Измерение Vcc для опорного напряжения

Вы также можете использовать её, чтобы получить правильное значение Vcc для использования с analogRead (), когда вы используете опорное напряжение (Vcc). Пока Вы не используете стабилизированный источник питания, Вы не можете быть уверенны, что Vcc = 5.0 вольт. Эта функция позволяет получить правильное значение. Хотя есть один нюанс….

В одной из статей я сделал заявление, что эта функция может использоваться, чтобы улучшить точность аналоговых измерений в тех случаях, когда Vcc было не совсем 5.0 вольт. К сожалению, эта процедура не будет давать точный результат. Почему? Это зависит от точности внутреннего источника опорного напряжения. Спецификация дает номинальное напряжение 1.1 вольт, но говорится, что оно может отличаться до 10%. Такие измерения могут быть менее точными, чем наш источник питания Arduino!

Повышаем точность

Пока большие допуски внутреннего источника питания 1.1 В. значительно ограничивают точность измерений при использовании в серийном производстве, для индивидуальных проэктов мы можем добиться большей точности. Сделать это просто, просто измерив Vcc с помощью вольтметра и нашей функции readVcc(). Далее заменяем константу 1125300L новой переменной:

scale_constant = internal1.1Ref * 1023 * 1000

internal1.1Ref = 1.1 * Vcc1 (показания_вольтметра) / Vcc2 (показания_функции_readVcc())

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

Вывод

С этой маленькой функцией можно сделать многее. Вы можете использовать стабильное опорное напряжение близкое к 5.0 В не имея на самом деле 5.0 В на Vcc. Вы можете измерять напряжение вашей батареи или даже увидеть на каком вы питание от батареи или от стационарного источника питания.

И наконец, код будет поддерживать все Arduino, включая новый Leonardo, а также чипы ATtinyX4 и ATtinyX5 серий.

Похожие статьи