Лічильник SDM630 та OpenHAB

ля вимірювання параметрів електричної мережі на мій погляд доцільно використовувати створені для цього пристрої. Одним з таких пристроїв є лічильник електричної енергії Eastron SDM630  Наскільки я знаю він не сертифікований в Україні та не є вимірювальним приладом, але для дома ніхто не заважає його використовувати (його однофазний аналог в мене нарахував на 3 кВт більше у порівнянні з лічильником від обленерго. За цей період було спожито біля 4000 кВт*ч. Вважаю що це нормальний результат, хоча він ніяк не дає можливості робити висновки на відповідність китайського лічильника нормам). SDM630 окрім рахування спожитої енергії вимірює усі основні показники як напруга, струм, потужність активна те реактивна по фазам та у цілому та інші. Отримати ці значення можна за допомогою протоколу Modbus. Знайти опис регістрів можна наприклад за цим посиланням – SDM630-Modbus_Protocol.pdf (innon.com)

Я буду отримувати параметри електромережі за допомогою Openhub. Він має підтримку протоколу Modbus. Лічильник має порт RS485 у той час як openHAB працює у віртуальному середовищі та немає ніяких фізичних портів. Для можливості легкого переносу віртуальної машини у іншу систему віртуалізації чи апаратну платформу ніякого доступу з віртуальної машини до заліза робити не будемо. Для підключення будемо використовувати TCP2RS485 Modbus gateway. Схема виходить наступна:


Read More

Світло для ліжка

Вже давно мені не подобалась наявність тільки одного джерела світла у кімнаті. Через це треба було постійно вставати з ліжка щоб його вимкнути чи увімкнути, та й у більшості випадків треба було світло не у кімнаті, а локальне світло біля ліжка. Просто придбати маленький світильник це дуже просто та й займає він додаткове місце. Окрім цього вже багато років після ремонту ліжко чекало виготовлення узголів’я. Час прийшов, було вирішено зробити узголів’я та вмонтувати світло у нього. Основні вимоги до світла:

  • плавне вмикання/вимикання
  • наявність нічника
  • можливість керувати з будь-якої сторони ліжка

Схематично це повинно виглядати так

Створюємо креслення узголів’я, та віддаємо у меблеву майстерню на виготовлення, а тим часом переходимо до створення електроніки та програмного забезпечення.

Апаратна частина

У якості плати керування беремо саморобну плату на ESP32 котра має живлення через мережу Ethernet та перетворювач на 12В потужністю 13 Вт.
Read More

Керування кондиціонером за допомогою OpenHAB

Керування кондиціонером за допомогою системи автоматизації будинку може бути корисним, але більшість дешевих домашніх кондиціонерів не мають інтерфейсів для керування. Вони можуть керуватись тільки за допомогою інфрачервоного пульта керування. Гарна новина у тому, що зробити  пристрій котрий буде відправляти на кондиціонер таки самі команди як пульт не складно. В інтернеті можна знайти кілька готових бібліотек, мені більш сподобалась arduino-heatpumpir. Вона підтримує arduino, ESP8266 та з моєю допомогою – ESP32.

arduino-heatpumpir це бібліотека, яка дозволяє керувати кондиціонерами з якогось коду, це не готове рішення. Для керування я бажаю використовувати OpenHAB  за допомогою MQTT. У якості апаратного забезпечення я буду використовувати ESP32 модуль з підтримкою Ethernet. Програмне забезпечення модуля – ESPHome. У результаті треба створити таке рішення:

Read More

Openhab on FreeBSD: InfluxDB+Grafana persistence and graphing

Для керування домашніми приладами я використовую Openhab котрий інстальовано на FreeBSD. Як відомо, FreeBSD дуже гарна система, але є деяки ньюанси з програмним забезпеченням. З openhab ніяких проблем немає, але коли я спробував малювати графіки за допомогою Grafana проблема виникла. Сама інcтрукція по встановленню InfluxDb та Grafana є тут

На момент написанні цієї статті не виникло жодних проблем з встановленням InfluxDb та Grafana на FreeBSD (усе доступно у вигляді пакетів та встановлюється за допомогою 2-х команд). Навіть ніяких проблем з побудовою графіка у grafana. Проблема виникла у той час, коли треба було графік від grafana додати на дашбоард опенхаба. Grafana дозволяє експортувати графіки у вигляді малюнку з прямим посиланням, а опенхаб дозволяє вставляти малюнки на дашбоард. Проблема полягяла у тому, що grafana використовує phantomjs для генерування малюнку, а у пакетах цього додатка не було. На спробу експортуваи малюнок за посиланням отримуємо помилку:

Rendering failed – PhantomJS isn’t installed correctly

Перша спроба поставити з портів закінчилась невдало – помилка компіляції. Як з’ясувалось – проблема була у версії openssl, проблема вирішилась встановленням останньої версії openssl з пакетів. Після компіляції та копіювання phantomjs у папку, grafana змінила помилку на:

t=2019-02-09T15:18:25+0200 lvl=info msg=Rendering logger=rendering path="d-solo/Ita8FKXmk/heat-dashboard?orgId=1&from=1549707668905&to=1549718468906&panelId=2&width=1000&height=500&tz=Europe%2FKiev"
t=2019-02-09T15:18:25+0200 lvl=eror msg="Phantomjs exited with non zero exit code" logger=rendering error="exit status 255"
t=2019-02-09T15:18:25+0200 lvl=eror msg="Rendering failed." logger=context userId=1 orgId=1 uname=admin error="exit status 255"

Як з’ясувалось – не вистачало файла render.js. Знайти його можна за посиланням

Після копіювання цього файла до теки /usr/local/share/grafana/tools/phantomjs/ усе запрацювало як треба.

 

 

 

Встановлення та отримання стану виходу/входу за допомогою MQTT шини

Коли ви маєте вимикач та лампу, нічого вам не заважає контролювати напряму стан цієї лампи за допомогою вимикача, але ми не шукаємо простих рішень.

Маємо:

  • вимикач
  • лампа
  • openhab

Бажаємо: підключити лампу та вимикач до openhab, вимикати та вмикати лампу за допомогою цього вимикача.

Апаратне забезпечення: беремо raspberry pi (можна зробити на ESP8266 але є бажання не мати WiFi там, де його можна не мати), на вході зробимо просту схему для захисту (ну якщо вимикач буде далеко, а неподалік буде блискавка), на виході MOC3063 (навіть без додаткового сімістора вона позволяє керувати сучасними лампами).

Виходить щось таке:

 

 

 

 

 

Програмне забезпечення: spring-boot java додаток. Додаток можна знайти тут.

Openhab конфігурація:  повинна мати такий запис у секції items:

Switch PI1_SW_1 { mqtt=">[broker:/java-switch/gpio/out/GPIO 2:state:OFF:LOW],>[broker:/java-switch/gpio/out/GPIO 2:state:ON:HIGH],<[broker:/java-switch/gpio/in/GPIO 0:state:MAP(HILO.map)]" }

Як наслідок, воно працює. Затримка між командою зі станом та між та командою на зміну стану є приблизно 50 мс.

Як додаток можна подивитись (та змінити) поточний стан за допомогою веб інтерфейсу:

 

Розумна хатинка – OpenHAB, підрахунок електроенергії

Трохи раніше ми налаштували OpenHAB записувати усі історичні данні до бази даних.

На даний момент тестова система керує розеткою, до якої підключено бойлер.
Розетка може вимірювати струм, значення струму заноситься до бази даних.
Щоб підрахувати скільки електроенергії було витрачено бойлером підключимось напряму до бази даних. Ми використовуємо базу H2, тому можна підключитись з браузера, просто перейшовши за адресою – http://192.168.0.6:8082/
База має просту структуру. Одну таблицю ITEMS та таблиці ITEMXXXX які містять дані.
Зробимо запрос

SELECT * FROM ITEMS

на що отримаємо відповідь:

з відповіді можна побачити, що  значення з датчика BATHROOM_BOILER1_CURRENT_1 пишуться у таблицю ITEM0007.

Усі таблиці мають дуже простий формат – стовпчики TIME та VALUE. Для підрахунку кількості витраченої електроенергії виконаємо такй запрос:

SELECT formatedtime,
       sum((previous/1000.0)*230*TIMESTAMPDIFF(SECOND, prevtime, currenttime)*0.000277778/1000.0) AS power
FROM
  (SELECT @prevtime AS prevtime,
          SET(@prevtime,TIME)currenttime,
          FORMATDATETIME(TIME, 'yyyyMM') AS formatedtime,
          @prev AS previous,
          SET(@prev,value)CURRENT
   FROM ITEM0007
   ORDER BY TIME) AS TBL
GROUP BY formatedtime
ORDER BY formatedtime

Для простоти будемо вважати, що напруга у мережі постійна та дорівнює 230В.
У результаті отримаємо кількість споживаної електроенергії по місяцям:

Якщо переписати запроси щоб отримати суми по днях, експортувати ці данні у excel то можна отримати такий графік:

OpenHAB – моніторінг напруги у мережі

Вимоги

  • Openhab на ubuntu
  • Back-UPS XS 1100CI (можна використовувати будь-який інший, але в мене саме такий)

Підготовка

Встановлення Apcupsd

Інструкцію можна знайти наприклад за цим посиланням.

Як результат ми повинні мати змогу запустити команду apcaccess, результат виводу котрої ми й будемо використовувати

pi@openhab:/etc/openhab2 $ apcaccess
APC      : 001,036,0868
DATE     : 2017-07-15 12:12:51 +0300
HOSTNAME : openhab
VERSION  : 3.14.12 (29 March 2014) debian
UPSNAME  : openhab
CABLE    : USB Cable
DRIVER   : USB UPS Driver
UPSMODE  : Stand Alone
STARTTIME: 2017-07-15 11:02:42 +0300
MODEL    : Back-UPS XS 1100CI
STATUS   : ONLINE
LINEV    : 236.0 Volts
LOADPCT  : 1.0 Percent
BCHARGE  : 100.0 Percent
TIMELEFT : 269.3 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME  : 0 Seconds
SENSE    : Medium
LOTRANS  : 155.0 Volts
HITRANS  : 280.0 Volts
ALARMDEL : No alarm
BATTV    : 27.2 Volts
LASTXFER : No transfers since turnon
NUMXFERS : 0
TONBATT  : 0 Seconds
CUMONBATT: 0 Seconds
XOFFBATT : N/A
SELFTEST : NO
STATFLAG : 0x05000008
SERIALNO : XBXXXXX0XXXX
BATTDATE : 2015-03-17
NOMINV   : 230 Volts
NOMBATTV : 24.0 Volts
NOMPOWER : 660 Watts
FIRMWARE : 920.T4 .I USB FW:T4
END APC  : 2017-07-15 12:12:51 +0300

 

Підготовка OpenHAB

Відкриємо панель конфігурування OpenHAB та встановимо

RegEx Transformation

Конфігурування OpenHAB

things

Створимо файл /etc/openhab2/things/system.things

Thing exec:command:apc [command="/sbin/apcaccess -p LINEV", transform="REGEX((\\d+.\\d+).*)", interval=5, timeout=1, autorun=true]

items

Створимо файл /etc/openhab2/items/system.items

String SYSTEM_APC_VOLTAGE "[%s]" (SYSTEM) {channel="exec:command:apc:output"}
Number SYSTEM_APC_VOLTAGE_DOUBLE "Напруга [%.1fВ]" <energy> (SYSTEM)

Item SYSTEM_APC_VOLTAGE_DOUBLE треба через те, що exec повертає строку, а нам треба число. Створимо правило для перетворення строки до числа

rules

Створимо файл /etc/openhab2/rules/system.rules

rule "Convert System APC voltage"
when
  Item SYSTEM_APC_VOLTAGE changed
then
   SYSTEM_APC_VOLTAGE_DOUBLE.postUpdate(SYSTEM_APC_VOLTAGE.state.toString)
end

persist

Створимо конфігурацію для зберігання напруги до бази даних. Додамо строку

        SYSTEM_APC_VOLTAGE_DOUBLE : strategy = everyMinute

у файл /etc/openhab2/persistence/jdbc.persist

sitemap

Створимо графік для відображення історічних даних

Додамо строку

Chart label="Voltage" item=SYSTEM_APC_VOLTAGE_DOUBLE period=12h refresh=300

у файл /etc/openhab2/sitemaps/house.sitemap

Як результат маємо такий графік:

 

 

 

Розумна хатинка – OpenHAB, зберігання історії

У цієї статті мова піде про те, як зберігати історичні дані та потім строїти графіки. Це дає змогу потім ці дані аналізувати. Наприклад кондиціонер, обігрівач, нагрівач води витрачає більше електроенергії коли увімкнений постійно чи тільки коли треба. Та інше.

Для зберігання даних будемо використовувати базу даних H2.

Встановлення бази даних

Завантажимо архів та розпакуємо у теку наприклад /opt/h2v3

Створимо теку для бази даних: /opt/h2/db

Для запуску створемо скріпт  /opt/h2v3/bin/start.sh

#!/bin/sh
cd /opt/h2v3/bin/
java -cp ./h2-1.3.175.jar org.h2.tools.Server -web -webPort 8081 -webAllowOthers -tcp -tcpPort 8082 -tcpAllowOthers -baseDir /opt/h2/db

Для запуску бази діних під час старту системи створимо файл /etc/systemd/system/h2.service

[Unit]
Description=H2 database
After=h2.target
Before=openhab2.service

[Service]
ExecStart=/opt/h2v3/bin/start.sh

[Install]
WantedBy=default.target

Увімкнемо цей сервіс під час старту системи за допомогою команди

sudo systemctl enable h2.service

Конфігурування OpenHAB для зберігання даних

Встановимо JDBC Persistence H2 addon

 

Додаємо шлях до бази даних у файл /etc/openhab2/services.jdbc.cfg

url=jdbc:h2:tcp://localhost:8082/openhab-db

Створимо конфігурацію для зберігання усіх значеннью Для цього створимо файл /etc/openhab2/persistence/jdbc.persist:

Strategies {
        // if no strategy is specified for an item entry below, the default list will be used
        everyMinute     : "0 * * * * ?"
        every5Minutes : "0 */5 * * * ?"
        everyHour   : "0 0 * * * ?"
        everyDay    : "0 0 0 * * ?"
        default = everyChange
}

Items {
    // persist all items once a day and on every change and restore them from the db at startup
        BATHROOM*, ROOM1* : strategy = everyChange, everyMinute, everyDay, restoreOnStartup
}

Все. OpenHAB повинен створити усі таблиці та почати записувати данні:

 

Оновимо конфігурацію сайту (додамо графік):

sitemap house label="Мій дім" {
        Frame label="Дата" {
                Text item=Date
        }

        Frame label="Ванна" {
                Switch item=BATHROOM_BOILER_1
                Text item=BATHROOM_BOILER1_CURRENT_1
                Text item=BATHROOM_BOILER1_CURRENT
        }

        Frame label="History" {
                Chart label="Current" item=BATHROOM_BOILER1_CURRENT_1 period=12h refresh=300
        }
}

У результаті отримаємо таку сторінку

 

 

 

 

Розумна хатинка – OpenHAB

Виникла в мене ідея автоматизувати квартиру. В інтернеті є безліч готових варіантівю Дуже гарний перелік ви можете знайти за цим посиланням.

У тестовому варіанті ми зробимо вмикання вимикання світлодіода, та отримання рівня температури та вологості. У якості ядра розумної хатинки будемо використовувати OpenHAB, протокол обміну – ModBus. Повна схема буде виглядати так:

 

Для повторення всього, про що піде мова далі вам необхідно мати:

Програмне забезпечення

  • AtmelStudio, WinAVR чи щось інше, що надає можливість компілювати с код для мікроконтролерів Atmel (я використовував WinAVR-20100110)
  • OpenHAB

Апаратне забезпечення

  • Будь-що з підтримкою java
  • USB to RS2485 converter
  • AVR програматор
  • AT90S8515 (ви можете використовувати будь який інший, в мене просто є купа таких)
  • кілька резисторів 4К7
  • кнопка
  • світлодіод
  • монтажна плата
  1. Встановлення та конфігурація OpenHAB

Для встановлення OpenHAB його треба скачати та розпакувати. На цьому інсталяція завершена та можна починати його конфігурувати.

Конфігурування розширення Modbus

Для цього треба створити файл conf/services/modbus.cfg

#LEDS on Device 2
modbus:serial.slave5.connection=COM3:115200:8:none:1:rtu:35:2000:none:none
modbus:serial.slave5.id=2
modbus:serial.slave5.start=0
modbus:serial.slave5.length=8
modbus:serial.slave5.type=coil

#BUTTONS on Device 2
modbus:serial.slave6.connection=COM3:115200:8:none:1:rtu:35:2000:none:none
modbus:serial.slave6.id=2
modbus:serial.slave6.start=0
modbus:serial.slave6.length=8
modbus:serial.slave6.type=discrete

У моєму випадку AVR було підключено до порта COM3

Створюємо items.

Для цього треба створити файл  conf/items/modbus.items

Group  ROOM1

Contact ROOM1_SW_LIGHT_BTN_2 "Light Button 2" (ROOM1) {modbus="slave6:1"}

Switch ROOM1_SW_LIGHT_LAMP_2 "Світло 2" <light> (ROOM1) {modbus="slave5:2"}

Створюємо sitemap

sitemap test label="Мій дім" {
	Frame label="Комната 1" {
		Switch item=ROOM1_SW_LIGHT_LAMP_2

	}

}

Після цього треба сконфігорувати Classic-UI

Створюємо правило щоб обробляти команди від кнопки

rule "Light room 2 ON"
when
  Item ROOM1_SW_LIGHT_BTN_2 changed from OPEN to CLOSED
then
    if (ROOM2_SW_LIGHT_LAMP_2.state!=ON)      
        ROOM1_SW_LIGHT_LAMP_2.sendCommand(ON)
    else
        ROOM2_SW_LIGHT_LAMP_2.sendCommand(OFF)
end

 

2. Створюємо апаратну частину.

Принципова схема

Повинно вийти щось таке:

 

3. Компілюємо програму

 
#define clientAddress 0x02

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include "yaMBSiavr.h"

#define LIGHLCD PC7
#define LIGHLCDDDR DDRC
#define LIGHLCDPORT PORTC


volatile uint8_t instate = 0;
volatile uint8_t outstate = 0;
volatile uint16_t inputRegisters[4];
volatile uint16_t holdingRegisters[4];

void timer0100us_start(void) {
	TCCR0|=(1<<CS01); //prescaler 8
	TIMSK|=(1<<TOIE0);
}

/*
*   Modify the following 3 functions to implement your own pin configurations...
*/
void SetOuts(volatile uint8_t in) {
	PORTD|= (((in & (1<<3))<<4) | ((in & (1<<4))<<1) | ((in & (1<<5))<<1));
	PORTB|= (((in & (1<<0))<<2) | ((in & (1<<1))) | ((in & (1<<2))>>2));
	in=~in;
	PORTB&= ~(((in & (1<<0))<<2) | ((in & (1<<1))) | ((in & (1<<2))>>2));
	PORTD&= ~(((in & (1<<3))<<4) | ((in & (1<<4))<<1) | ((in & (1<<5))<<1));
}

uint8_t ReadIns(void) {
	uint8_t ins=0x00;
	ins|=(PINC&((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)));
	ins|=(((PIND&(1<<4))<<2)|((PIND&(1<<3))<<4));
	return ins;
}

void io_conf(void) { 
	/*
	 Outputs: PB2,PB1,PB0,PD7,PD5,PD6
	 Inputs: PC0, PC1, PC2, PC3, PC4, PC6, PD4, PD3
	*/
	DDRD=0x00;
	DDRB=0x00;
	DDRC=0x00;
	PORTD=0x00;
	PORTB=0x00;
	PORTC=0x00;
	PORTD|=(1<<0);
	DDRD |= (1<<2)|(1<<5)|(1<<6)|(1<<7);
	DDRB |= (1<<0)|(1<<1)|(1<<2)|(1<<3);

	// set ports as output
	LIGHLCDDDR |= (1<<LIGHLCD);

}

ISR(SIG_OVERFLOW0) { //this ISR is called 9765.625 times per second
	modbusTickTimer();
}

void modbusGet(void) {
	if (modbusGetBusState() & (1<<ReceiveCompleted))
	{
		LIGHLCDPORT |= _BV(LIGHLCD);
		//PUMPPORT &= ~_BV(PUMP);
		switch(rxbuffer[1]) {
			case fcReadCoilStatus: {
				modbusExchangeBits(&outstate,0,8);
			}
			break;
			
			case fcReadInputStatus: {
				volatile uint8_t inps = ReadIns();
				modbusExchangeBits(&inps,0,8);
			}
			break;
			
			case fcReadHoldingRegisters: {
				modbusExchangeRegisters(holdingRegisters,0,4);
			}
			break;
			
			case fcReadInputRegisters: {
				modbusExchangeRegisters(inputRegisters,0,4);
			}
			break;
			
			case fcForceSingleCoil: {
				modbusExchangeBits(&outstate,0,8);
				SetOuts(outstate);
			}
			break;
			
			case fcPresetSingleRegister: {
				modbusExchangeRegisters(holdingRegisters,0,4);
			}
			break;
			
			case fcForceMultipleCoils: {
				modbusExchangeBits(&outstate,0,8);
				SetOuts(outstate);
			}
			break;
			
			case fcPresetMultipleRegisters: {
				modbusExchangeRegisters(holdingRegisters,0,4);
			}
			break;
			
			default: {
				modbusSendException(ecIllegalFunction);
			}
			break;
		}
	}
}

int main(void)
{
	io_conf();
	sei();
	modbusSetAddress(clientAddress);
	modbusInit();
    wdt_enable(7);
	timer0100us_start();

	holdingRegisters[0] = 0x0A;
	holdingRegisters[1] = 0x0B;
	holdingRegisters[2] = 0x0C;
	holdingRegisters[3] = 0x0D;
    while(1)
    {
		wdt_reset();
	    modbusGet();
    }
}

Для компілювання вам буде потрібна бібліотека ModBus.

Після компіляції прошиваємо мікроконтролер, та запускаємо усе. Повинно вийти щось таке:

Якщо щось не працює вам може допомогти

QModBus – додаток для тестування роботи шини. Дозволяє надсилати команди пристроям та дивитись відповіді.

Після міграції всього на Raspberry Pi можна отримати таку конфігурацію:

2 пристроя на шині ModBus, OpenHAB на Rasbrerry Pi.

Один має датчик температури та вологості, лампу та кнопку. Інший має тільки кнопку та лампу.