1 2 3 4 5 6 7 8 9 10 10/10 10,00оценок: 5

OpenHAB - обмен опытом, совместное изучение и т. п

Тема в разделе "Умный дом", создана пользователем Anton66, 15.03.14.

  1. Smith2007
    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746

    Smith2007

    Живу здесь

    Smith2007

    Живу здесь

    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746
    Адрес:
    Россия
    Добрался до дому. Со смарта не удобно писать.
    И так.
    @Felix3000, если не получилось - сделайте второй эксперимент. На сколько помню, то сами операции чтения/записи модбас всегда оперируют регистром. Т. е. 2 байта.

    1. Покажите как Вы создали в модбас-слейве два байта.
    2. Попробуйте еще раз
    Код:
    modbus: tcp. slave1.connection=192.168.0.108:502
    modbus: tcp. slave1.id=1
    modbus: tcp. slave1.start=0
    modbus: tcp. slave1.length=2
    modbus: tcp. slave1.type=coil
    
    Switch Beckhoff_Input0   (gModbus)   { modbus="slave1:0"}
    Switch Beckhoff_Input1   (gModbus)   { modbus="slave1:1"}
    Меняя первые два бита на контроллере в модбас - следите за логами OH.

    В сети modbus всегда есть один мастер и много слейвов (для каждого интерфейса отдельно)
    OH выступает для ПЛК в качестве мастера по интерфейсу Ethernet. На ПЛК, на интерфейсе Eth Вы должны создать Modbus Slave в котором будут все Ваши переменные. Если нужно передавать значение со входа контроллера в openhab - у Вас будут две переменные. Одна связана со входом и вторая в слейве. В программе сделайте присваивание Переменная_Слейва = Вход_Контроллера.
    Если к примеру нужно управлять освещением то в слейве указываем переменную, которая будет тем самым "включателем" и уже ее будете анализировать в ПЛК на предмет "чего делать вкл или выкл"
    Если управление этой переменной предполагается не только со стороны OH но и ПЛК должен ее по своему передергивать то тогда нужно использовать тригеры для управления этой переменной, что бы переменной присваивалось управляющее воздействие только в течении одного цикла программы управления.

    Нет не нужно. Все делается в одном.
    Но для простоты я сделал два слейва. В первом у меня все переменные типа BOOL, вот втором INT, REAL, DWORD Так удобнее в rule программировать.

    Ну если у вас в слейве
    Switch Beckhoff_Input0 (gModbus) { modbus="slave1:0"}
    Просто присваивайте значение этой переменной.

    Передать состояние кнопок в переменные Slave

    Описываем переменную в слейве и получаем ее в OH
    Switch Beckhoff_Input0 (gModbus) { modbus="slave1:0"}
    В OH устанавливаем эту переменную в CLOSED и эта переменная станет true в слейве. В программе ПЛК присваиваем значение
    выходная_переменная=Переменная_Слейва
     
  2. Felix3000
    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0

    Felix3000

    Участник

    Felix3000

    Участник

    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0
    @Smith2007, спасибо за помощь. Проблема заключается в том, что как только я ставлю в конфиге OpenHab "modbus: tcp. slave1.type=coil" вместо "modbus: tcp. slave1.type=holding", в логе вижу только сообщения об ошибке подключения. А когда стоит holding - получается добраться до переменных в памяти Beckhoff.

    Сейчас в такой вот конфигурации:
    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

    у меня получается прочитать переменные из PLC (через slave1) и сохранить их в памяти PLC (через slave2). Причем slave1.0..15 читает почему-то из области %IB128..%IB%143, а slave2.0..15 читает/пишет в область %MB0..%MB15. Да и фиг бы с ним, меня бы устроил и такой вариант - но это не дает мне возможности напрямую обращаться ко входам-выходам PLC, что резко усложняет коммуникацию.

    Продолжаю эксперименты в направлении триггеров.
     
    Последнее редактирование: 08.10.15
  3. Felix3000
    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0

    Felix3000

    Участник

    Felix3000

    Участник

    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0
    так делать я уже научился.

    Проблема в отсутствии непосредственной обратной связи - если у меня состояние выхода меняется в зависимости от состояния входа логикой PLC, и при этом я еще и присваиваю состоянию выхода значение их OH - возникают проблемы с приоритетом (что главнее - кнопка на входе или OH). Гораздо удобнее было бы связать напрямую аппаратный выход PLC с свитчем ОН, так чтобы при изменении выхода логикой PLC соответствующее изменение отражалось в ОН, и наоборот - при перещелкивании выхода в ОН это бы мгновенно отражалось на состоянии выхода, без дополнительных промежуточных переменных и присваиваний.
     
  4. Smith2007
    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746

    Smith2007

    Живу здесь

    Smith2007

    Живу здесь

    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746
    Адрес:
    Россия
    Вечером доберусь до компа и скину пример. В двух словах по управлению с кнопки и плк. За сигнал переключения берем не вход плк, а переменную модбас слейв. Которую мы научились переключать из oh. Плк может так же легко управлять этой переменной по своему алгоритму. Но надо учесть, что нельзя сделать простое присваивание переменной слева значением входа.
    Нужно сгенерировать одиночный импульс тригером при переходе состояния входа из 0 в 1 и во время этого импульса установить переменную модбас.
    Это особенности работы программ на плк. Плк программа выполняется от нача до конца за несколько микросекунд. Через несколько миллисекунд вызов повториться и т. д.
    С таким способом управления можно еще добавлять источники управления. Например смс
     
  5. Felix3000
    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0

    Felix3000

    Участник

    Felix3000

    Участник

    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0
    Буду признателен за пример. Вообще, кое-что уже проясняется - простую логику совместного управления с кнопки и из ОН я уже поднял, застрял на этапе включения-выключения из ОН выхода, который управляется ПЛК с помощью таймера.

    Вот как у меня выглядит код простой лампочки, которая управляется и с ПЛК, и из ОН:

    Переменные:
    Код:
    VAR_GLOBAL
        OH_O1        AT %MB0:       INT;      (* переменная, которую я могу читать/писать по Modbus *)
        IN_E_K1        AT %IX0.0:    BOOL;   (* аппаратный вход ПЛК *)
        OUT_E_L1     AT %QX0.0:    BOOL;   (* аппаратный выход ПЛК на реле лампочки *)
    END_VAR
    
    Функциональный блок кнопки:
    Код:
    
    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;
    
    и сама программа
    Код:
    
    PROGRAM MAIN
    VAR
        BUTT_E_B1:SM_BUTT;     (* объект кнопки *)
        OutState: BOOL := FALSE;   (* память состояния выхода *)
    END_VAR
    
    IF NOT (INT_TO_BOOL(OH_O1) = OutState) THEN       (* если состояние слейва в ОН не совпадает с памятью состояния выхода *)
            BUTT_E_B1 (IN:=TRUE);    (* вызвать принудительное нажатие кнопки *)
        ELSE
            BUTT_E_B1 (IN:=IN_E_K1);   (* иначе вызвать стандартную процедуру кнопки *)
    END_IF
    
    OUT_E_L1 := BUTT_E_B1.Q;     (* передать выход блока кнопки на лампочку *)
    
    OH_O1 := BOOL_TO_INT(OUT_E_L1);    (* передать выход блока кнопки в ОН *)
    
    OutState := OUT_E_L1;    (* запомнить состояние выхода *)
    
    
    По факту - работает как задумано (лампочка включается/выключается независимо с кнопки и из ОН, Switch в ОН исправно меняет свое состояние). Буду признателен за комментарии к коду (я только начинаю осваивать программирование ПЛК).
     
    Последнее редактирование: 09.10.15
  6. Smith2007
    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746

    Smith2007

    Живу здесь

    Smith2007

    Живу здесь

    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746
    Адрес:
    Россия
    Я могу выслать Вам проект а формате cds 2. x
    Я использую библиотечные ф. блоки, что бы не изобретать колесо заново :)
     
  7. Felix3000
    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0

    Felix3000

    Участник

    Felix3000

    Участник

    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0
    @Smith2007, @Smith2007, @Smith2007,
    Емейл отправил в ЛС, спасибо!
     
  8. Smith2007
    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746

    Smith2007

    Живу здесь

    Smith2007

    Живу здесь

    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746
    Адрес:
    Россия
    Вот так реализовал простейший алгоритм управления уличным освещением.
    Включается и выключается автоматически в зависимости от месяца. Так же можно включить и выключить через OpenHab
    Несколько грубовато, но вполне устраивает не и не требует существенных ресурсов на ПЛК.

    Выполняется данный код около 0,3 мс.

    Код:
    PROGRAM lighting
    VAR
        NightMode  : ARRAY[1..12] OF tLigtMode :=
            (H_OFF := 9, M_OFF := 00, H_ON := 18, M_ON := 30),    (* Январь *)
            (H_OFF := 8, M_OFF := 00, H_ON := 19, M_ON := 30),    (* Февраль *)
            (H_OFF := 7, M_OFF := 00, H_ON := 20, M_ON := 30),    (* Март *)
            (H_OFF := 6, M_OFF := 00, H_ON := 21, M_ON := 30),    (* Апрель *)
            (H_OFF := 4, M_OFF := 30, H_ON := 22, M_ON := 30),    (* Май *)
            (H_OFF := 4, M_OFF := 00, H_ON := 23, M_ON := 00),    (* Июнь *)
            (H_OFF := 4, M_OFF := 30, H_ON := 23, M_ON := 00),    (* Июль *)
            (H_OFF := 5, M_OFF := 00, H_ON := 22, M_ON := 00),    (* Август *)
            (H_OFF := 6, M_OFF := 00, H_ON := 21, M_ON := 00),    (* Сентябрь *)
            (H_OFF := 7, M_OFF := 00, H_ON := 19, M_ON := 30),    (* Октябрь *)
            (H_OFF := 8, M_OFF := 00, H_ON := 18, M_ON := 30),    (* Ноябрь *)
            (H_OFF := 9, M_OFF := 00, H_ON := 18, M_ON := 30);    (* Декабрь *)
        GetTime: CurTimeEx;
        Sys_DateTime, Z: SystemTimeDate;
        Sys_Time: SysTime64;
        t_current, t_off, t_on:    INT;
        lamp0_on : R_TRIG;
        lamp0_off : F_TRIG;
        sw_lamp0:    BOOL;
    
    END_VAR
    
    Sys_DateTime := Z;
    GetTime (SystemTime:=Sys_Time , TimeDate:= Sys_DateTime);
    
    t_current := Sys_DateTime.Hour * 60 + Sys_DateTime.Minute;
    t_off := NightMode[Sys_DateTime.Month].H_OFF * 60 + NightMode[Sys_DateTime.Month].M_OFF;
    t_on := NightMode[Sys_DateTime.Month].H_ON * 60 + NightMode[Sys_DateTime.Month].M_ON;
    
    (*************************************************)
    IF t_current   >=  t_off  AND t_current <= t_on
        THEN
            sw_lamp0 := FALSE;
        ELSE
            sw_lamp0 := TRUE;
    END_IF;
    lamp0_on(CLK := sw_lamp0);
    lamp0_off(CLK := sw_lamp0);
    IF lamp0_on.Q = TRUE THEN cmdLamp0 := TRUE; END_IF;
    IF lamp0_off.Q = TRUE THEN cmdLamp0 := FALSE; END_IF;
    
    lamp0 := cmdLamp0;
    
    
    lamp0 - это выход контроллера к которому нагрузка подключена
    cmdLamp0 - переменная modbus slave

    lamp0_on: R_TRIG;
    lamp0_off: F_TRIG;


    Тригеры генерирующие одиночный импульс
     
  9. Felix3000
    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0

    Felix3000

    Участник

    Felix3000

    Участник

    Регистрация:
    30.09.15
    Сообщения:
    7
    Благодарности:
    0
    @Smith2007, спасибо за пример кода. Можно еще часть с описанием переменных? Мне как новичку сложно понять - где системные типы, а где описанные вами. Как, например, описывается tLightMode?

    В целом логика кода понятна, буду учиться использовать триггеры.

    У меня получилось реализовать задачу несколько по-другому - я просто передаю на вход функц. блока кнопки "внешний сигнал" (состояние переменной modbus slave) и на основании ее значения принимаю решение о включении/выключении выхода вентилятора. Функционал в блоке следующий: короткое нажатие на аппаратную кнопку включает/выключает свет, длинное нажатие при выключенном свете (1 сек) включает свет и вентилятор, длинное нажатие при включенном свете выключает свет и вентилятор, короткое нажатие при включенном свете выключает свет и запускает таймер, по истечении которого вентилятор выключается сам.

    Код:
    FUNCTION_BLOCK SM_BUTT_TIMER
    VAR_INPUT
        IN: BOOL;        (* input to watch *)
        TS: INT;            (* ext signal for 2nd out *)
        TC: TIME;        (* time for a long press *)
        TC2: TIME;        (* time to switch the fan off *)
    END_VAR
    VAR_OUTPUT
        Q1: BOOL := FALSE;        (* light state *)
        Q2: BOOL := FALSE;        (* fan state *)
    END_VAR
    VAR
        TX: TON;
        TX2: TON;
        MEM1, MEM2, MEM3: BOOL;
    END_VAR
    
    
    IF IN AND NOT MEM1  THEN         (* button pressed  *)
        Q1 := NOT Q1;            (* change lamp state immediately *)
    END_IF
    
    CASE TS OF     (* принимаем решение о включении/выключении вентилятора *)
        1:                    (* signal to turn fan on *)
            Q2 := TRUE;
        2:                    (* signal to turn fan off *)
            Q2 := FALSE;
    ELSE                    (* no ext signal  *)
    
        IF TX.Q AND NOT MEM2  THEN        (* timer1 signal when lamp is on  *)
            Q2 := Q1;                        (*  set fan state to lamp state *)
        END_IF
    
        IF TX2.Q AND  NOT MEM3   THEN    (* timer2 signal *)
            IF NOT Q1 THEN                (* if the lamp is off now *)
                Q2 := FALSE;                (* switch the fan off *)
            END_IF
        END_IF
    
    END_CASE;
    
    
    MEM1 := IN;
    MEM2 := TX.Q;
    MEM3 := TX2.Q;
    
    А как измерить время выполнения программы?
     
  10. Smith2007
    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746

    Smith2007

    Живу здесь

    Smith2007

    Живу здесь

    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746
    Адрес:
    Россия
    Да, это я забыл привести описание пользовательского типа данных
    Код:
    TYPE tLigtMode :
    STRUCT
        H_ON:    INT;
        M_ON:    INT;
        H_OFF:    INT;
        M_OFF:    INT;
    END_STRUCT
    END_TYPE
    Из документации по CodeSys
    Конфигуратор задач в режиме онлайн
    В режиме онлайн дерево конфигурации задач отображает статус каждой задачи и число отработан- ных ею циклов. Временная диаграмма работы задач показана в правой части окна. Предварительное условие: для поддержки функции мониторинга времени библиотеки SysTaskInfo. lib и SysLibTime. lib должны быть включены в проект. Данные библиотеки отсутствуют, если не установлены целевые платформы, поддерживающие мониторинг задач.

    task.jpg

    @Felix3000, поверьте, что моя работа очень далека от программирования, поэтому могу только поделиться своим опытом но давать советы в этой части не возьмусь :)
    Что бы проверить Ваш алгоритм нужно его на контроллер загрузить и пошагово пройти по нему.

    зы. Одну и ту же задачу на ПЛК можно решить множеством различных способов. И каждый из них будет иметь свои плюсы и минусы и будет верным.
    Для себя я выбрал приоритетом - минимально-необходимое время для выполнения программы. При этом в угоду читаемости кода иногда отступаю от правила экономии времени, что бы в последствии (через год или два) не вспоминать все хитрости программирования.
     
  11. Smith2007
    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746

    Smith2007

    Живу здесь

    Smith2007

    Живу здесь

    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746
    Адрес:
    Россия
    эти вычисления можно исключить, если в массиве сразу указать значение в минутах от начала суток.
    Но я думал, что может потребоваться редактировать эти значения в системе через интерфейс OH. Хотя сейчас уже склоняюсь исключить эту пустую трату вычислительных ресурсов.
    Надо понимать, что значения эти практически статичны и по нескольку раз в секунду делать вычисления по меньшей мере бессмысленно.
    Оставить просто массив значений INT.
    Ну а если понадобиться редактировать со стороны OH то там так же можно будет разложить кол-во минут на часы и минуты.

    Вот как-то так. :)
     
  12. ktulhufhtagn
    Регистрация:
    27.11.11
    Сообщения:
    92
    Благодарности:
    26

    ktulhufhtagn

    Живу здесь

    ktulhufhtagn

    Живу здесь

    Регистрация:
    27.11.11
    Сообщения:
    92
    Благодарности:
    26
    Адрес:
    Рязань
    Добрый день. Есть вопрос по openhab: возможно ли к нему прикрутить управление шлюзом noolite ?
    У него же есть api, может он команды на шлюз отправлять и данные с датчиков получать ?
     
  13. Smith2007
    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746

    Smith2007

    Живу здесь

    Smith2007

    Живу здесь

    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746
    Адрес:
    Россия
    @ktulhufhtagn, судя по описанию можно управлять по GET запросам. OH имеет поддержку запросов.
    Смотрите HTTP Binding или напрямую вызов из скриптов/
     
  14. llentiai
    Регистрация:
    16.10.15
    Сообщения:
    6
    Благодарности:
    0

    llentiai

    Участник

    llentiai

    Участник

    Регистрация:
    16.10.15
    Сообщения:
    6
    Благодарности:
    0
    Здравствуйте. Хотел управлять Болидом с2000пп по modbus. Оказалось что в с2000пп адресация регистров отличается от modbus binding. Какой программой можно отредактировать modbus binding.
     
  15. Smith2007
    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746

    Smith2007

    Живу здесь

    Smith2007

    Живу здесь

    Регистрация:
    27.05.12
    Сообщения:
    1.265
    Благодарности:
    746
    Адрес:
    Россия
    @llentiai, что значит отличается адресация? Протокол modbus он стандартизирован. И если с200пп поддерживает modbus, то он может быть подключен к OH