OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Обсуждение статей, технологий домашней автоматизации, программных и аппаратных решений
Selecta
Сообщения: 31
Зарегистрирован: 26 сен 2015, 12:38

OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение Selecta » 16 окт 2015, 02:26

По просьбе в личных сообщениях, делюсь своими настройками для интеграции Beckhoff с системой "умного дома" OpenHAB. Интересующихся общими принципами функционирования OpenHAB отправляю к краткому обзору на Хабре - http://habrahabr.ru/post/232969/. От себя отмечу, что OpenHab полностью удовлетворил мои запросы по программированию и визуализации УД - масса binding'ов для любого оборудования, простой язык правил и скриптов, неплохие средства визуализации, стабильная работа даже под Windows (у меня крутится под 10) - в общем, все что нужно для непритязательного старта. В стандартном наборе - binding'и для связи с более чем 50 системами (от Z-Wave, KNX и EnOcean до проекторов Epson и кондиционеров Daikin). То что уже работает у меня - мультирум через Softsqueeze (стандартный байндинг Squeezebox), голосовое управление с андроид-планшета, анализ голосовых команд (пока ограничено "поставь Гребенщикова в спальне", "поставь джаз в гостиной", "сделай свет ярче на кухне" и т.п.), голосовая обратная связь через Yandex TTS, интеграция с гугль-календарем и сервисами погоды. Если интересно - в последующих сообщениях расскажу подробнее с примерами кода.

Ну а пока про то, как подружить его с Beckhoff. Структура ПЛК, похоже, препятствует прямому обращению по Modbus к битовым регистрам (coils) - по крайней мере, обратиться к ним у меня не получилось ни из OpenHAB, ни из внешних программ типа Modbus Poll - при обращении "read coil", "write coil" - сообщение об ошибке "неправильный адрес" в ответ. Если кто-то знает, как это победить - буду признателен за совет. Возможно, поможет настройка в KS2000. Ну а пока что я научился только читать-писать пословно в область памяти с адреса 16384 (0х4000) - это позволяет мне обмениваться данными с OpenHAB, хотя и не дает возможности напрямую взаимодействовать с аппаратными входами-выходами устройства. Приходится прибегать к программным костылям, но это проблема не самая страшная.

Итак, конфиг OpenHAB (не забудьте скопировать в папку addons соответствующий байндинг для Modbus - org.openhab.binding.modbus-1.7.1):

Код: Выделить всё

modbus:tcp.slave1.connection=192.168.0.108:502
modbus:tcp.slave1.id=1
modbus:tcp.slave1.start=0
modbus:tcp.slave1.length=16
modbus:tcp.slave1.type=holding

modbus:tcp.slave2.connection=192.168.0.108:502
modbus:tcp.slave2.id=1
modbus:tcp.slave2.start=16384
modbus:tcp.slave2.length=16
modbus:tcp.slave2.type=holding


slave1 у меня умеет читать из Beckhoff, а slave2 - читать и писать

описание тестовых айтемов (для отслеживания и управления выходами Beckhoff):

Код: Выделить всё

Switch Beckhoff_Input10   (gModbus)   { modbus="slave1:0"}
Switch Beckhoff_Input11   (gModbus)   { modbus="slave1:1"}

Switch Beckhoff_Input20   (gModbus)   { modbus="slave2:0"}
Switch Beckhoff_Input21   (gModbus)   { modbus="slave2:1"}


и отображение их на сайтмэпе:

Код: Выделить всё

   Frame {
      Group item=gModbus label="Modbus"
   }


Далее, описания переменных для "общения" с OpenHAB в программе ПЛК:

Код: Выделить всё

VAR_GLOBAL
   OH_I1      AT %QB128:   INT;       //  "slave1:0"
   OH_I2      AT %QB130:   INT;        //  "slave1:1"
         OH_O1      AT %MB0:       INT;        //  "slave2:0"
         OH_O2      AT %MB2:       INT;          //  "slave2:1"
   IN_E_K1      AT %IX0.0:   BOOL;      // кнопка аппаратного входа
   IN_E_K2      AT %IX0.1:   BOOL;      // кнопка аппаратного входа
   OUT_E_L1    AT %QX0.0:   BOOL;   // выход на реле (лампочка)
   OUT_E_L2   AT %QX0.1:   BOOL;      // выход на реле (вентилятор)
END_VAR


Для экспериментов была взята программа из темы про "Элементы умного дома на Beckhoff", включающая лампочку и вентилятор. Логика работы простая - короткое нажатие в темноте включает лампочку, длинное - включает лампочку и вентилятор, короткое нажатие при включенной лампочке и/или вентиляторе выключает лампочку, а вентилятор остается включенным на заданный период времени, длинное нажатие при включенной лампочке и вентиляторе выключает сразу и то, и то.

Без участия OpenHAB все было достаточно просто - два таймера, каждый со своей логикой в ПЛК, и все работало как часы. Но подключив все это хозяйство к OpenHAB, сразу возникло желание не только видеть в OpenHAB состояние лампочки и вентилятора, но и иметь возможность независимо включать и выключать оба прибора из программной оболочки, параллельно с аппаратной кнопкой. Что естественно привело к конфликту приоритетов - что считать более главным - нажатия кнопки или команды OpenHAB.

В конечном итоге после двух вечеров экспериментов решение приняло такой вид:

Функциональный блок кнопки без таймера (нужно для принудительного включения-выключения):

Код: Выделить всё

FUNCTION_BLOCK SM_BUTT
VAR_INPUT
   IN: BOOL;
END_VAR
VAR_OUTPUT
   Q:BOOL := FALSE;
END_VAR
VAR
   MEM:BOOL := FALSE;
END_VAR


IF IN AND NOT MEM THEN
   Q:= NOT Q;
END_IF

   MEM := IN;


Функциональный блок кнопки с таймерами:

Код: Выделить всё

FUNCTION_BLOCK SM_BUTT_TIMER
VAR_INPUT
   IN: BOOL;      (* вход за которым следим *)
   TC: TIME;      (* время длинного нажатия  *)
   TC2: TIME;      (* время работы вентилятора *)
END_VAR
VAR_OUTPUT
   Q1: BOOL := FALSE;      (* состояние лампочки *)
   Q2: BOOL := FALSE;      (* состояние вентилятора  *)
END_VAR
VAR
   TX: TON;
   TX2: TON;
   MEM1, MEM2, MEM3: BOOL;
END_VAR

TX (IN := IN, PT := TC);       (*  отправляем данные в таймеры *)
TX2(IN := NOT Q1, PT:=TC2);

IF IN AND NOT MEM1  THEN        (* если нажали аппаратную кнопку *)
   Q1 := NOT Q1;         (* сразу меняем состояние лампочки *)
END_IF

IF TX.Q AND NOT MEM2  THEN      (* сигнал таймера1 когда лампочка горит *)
   Q2 := Q1;               (*  состояние вентилятора = состоянию лампочки *)
END_IF

IF TX2.Q AND  NOT MEM3   THEN         (* сигнал от таймера 2 *)
   IF NOT Q1 THEN               (* если лампочка выключена  *)
      Q2 := FALSE;               (* выключить и вентилятор *)
   END_IF
END_IF

MEM1 := IN;
MEM2 := TX.Q;
MEM3 := TX2.Q;



Ну и основная программа:

Код: Выделить всё

PROGRAM MAIN
VAR
   BUTT_E_B1:SM_BUTT;
   BUTT_E_B2:SM_BUTT_TIMER;
   LampState , FanState: BOOL := FALSE;
END_VAR


IF NOT (INT_TO_BOOL(OH_O1) = LampState) THEN             (* Если поменялось состояние лампочки в OpenHAB *)
      BUTT_E_B2 (IN:=TRUE, TC:=t#1s, TC2:=t#10s);       (*  "нажать" на аппаратную кнопку программно *)
   ELSE
      BUTT_E_B2 (IN:=IN_E_K1, TC:=t#1s, TC2:=t#10s);   (* иначе запустить обычную проверку нажатия *)
END_IF

OUT_E_L1 := BUTT_E_B2.Q1;                     (* переключить выход лампочки *)      
OH_O1 := BOOL_TO_INT(OUT_E_L1);                  (* и сохранить значение в OpenHAB *)
LampState := OUT_E_L1;

IF NOT (INT_TO_BOOL(OH_O2) = FanState) THEN         (* если поменялось состояние вентилятора в OpenHAB *)
      FanState := INT_TO_BOOL(OH_O2);            (* переключить вентилятор *)
   ELSE
      FanState := BUTT_E_B2.Q2;               (* иначе присвоить вентилятору состояние выхода по значению кнопки *)
END_IF

OUT_E_L2 := FanState;
OH_O2 := BOOL_TO_INT(OUT_E_L2);



Сильно не пинайте - понимаю, что код корявый, и изящнее было бы использовать триггеры, но поскольку это моя первая программа для ПЛК, пока что не хватает опыта. В будущем перепишу покрасивее, и буду признателен за советы.

Но в таком виде все работает отлично - аппаратная кнопка полностью выполняет свою функцию, все включения-выключения лампочки и вентилятора видны в интерфейсе OpenHAB, и принудительное переключение элементов интерфейса мышкой вызывает соответствующую реакцию выходов Beckhoff.

Как-то так. Если будут вопросы - задавайте. Ну и буду рад вашим собственным описаниям интеграции устройств с OpenHAB и прикольных сценариев для него, так как только начинаю его осваивать. Но подчеркну еще раз - система полностью удовлетворяет мои немудреные потребности. Я не представляю задачи по домашней автоматизации, которую с ее помощью невозможно было бы решить. Недостаток - отсутствие нормальной документации, но активное сообщество частично это компенсирует. Любую задачу или проблему кто-то уже решал до тебя, нужно только найти это обсуждение в гугле.

scorp309
Сообщения: 35
Зарегистрирован: 12 окт 2011, 11:21

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение scorp309 » 20 окт 2015, 22:43

Не получается заставить работать openhab и bc9000 совместно.
Что сделал:

Код: Выделить всё

openhab_default.cfg

modbus:poll=500
modbus:slave1.host=192.168.121.9
modbus:slave1.type=holding
modbus:slave1.id=1
modbus:slave1.start=16384
modbus:slave1.length=16


Код: Выделить всё

demo.items

Group FF_Modbus      "Modbus"               (All)
Switch Beckhoff_Input10            "CL10"         (FF_Modbus){modbus="slave1:0"}
Switch Beckhoff_Input11            "CL11"         (FF_Modbus){modbus="slave1:1"}
Switch Beckhoff_Input12            "CL12"         (FF_Modbus){modbus="slave1:2"}
Switch Beckhoff_Input13            "CL13"         (FF_Modbus){modbus="slave1:3"}
Switch Beckhoff_Input14            "CL14"         (FF_Modbus){modbus="slave1:4"}
Switch Beckhoff_Input15            "CL15"         (FF_Modbus){modbus="slave1:5"}
Switch Beckhoff_Input16            "CL16"         (FF_Modbus){modbus="slave1:6"}
Switch Beckhoff_Input17            "CL17"         (FF_Modbus){modbus="slave1:7"}
Switch Beckhoff_Input18            "CL18"         (FF_Modbus){modbus="slave1:8"}


Код: Выделить всё

demo.sitemap

   Frame label="Test" {
      Text label=Test_Frame icon="attic" {
      Frame {
   Switch item= Beckhoff_Input10
   Switch item= Beckhoff_Input11
   Switch item= Beckhoff_Input12
   Switch item= Beckhoff_Input13
   Switch item= Beckhoff_Input14
   Switch item= Beckhoff_Input15
   Switch item= Beckhoff_Input16
   Switch item= Beckhoff_Input17
   Switch item= Beckhoff_Input18
               }


19 кнопок сделал для отлова адресации, на случай если неправильно что то где то прописал.

В bc9000 программа следующая

Код: Выделить всё

PROGRAM MAIN
VAR
   BUTT_MB1      :   SM_BUTT;
   LampState1: BOOL := FALSE;
END_VAR

IF NOT (INT_TO_BOOL(OH_O1) = LampState1) THEN
      BUTT_MB1 (IN:=TRUE);
   ELSE
      BUTT_MB1 (IN:=IN_MB1);
END_IF

OUT_MB1_L:=BUTT_MB1.Q;
OH_O1:= BOOL_TO_INT(OUT_MB1_L);
LampState1 := OUT_MB1_L;

Код: Выделить всё

VAR_GLOBAL
   OH_O1            AT %MB0:   INT;   (*slave1:0*)
END_VAR

Код: Выделить всё

VAR_GLOBAL
   IN_MB1            AT %IX0.2:   BOOL;

   OUT_MB1_L         AT %QX0.1:   BOOL;
END_VAR

С кнопки работает - лампа зажигается, но в вэб-интерфейсе всё глухо, такое ощущение, что связи с контроллером нету. C modbus pool при ручном вводе значений в ячейку памяти тоже всё работает.
Где я накосячил?

Selecta
Сообщения: 31
Зарегистрирован: 26 сен 2015, 12:38

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение Selecta » 21 окт 2015, 10:36

modbus:slave1.host=192.168.121.9

Где я накосячил?


Скорее всего - в описании modbus. Потому что правильное ключевое слово connection, а не host. Посмотрите в первом сообщении темы.

А вообще - есть смысл смотреть лог-файл при инициализации openhab. Все байндинги там отписываются и можно найти проблему.

scorp309
Сообщения: 35
Зарегистрирован: 12 окт 2011, 11:21

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение scorp309 » 21 окт 2015, 12:47

Host было в дефолтном конфиге openhab. Я только расскомментировал строку и вписал IP

В логах ничего не пишет вообще упоминается только в openhab.log

Код: Выделить всё

[INFO ] [.service.AbstractActiveService] - Modbus Polling Service has been started


Да у меня openhab на винде 7. Надо наверно линуксовую машину организавать на попробовать.

Selecta
Сообщения: 31
Зарегистрирован: 26 сен 2015, 12:38

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение Selecta » 21 окт 2015, 22:15

Host было в дефолтном конфиге openhab


Я тоже на эти грабли наступал. Кроме дефолтного конфига нужно читать описания байндингов. В конфиге есть устаревшие моменты, которые есть только в описании и в обсуждениях на гугльгруппах.

Да у меня openhab на винде 7. Надо наверно линуксовую машину организавать на попробовать.


У меня работает под Windows 10 без проблем.

scorp309
Сообщения: 35
Зарегистрирован: 12 окт 2011, 11:21

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение scorp309 » 21 окт 2015, 23:42

Как я и ожидал - ошибка идиотская :oops:

    modbus:tcp.slave1.connection=192.168.121.9
    modbus:tcp.slave1.type=holding
    modbus:tcp.slave1.id=1
    modbus:tcp.slave1.start=16384
    modbus:tcp.slave1.length=16

scorp309
Сообщения: 35
Зарегистрирован: 12 окт 2011, 11:21

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение scorp309 » 23 окт 2015, 22:34

Немного повозился с кодом. Смущала монструозность программы. На выходе получилось, что переменные LampState/FanState и не нужны, вместо них можно использовать состояние выходов. И условие IF из основной программы можно перенести в функцию кнопки.
Переменные для OpenHAB у меня прописаны данным образом

Код: Выделить всё

H2_R1_L            AT %MB0:   INT;

И работает это только с чётными значениями почему то, если прописать MB1 - ругается Invalid type INT at address: %MB1
Кто-нибудь знает почему?

Поехали по коду

Код: Выделить всё

FUNCTION_BLOCK SM_BUTT_OH   (*ОБЫЧНАЯ КНОПКА *)
VAR_INPUT
   IN: BOOL;               (*ВХОД ЗА КОТОРЫМ СЛЕДИМ*)
   MB: INT;                  (*ЗНАЧЕНИЕ В ПАМЯТИ ДЛЯ OPENHAB*)
   OUT: BOOL;               (*СОСТОЯНИЕ ВЫХОДА*)
END_VAR
VAR
   MEM : BOOL := FALSE;         (*ВНУТРЕННЯЯ ПЕРЕМЕННАЯ ДЛЯ ХРАНЕНИЯ СОСТОЯНИЯ ВХОДА *)
END_VAR
VAR_OUTPUT
   Q: BOOL:=FALSE;            (*СОСТОЯНИЕ ВЫХОДА НА ЛАМПОЧКУ*)
END_VAR
---------------------------------
IF NOT(INT_TO_BOOL(MB) = OUT) THEN   (*УСЛОВИЕ IF, КОТОРОЕ ПЕРЕНЕСЛИ ИЗ ОСНОВНОЙ ПРОГРАММЫ*)
      Q:= NOT Q;
   ELSE
      IF IN AND NOT MEM THEN (*ПОЙМАЛИ НАЖАТИЕ НА КНОПКУ*)
         Q:= NOT Q;         (*МЕНЯЕМ СОСТОЯНИЕ ВЫХОДА НА ПРОТИВОПОЛОЖНОЕ*)
      END_IF
END_IF
      MEM := IN; (*ЗАПОМИНАЕМ ТЕКУЩЕЕ СОСТОЯНИЕ ВХОДА*)


В результате в основной программе будем иметь:

Код: Выделить всё

PROGRAM MAIN
VAR
   BUTT_H2_R1   :   SM_BUTT_OH;
   BUTT_H2_R2   :   SM_BUTT_OH;
END_VAR
---------------------------------
BUTT_H2_R1 (IN:=IN_H2_R1 OR  IN_H2_R2, OUT:=OUT_H2_R1_L, MB:=H2_R1_L);   (*ВАРИАНТ С ПРОХОДНЫМ ВЫКЛЮЧАТЕЛЕМ*)
   OUT_H2_R1_L:=BUTT_H2_R1.Q;
   H2_R1_L:= BOOL_TO_INT(OUT_H2_R1_L);
   
BUTT_H2_R2 (IN:=IN_H2_R3, OUT:=OUT_H2_R2_L, MB:=H2_R2_L);            (*ОБЫЧНАЯ ОРДИНАРНАЯ КНОПКА*)
   OUT_H2_R2_L:=BUTT_H2_R2.Q;
   H2_R2_L:= BOOL_TO_INT(OUT_H2_R2_L);


Пояснение небольшое
    IN_H2_R1, IN_H2_R2 и IN_H2_R3 - входные контакты
    OUT_H2_R1_L и OUT_H2_R2_L - выходы
    H2_R1_L и H2_R2_L - переменные в который пишется состояние выходов и с которыми взаимодействует OpenHAB

Конструктивная критика приветствуется. Я не программист ни разу, так что написал как смог :D

Дальше в планах разобраться с таймером (у меня по длительному нажатию кнопки в прихожей выключался весь свет в квартире)

Selecta
Сообщения: 31
Зарегистрирован: 26 сен 2015, 12:38

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение Selecta » 24 окт 2015, 01:57

И работает это только с чётными значениями почему то, если прописать MB1 - ругается Invalid type INT at address: %MB1
Кто-нибудь знает почему?


Потому что INT занимает два байта.

empenoso
Сообщения: 587
Зарегистрирован: 11 ноя 2015, 08:03
Откуда: Пермь

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение empenoso » 27 авг 2016, 22:39

В чем-то есть принципиальное отличие между ПЛК в частности Beckhoff (или ОВЕН) и контроллера MegaD для применения в домашней автоматизации?

d.v.ermakov
Сообщения: 444
Зарегистрирован: 29 май 2015, 21:23
Откуда: Екатеринбург, Нижний Тагил

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение d.v.ermakov » 28 авг 2016, 06:01

У Меги прошивка открытая (и есть 1wire,dht,ir поэтому). И дешевле она.

flighttothemoon
Сообщения: 101
Зарегистрирован: 27 мар 2011, 02:15

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение flighttothemoon » 07 дек 2016, 03:05

А не логичнее ли связать beckhoff и openhab через TCP Binding?

Pagan
Сообщения: 17
Зарегистрирован: 25 авг 2013, 16:50

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение Pagan » 25 янв 2017, 22:36

Господа, а не подскажете случаем как настроить библиотечные блоки modbus TCP server на TwinCAT? Для связи с ОН. У меня контролёр СХ9000.

scorp309
Сообщения: 35
Зарегистрирован: 12 окт 2011, 11:21

Re: OpenHAB - интеграция с Beckhoff, первые шаги по освоению

Сообщение scorp309 » 26 окт 2017, 13:36

2 года пролетели как неделя :roll: Beckhoff работает и не жужжит, а вот OpenHab пару раз ломался при обновлении. Стал вносить изменения небольшие в электрическую схему квартиры и понадобилось опять углубляться в настройку опенхаба и бехкофа.
По-человечески работу с таймером настроить не получилось (даже привлечение Си программиста не помогло), точнее оно работало конечно, но немного не так как задумывалось. В принципе жить можно и было оставлено так. Потому свой корявый код не решился выставлять на публичное обозрение.

В общем вернулся к настройке и даже есть что показать :D
В программе глаза мозолили постоянные преобразования INT-to-BOOL и обратно и хотелось всё-таки, чтобы корректно работало длительное нажатие. А тут ещё подкатила задача отрабатывать двойной клик! Ну и стал ковырять настройки OpenHab и программу Beckhoff.

Откатился к версии программы, которую написал на основе исходников Уважаемого Ali (там всё работало корректно и исключительно на BOOL переменных). И стал прикручивать к этому коду OpenHab2. В общем вылезла такая закономерность - опенхаб читает ячейки памяти с контроллера целым словом и корректно соотносит биты в этом слове с переключателями в интерфейсе, но при записи перезаписывает слово целиком и затирает состояния остальных ячеек. Пример: слово - это 2 байта или 16 бит в которых записывается 0 или 1 в зависимости от состояния выхода (вкл/выкл). Для визуализации

Код: Выделить всё

0000 0000  0000 0000

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

Код: Выделить всё

0000 0000 0000 0011
OpenHab это нормально прочитает и отобразит в интерфейсе, что свет включен в обеих комнатах. Но если мы через интерфейс выключим свет в гостиной, то опенхаб перезапишет всё слово нулями и свет погаснет и в спальне. Кароч неудобно :shock:

Победить опенхаб, чтобы он записывал по-битово не получилось и было принято решение зайти с тылу. В программе beckhoff-a присвоил значения не битам в слове, а нулевым битам в разных словах

Код: Выделить всё

Было
   H2_R1_L            AT %MX0.0:   BOOL := FALSE;
   H2_R2_L            AT %MX0.1:   BOOL := FALSE;

Стало
   H2_R1_L            AT %MX0.0:   BOOL := FALSE;
   H2_R2_L            AT %MX2.0:   BOOL := FALSE;
Единственная неудобность - пришлось для каждого слова прописывать настройки modbus в OpenHab

Код: Выделить всё

# Гостинная
tcp.slave1.connection=192.168.1.2
tcp.slave1.type=holding
tcp.slave1.id=5
tcp.slave1.start=16384
tcp.slave1.length=16

# Спальня
tcp.slave2.connection=192.168.1.2
tcp.slave2.type=holding
tcp.slave2.id=5
tcp.slave2.start=16385
tcp.slave2.length=16

В остальном программа идентична примерам Ali.
Если есть предложения как заставить писать опенхаб по-битово выслушаю с превеликим удовольствием!


Вернуться в «Умный Дом своими руками»

Кто сейчас на конференции

Сейчас этот форум просматривают: Bing [Bot], Prokol, Yandex [Bot] и 20 гостей