Аналіз даних з електролічильника 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.2 f' ), # Voltage [V]
( 'Curr:', 0x06, '%6.2 f' ), # Current [A]
( 'Pact:', 0x0c, '%6.0 f' ), # Active Power («Wirkleistung») [W]
( 'Papp:', 0x12, '%6.0 f' ), # Apparent Power («Scheinl.») [W]
( 'Prea:', 0x18, '%6.0 f' ), # Reactive Power («Blindl.») [W]
( 'PF:', 0x1e, '%6.3 f' ), # Power Factor [1]
( 'Phi:', 0x24, '%6.1 f' ), # cos(Phi)? [1]
( 'Freq:', 0x46, '%6.2 f' ), # Line Frequency [Hz]
( 'Wact:', 0x0156, '%6.2 f' ), # Energy [kWh]
( 'Wrea:', 0x0158, '%6.2 f' ), # 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 показання з погодинного архіву.

Скрипт PowerPerDayreadChannelID = 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, будь-які доповнення, правки і зауваження вітаються.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.