Измерение тока в домашней сети

Существует целый класс устройств под названием Ethernet Relay, которые позволяют удаленно управлять подключенной нагрузкой через сеть. Большинство из них достаточно дорогие – ближе к 100 долл., и заведомо уступают по цене и по гибкости настройки связке, скажем, Raspberry Pi + PiFace. А что если задача не только включать-выключать нагрузку, но и измерять протекающий ток? Для этого требуется собственно датчик (на шунте или эффекте Холла) и АЦП (Raspberry Pi не содержит встроенного АЦП). В качестве датчика можно взять недорогой ACS712, а в качестве АЦП, например, ADC-Pi.

ADC-Pi мне не понравился по двум причинам:
  • при той частоте измерений, которая требуется для определения силы переменного тока в сети, этот АЦП дает очень большую погрешность (скорее всего я до конца не разобрался с регистрами)
  • используя этот АЦП в связке с Raspberry Pi под Linux сложно обеспечить необходимую стабильность периода измерений. Устанавливать и настраивать RTOS Linux только для этой задачи мне показалось слишком сложным предприятием, тем более что есть более простое и проверенное решение: Arduino

У всех Arduino уже есть АЦП (8-битный, но этого вполне достаточно), скетчи для Arduino исполняются с необходимой стабильностью, для связи с Raspberry Pi есть различные варианты, самый простой из которых – USB кабель. Ну и конечно, привлекательная цена.

Связка, которую я использовал, приведена на картинке.

Измерение силы тока представляется несложной задачей, если бы не одно «но»: физические датчики «шумят». На рисунке приведен пример фактических и расчетных показателей тока для моей схемы при 512 последовательных измерениях.


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

Попытка номер раз


Формула переменного тока (кто забыл – см. wiki)

i=Im sin(ωt+ψ)

где:

Im – максимальное значение тока
ω – угловая частота
t – время (порядковый номер) изменения
ψ – начальная фаза тока

Можно попытаться найти необходимые параметры, используя аналитические инструменты. И тут нас ждет приятный сюрприз: осенью прошлого (2013) года компания Wolfram выпустила версию своего замечательного пакета Mathematica для Raspberry Pi. Бесплатно (для домашнего использования). И мы можем применить его для анализа данных, считанных с датчика.

Пример вызова пакета расчета в Raspberry Pi:

pi@raspi ~ $ wolfram -script calc_current.wl datafile=/tmp/data.csv

Сам скрипт calc_current.wl ниже с комментариями:

Прочитать данные из файла, переданного в качестве параметра. Файл содержит строки вида <номер измерения>,<значение>.

data=Import[$CommandLine[[4]]]

Когда данные прочитаны, можно проделать анализ Фурье (Fast Fourier Transform) для того чтобы определить, приблизительно, количество циклов синусоиды на имеющейся выборке. Зависимость силы тока от времени нелинейна, и приблизительная угловая скорость, рассчитанная по FFT и переданная в качестве начального значения, резко увеличит шансы подобрать правильные параметры синусоиды.

fourier=Take[Abs[Fourier[data[[All,2]]]],{2,256}]

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

topcycle=Ordering[fourier,-1]
avg=Mean[fourier]
top=fourier[[topcycle[[1]]]]
If[top < 10 * avg, Print["No AC"]; Exit[]]

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

nlm=NonlinearModelFit[data, a Sin[b x + c]+d, {a,{b, 2 Pi * topcycle[[1]] / 512}, c, d},x]

Зная физические характеристики АЦП (размерность 1024, базовое напряжение 5V) и датчика (в моей версии 0.185V / A), можно вычислить эффективную силу тока:

imax=Abs[nlm["BestFitParameters"][[1]][[2]]] / (1024 / 5 * 0.185)
Print["Imax=", imax]
iefc=imax / Sqrt[2]
Print["Iefc=", iefc]
Print["Power=", iefc * 230]

Предложенный метод работает в большинстве случаев. Количество измерений, когда NonlinearModelFit не смогла верно подобрать параметры синусоиды, составило около 5 процентов. Однако каждое измерение требует много времени – у меня в среднем 5 секунд – для запуска приложения wolfram. Поэтому…

Попытка номер два


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



или



Дифференцируя по X и Y, получаем систему линейных уравнений:



Решая систему по Крамеру, получим значения коэффициентов:



Тогда по теореме Пифагора максимальное значение тока составит:



Arduino-скетч, который реализует данный алгоритм, можно найти на Github-е. Метод обеспечивает хорошую точность измерений: для схемы на рисунке измеренное значение тока составляло стабильно 0.13A, что соответствует потреблению 29.9 Вт при напряжении 230V. Номинал лампочки, которая служила нагрузкой, 30 Вт.

Кстати, для Arduino также есть шилды с реле и весь функционал управления и мониторинга нагрузки можно реализовать на этой платформе. Raspberry Pi в таком случае будет использоваться только для организации удобного пользовательского интерфейса, например, через веб-сервер и как шедулер.
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 29

    +18
    Как гадко обжат сетевой кабель в RPi на первой картинке.
      +2
      На практике востребованы не инвазивные (бесконтактные) способы измерения тока и, как следствие, потребляемой мощности в квартире или доме. К примеру британский Current Cost EnviR рассмотренный ранее на Хабре или же WebMeteoBox разработанный в Дубне и используемый в Народном мониторинге.
      Разумеется данный метод измерений менее точен (у британца до 5% заявлено), но отсутствие необходимости врезаться в электропроводку много стоит. Наиболее популярный измерительный датчик (трансформатор тока) SCT-013 за примерно $9 на eBay.
      Еще одного его применение также было опубликовано на Хабре.
        0
        Спасибо за ссылку на SCT-013, интересно.
        Вообще прототип предназначается для управления отдельно стоящим телевизором, чтобы дети днем делали уроки, а не пялились в ящик, пока родителей нет дома. Отсюда — реле. Измерялка же позволяет точно определить, «а не пялились ли дети в телевизор, вместо того чтобы делать уроки? (не играли ли в компьютер и т.д.)».
        Собственно, реализовать это как устройство — вариантов много. Мне показалось, что будет интересно рассказать про применение Mathematica для Raspberry Pi и напомнить про алгебру тем, кто ее подзабыл. На реально работающее устройство этот прототип, конечно, не тянет.
          +1
          Телевизор проще по пингу отлавливать (-
            0
            При условии, что смарт.
            Свой не смарт ловлю по наличию синезуба в эфире, запитанного от USB телевизора.
              0
              У меня ТВ воткнут в ИБП, на котором кроме ТВ висит только точка доступа и маршрутизатор — они его грузят на 1-3%, а вот когда включается телек, то нагрузка возрастает до 17%, поэтому мне легче по ИБП мониторить, когда дети телек включали.
          0
          Как-то слишком сложно… Проще ведь отлавливать начало синусоиды(переход через ноль), суммировать измеренные значения(абсолютные, без знака) за один период(10мс, или 20мс для полной волны) и разделить на количество измерений(обычно подбирается такая частота измерения которая дает количество измерений на период кратное двойке — 16, 32, 64...) за один период. Потом при необходимости пропускаем через оконный фильтр и можно показывать значение на индикаторе, с задержкой равной размеру окна зато без шума. Если датчик шумит даже при отсутствии тока — этот шум можно откалибровать и вычитать из измерений. Можно даже без отлова нуля, для медленно изменяющегося во времени среднего за период тока.
            +1
            Переход через ноль, по идее, должен соответствовать 1024 / 2, но в реальности довольно сильно от него отличается. Датчик действительно шумит на нуле, свою ошибку добавляет АЦП. Ноль также может плавать со временем. Не могу сказать почему, но результаты усреднения по 512 измерениям на нуле в разное время довольно сильно отличались.

            Кроме того, я бы не сказал, что второй вариант сильно сложный. По-моему наоборот все довольно просто. Не универсально, конечно, потому что не будет работать, скажем, для сети 60 Гц. Но можно заложить в скетч инициализацию и указывать частоту тока при подключении устройства в Raspberry.
              0
              Переход через ноль можно отлавливать по напряжению.
              Я кажется понимаю откуда шум берется, видимо пытаетесь измерять ток в цепи на уровне разрешающей способности датчика — слишком грубый датчик для измерения тока. Например, измерять 10мА на датчике со шкалой в 5А. Тогда надо усреднять выборки по нескольким периодам.

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

              У меня задача была несколько проще — я знаю что ток около нуля точно не протекает и есть довольно широкие интервалы возле нуля в которых тока гарантированно не может быть(либо это аварийное состояние) поэтому не так важно сколько точно циклов измерения уложится за полупериод — +-1 роли играть не будет, всеравно там в начале и конце много нулей. Усреднение 16 выборок за полупериод, затем за 16 периодов еще одно среднее получается и направляется на вычисление среднего из последних 8 значений. Получилось очень замечательно — показания не прыгают, стоят как вкопаные(3 знака) инерционность где-то в 1.5 секунд(почти стрелочный прибор получился).
              +2
              Можно еще в качестве АЦП использовать модуль на базе PCF8591.
              В модуль встроены датчик температуры и освещенности, есть простейший ЦАП.
              Интерфейс I2C, т.е. ничего лишнего. Цена бюджетна.

              image

              Ссылки для приобретения:
              electrodragon,
              dealextreme
                +2
                Забыл ссылку на исходник простейшей программки для него дать:
                https://github.com/ZigFisher/i2c-flymon/blob/master/src/pcf8591.c
                  0
                  Он довольно медленный, подойдет конечно для измерения медленных параметров таких как освещенность, датчик температуры и влажности, но захватить отдельные выборки 50Гц синусоиды будет проблематично.
                  +3
                  Судя по графику, там ВЧ шум. Его легко отфильтровать НЧ фильтром, благо он пишется ровно в одну строчку. Надобно ещё измерять настоящее напряжение (у меня оно например колеблется от 215В до 240В в зависимости от времени суток). Далее, тупо интегрируя, можно получить энергию и, соотвественно, мощность.
                    0
                    Приемлемое сглаживание получается на отрезке около 1/2 периода синусоиды. Понятно, что при этом амплитуда сильно проседает. Скорее всего с приемлемой точностью можно получить фактическую амплитуду, просто умножив сглаженную на заранее подобранную константу. Но я не проверял.
                      0
                      Э… не совсем понял. Вы НЧ фильтр использовали или просто усредняли по окну?
                      У вас остались сырые данные? Попробуйте применить к ним во такое преобразование:
                      y[i] := y[i-1] + α * (x[i] — y[i-1]) и поэскпериментировать со значением альфы от 0 до 1.
                      x — это сырые данные, y — отфильтрованные.
                        0
                        Нет, НЧ фильтр на цепь нагрузки я не ставил. Просто сглаживал по окну и смотрел, на каком объеме выборки графики будут достаточно гладкими.
                        Честно говоря, дальше экспериментировать я не планировал: результат меня вполне устраивает как по точности, так и по быстродействию.
                    0
                    А вы можете на ардуино сделать анализатор качества электроэнергии с автоматической генерацией отчета на соответсвие ГОСТ Р 54149-2010? Особенно интересует статистика всплесков напряжения. Я в таком заинтересован.
                      0
                      Только на Arduino — вряд ли. В связке с Raspberry — думаю да. Показания с Arduino можно снимать несколько (2 или 3) раз в секунду. Если такая дискретность удовлетворяет требованиям ГОСТа, то можно. Сделать сервер на PHP или Java, который будет генерить отчет легко. В выходные почитаю ГОСТ и отпишусь сюда же.
                        0
                        Если под анализатором качества подразумевается нечто подобное www.zetlab.ru/catalog/analyzers/a17_e8.php, то на Arduino его не сделать.

                        На Arduino можно добавить повесить датчик напряжения, например, как здесь habrahabr.ru/post/193022/. Но я бы скорее не отлавливал ноль, как автор, а сделал аналогично измерению тока и в цикле собирал данные и по току и по напряжению. Тогда можно было бы вычислять фазовое напряжение и ток, а также фазовый угол между током и напряжением.

                        Если же с Arduino брать только статистику, а анализ делать уже на Raspberry, тогда, скорее всего, можно вычислить все, что делает анализатор ZETLAB, включая частоту и гармоники.
                        0
                        Шумит не АЦП, а эти «сети» на фото, которые тянутся к датчику, вместо дифф-линий. Замените на скрученную пару: сигнал + земля. Земляной надо вывести к земляному выводу АЦП микроконтроллера, а не на любую первую попавшуюся землю. АЦП там всего-лишь десяти-разрядный, у него даже младший бит не прыгает, а в режиме 8-и бит чтобы там помехи были — нонсес.
                          0
                          Эта интересно. Я немного «упростил» схему, убрав «сопли»:



                          Правда это мало на что повлияло (график без нагрузки):



                          Есть еще какие-нибудь соображения, как избавиться от шума?
                            0
                            Нормирующий усилитель… немудрено столько шума наловить, амплитуда всего в 3 бита укладывается — малейшие наводки и имеем что имеем. Это кстати порядка 10мВ для АЦП, вполне может быть шум на «земле», надо бы общий провод для шунта взять непосредственно с вывода AGND контроллера и по этому проводу кроме прямого его назначения другой ток не пускать.
                              0
                              ACS712 — это не шунт, а дачик Холла. И я не знаю, какая из ног ATMEGA328P есть AGND. В даташите на него про отдельный AGND ничего не нашел, поэтому воткнул в ближайшую к блоку A0-A5 землю. Не думаю, чтобы это было принципиально. Мне все-таки кажется, что шумы на датчике. Залью на гит еще проект и назову ГСЧ на эффекте Холла… :)
                                0
                                Для таких величин порядка миливольт это очень принципиально. Для этого и задумывался этот вывод — именно относительно него идет отсчет АЦП. Если подключать не к нему, то практически любой ток вызовет изменение потенциала в точке подключения твоего «общего» провода относительно AGND и соответственно измеряемой величины.
                                Я когда-то давным давно делал блок питания, классика — стабилитрон, составной транзистор и т.д. долго не мог понять — на стабилитроне напряжение стабильно а на выходе идут пульсации в 200мВ — уже позже измерив всю схему вдоль и поперек выяснил причину — 15мА тока шли к стабилитрону от выпрямителя очень длинными дорожками, и все бы ничего но транзисторы стабилизатора брали общий провод прямо с выпрямителя, и этого длинного общего провода было достаточно чтобы ток в 15мА создавал 200мВ пульсаций, которые складывались с напряжением стабилитрона(которое таки было очень стабильное) и шли на транзисторы стабилизатора передавая эти пульсации на выход.

                                Странное дело, почему-то в даташите вывод этот не обозначен как аналоговая земля — вобщем он рядом с AVCC, AREF. AGND — 22 вывод(для DIP-а).
                                Кстати посмотри еще на схеме как подключено AVCC — он должен быть подключен к питанию через LC-фильтр, а на AREF должен быть конденсатор на AGND иначе АЦП можно использовать только с потенциометрами именно из-за помех в аналоговые цепи.
                                  0
                                  У меня Arduino такое: freeduino.ru/arduino/freeduino-2013.html

                                  На нем 22 нога припаяна к общей земле. AVCC не выведен никуда. AREF на другой стороне от A0-A5 и никаких конденсаторов я там не разглядел. Я попробую как-нибудь завязать датчик на него вместо VCC. Посмотрим, станет ли лучше.
                                    0
                                    Судя по расположению контроллера, AVCC AREF и AGND должны быть как раз со стороны аналоговых входов A0-A5. То что питание аналоговой части никак не фильтруется это фигово вобщем-то и может стать причиной «шума».
                                    Вообще по хорошему, на время измерения аналоговой величины необходимо еще и контроллер останавливать — для этого даже предусмотрен специальный спящий режим, из которого контроллер выходит в конце преобразования.
                              0
                              Отцепите всё — от датчика сети, USB и т.п, запитайтесь от аккумулятора. Далее острым пинцетом соедините выводы микроконтроллера AGND и входной пин АЦП. Снимите «осциллограмму», например в память, а потом по USB залейте к себе в приложение, там должно быть совершенно чисто, максимум, и то не факт, может прыгать младший бит. Если прыгает, то грязь идёт по питанию, например от ИП, или стабилизатора или USB, или по питанию REF. Тут только осциллографом можно это увидеть.
                            0
                            Я решил попробовать с другим датчиком и собрал конструкцию как здесь: openenergymonitor.org/emon/buildingblocks/measuring-voltage-with-an-acac-power-adapter Выглядит так:



                            Под напряжением дает такую картинку:



                            Лепота. Амплитуда вдвое шире, чем у авторов OpenEnergyMonitor, но это потому, что я взял трансформатор 12V/24V (какой оказался в принесенном в жертву БП). Без напряжения картинка получается в пределах (± 1 бит):









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

                              0
                              Попривыкали к автомасштабированию… 1 бит амплитуды растянуть на весь экран…
                              Достаточно было того же масштаба что и на первой картинке, шум в 1 бит было бы все еще видно, но так же была бы видна и его незначительность.

                              Та же тенденция почему-то встречается и в программах отображающих атмосферное давление… накой ляд автоматически подстраивать масштаб чтобы график давления всегда занимал всю ширину экрана? что изменение на 1милиБар что на 20милиБар — одинаковая амплитуда, визуально кажется что давление меняется одинаково сильно и подвох замечаешь только при считывании масштаба по меткам на оси.

                            Only users with full accounts can post comments. Log in, please.