Розумна хатинка – 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.

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