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

в 9:40, , рубрики: data mining, internet of things, IoT, Matlab, modbus, rs485, SDM220, ThingSpeak, визуализация данных, Разработка для интернета вещей, умный дом, электросчетчик

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

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

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

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

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

Через 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.

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

Код скрипта на 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()

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

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

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

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

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

Для напряжения настроил статистику за 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, которая при каждом запуске делает запись в канал, поэтому до полной отладки строку записи лучше закомментировать, однако даже когда скрипт готов, его нельзя просто сохранить без запуска, а запуск скрипта сразу занесет данные в канал. Удалить индивидуальные данные из канала тоже нельзя. Этот вопрос уже поднят на форуме проекта, но пока не исправлен.

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

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

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

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

Для этого графика в настройках указан 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, любые дополнения, замечания и правки приветствуются.

Автор: alk0v

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js