Анализ данных с электросчетчика Eastron SDM220 средствами ThingSpeak

    Всем привет. В статье на geektimes я рассказывал, как подключиться к электросчетчику Eastron SDM220-Modbus и забрать с него данные по шине RS-485. Сегодня я хочу рассказать про сбор и анализ статистических данных о потреблении электричества в доме.



    В качестве домашнего хаба для сбора данных я использовал тонкий клиент Centerm GI-945. Его плюсы — x86 архитектура (atom 1,6 GHz), 5 USB, 1G Ethernet, mini-pcie (поставил в него wifi-карту). С флешки грузится Ubuntu Server 14.04.





    Через USB-RS485 адаптер к «серверу» подключен электросчетчик. Опрос счетчика делает скрипт на Python, за основу взял этот пример. Для работы скрипта нужна библиотека pyModbus

    Установка библиотеки
    sudo add-apt-repository ppa:fkrull/deadsnakes-python2.7
    sudo apt-get update
    sudo apt-get upgrade

    apt-get -y install python-pip
    apt-get install python2.7-dev

    pip install -U pymodbus

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

    На сайте предварительно нужно зарегистрироваться, создать свой канал данных channel и назвать поля fields. Также для записи данных в канал понадобится write API key.



    Код скрипта на Python
    #!/usr/bin/python2
    import struct
    import pymodbus.client.sync
    import binascii
    import time
    import sys
    import urllib

    def read_float_reg(client, basereg, unit=1):
    resp = client.read_input_registers(basereg,2, unit=1)
    if resp == None:
    return None
    # according to spec, each pair of registers returned
    # encodes a IEEE754 float where the first register carries
    # the most significant 16 bits, the second register carries the
    # least significant 16 bits.
    return struct.unpack('>f',struct.pack('>HH',*resp.registers))

    def fmt_or_dummy(regfmt, val):
    if val is None:
    return '.'*len(regfmt[2]%(0))
    return regfmt[2]%(val)

    def main():
    regs = [
    # Symbol Reg# Format
    ( 'V:', 0x00, '%6.2f' ), # Voltage [V]
    ( 'Curr:', 0x06, '%6.2f' ), # Current [A]
    ( 'Pact:', 0x0c, '%6.0f' ), # Active Power («Wirkleistung») [W]
    ( 'Papp:', 0x12, '%6.0f' ), # Apparent Power («Scheinl.») [W]
    ( 'Prea:', 0x18, '%6.0f' ), # Reactive Power («Blindl.») [W]
    ( 'PF:', 0x1e, '%6.3f' ), # Power Factor [1]
    ( 'Phi:', 0x24, '%6.1f' ), # cos(Phi)? [1]
    ( 'Freq:', 0x46, '%6.2f' ), # Line Frequency [Hz]
    ( 'Wact:', 0x0156, '%6.2f' ), # Energy [kWh]
    ( 'Wrea:', 0x0158, '%6.2f' ), # Energy react [kvarh]
    ]

    cl = pymodbus.client.sync.ModbusSerialClient('rtu',
    port='/dev/ttyUSB0', baudrate=9600, parity='N',stopbits=1,
    timeout=0.8)

    values = [ read_float_reg (cl, reg[1], unit=1) for reg in regs ]
    outvals = list((' '.join([fmt_or_dummy(*t) for t in zip(regs, values)])).split())
    params = urllib.urlencode({'key': 'xxxxxxxxxxxxxxxx', 'field1': outvals[0], 'field2': outvals[1], 'field3': outvals[2], 'field4': outvals[8]})
    f = urllib.urlopen(«api.thingspeak.com/update», data=params)
    print(outvals)
    sys.stdout.flush()


    if __name__ == '__main__':
    main()

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

    Результат сразу будет отображаться на сайте (на скрине показана статистика за некоторое время, при первом опросе там будет только одна точка со значением)



    По умолчанию графики отображают последние 60 показаний, что при опросе раз в минуту дает результат за последний час. Для каждого графика можно настроить отображение



    Для напряжения настроил статистику за 6 часов с усреднением по 10 значений и сглаживанием кривой (spline).

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

    Для сбора почасовой статистики сделал следующее:

    1. Создал второй канал PowerStatistic;

    2. В Apps -> MATLAB Analysis создал скрипт, который берет текущее значение энергии и вычитает из него значение час назад. Результат заносится в поле канала;

    3. В Apps -> Time Control создал событие GetPowerPerHour, которое будет каждый час в 00 минут запускать матлабовский скрипт.

    Скрипт PowerPerHour
    % ID исходного канала, в который помещаются данные со счетчика, если канал приватный, нужно указать Read API Key
    readChannelID = 154291;

    % ID канала для записи обработанных данных (PowerStatistic)
    writeChannelID = 157182;
    writeAPIKey = 'xxxxxxxxxxxxxxxxxx';

    %% Read Data %%
    data1 = thingSpeakRead(readChannelID, 'Fields', 4);
    data2 = thingSpeakRead(readChannelID, 'Fields', 4, 'NumMinutes', 60);
    value = data1-data2(1);

    %в data1 читаем последнее значение из 4-го поля (Energy)
    %чтение в data2 сделано криво, но по другому я пока не придумал, читаются последние 60 значений (за час) и берется первое из них

    %% Analyze Data %%
    % пришлось добавить округление до двух знаков, так как несмотря на то, что в исходном массиве значения лежат округленные до двух знаков после запятой, результат вычитания почему-то выглядел так: 0.2700000000000031
    analyzedData = round(value,2);

    %disp можно использовать для отладки данных
    %disp(analyzedData);

    Если в analyzedData одно значение, а не вектор, оно будет записано в первое поле канала. Для записи в другие поля нужно добавить 'Fields',2, например.
    %% Write Data %%
    thingSpeakWrite(writeChannelID, analyzedData, 'WriteKey', writeAPIKey);

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



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

    Смотрим в канале результат:



    Для этого графика в настройках указан Type: column для отображения расхода электроэнергии по часам. Всплывающее окно соответствует пику потребления в 12 часов (курор на скрине не отобразился).

    Аналогичным образом работает скрипт, собирающий статистику за сутки. Скрипт запускается в 00:01 каждого дня и суммирует 24 показания из почасового архива.

    Скрипт PowerPerDay
    readChannelID = 157182;
    readAPIKey = 'zzzzzzzzzzzzzzzzzzzzz';

    writeChannelID = 157182;
    writeAPIKey = 'xxxxxxxxxxxxxxxxxxxx';

    %% Read Data %%
    % читаем последние 24 значения из первого поля канала
    data = thingSpeakRead(readChannelID, 'ReadKey', readAPIKey, 'Fields',1, 'NumPoints',24);

    %% Analyze Data %%
    %суммируем
    analyzedData = sum(data);

    %disp(analyzedData);

    %% Write Data %%
    thingSpeakWrite(writeChannelID, analyzedData, 'WriteKey', writeAPIKey, 'Fields',2);

    Для ThingSpeak также есть приложения под Android. Для просмотра последних значений мне понравился Pocket IoT, а для графиков — ThingView. Есть также пара виджетов, но они какие-то кривые.

    » Канал PowerMeter
    » Канал PowerStatistic

    На этом, пожалуй, все. Статья не претендует на tutorial, так как я только начал знакомиться с возможностями ThingSpeak, любые дополнения, замечания и правки приветствуются.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 6

      0
      Расскажите в следующих частях чего интересного/неожиданного намерили.
        0
        На отдельную часть это не тянет, но в целом статистика забавная. Видно, как работает холодильник ночью, сколько утром потребляют чайник, тостер и микроволновка. Кстати, сдавал этот счетчик на метрологическую поверку, в свой первый класс точности входит с трехкратным запасом.
        0
        На предыдущей работе — стартапе под названием Bidgely, занимался тем, что писал алгоритмы, которые из временных рядов потребления энергии типа того, что выше вычленяли компоненты которые соответствуют стиральной машине, холодильнику, кондиционеру, насосу в бассейне и т. д. — крайне востребованный анализ в Европе, США и Австралии для тех, кто пытается понять, как сократить издержки на электричество.

        Это была очень интересная задача. Мы под неё какие-то велоспеды придумывали, но, видится мне, задача очень похожа на распознование голоса, так что я пытался раскрутить начальство начать работать в сторону рекурентных нейронных сетей. Но индусы этой идеей не прониклись, да и я ушёл в другое место.
          0
          Есть интересный проект ecois.me, там подобная аналитика делается на основании анализа спектра сигнала в сети, тоже позволяет после некоторого обучения отличить одну нагрузку от другой. Мне, честно говоря, такие подробности не сильно нужны, достаточно посуточного учета электроэнергии и наблюдения текущих показаний.
          0
          Хех, как раз себе заказал такой счетчик и на днях забрал. Спасибо за ссылку на ThingSpeak, не знал об этот проекте. Думал еще написать простую страницу, чтобы в realtime за последнюю минуту показывала параметры. Но пока еще не уверен, кроме фана и опыта, будет ли это полезно.
            0
            Я тоже думал что-то свое сгородить, но остановился на ThingSpeak, пока функционал устраивает, хотя нюансы тоже есть. Можно забирать данные с ThingSpeak на свой сайт, там уже обрабатывать как угодно.

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

          Самое читаемое