Контроллеры Wago в "Умном доме"

Обсуждение статей, технологий домашней автоматизации, программных и аппаратных решений
THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Контроллеры Wago в "Умном доме"

Сообщение THK » 21 ноя 2014, 22:50

Эта тема является ответвлением темы Ali Элементы "умного дома" на Beckhoff . Посвящена она будет контроллерам Wago, а именно Wago 750-881. Все примеры честно содраны у Ali (за что ему отдельное СПАСИБО!). Решил открыть ее, т.к. несмотря на то, что Beckhoff и Wago близнеци-братья, а отличия все-таки есть.
На отличия или неосвещенные в теме Ali возможности контроллера и будет основной упор в моем повествовании.

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 21 ноя 2014, 22:51

Начать, я думаю, стоит с настроек подключения. Все настройки находятся в меню «Онлайн -> Параметры связи…» в появившемся окне нажимаем «Gateway», далее надо указать localhost - драйвер будет запущен на том же компьютере, где и CoDeSys.
Далее жмем «New», выбираем S3 Tcp/ip driver. Указываем IP адрес контроллера, и порт 2455.
Важно заметить, что любые изменения параметров в полях ввода надо заканчивать нажатием клавиши Enter, иначе значение поменяется, а применено не будет – потратил на выяснение этой фичи целый день. :)
Все это выяснилось потом, а с начала я воспользовался китайским переходником USB-COM с выходными уровнями 5 вольт, купленным на eBay за целый доллар. Магазинный переходник без переделки использовать нельзя, вернее можно, но потребуется микросхема-преобразователь MAX232 или аналогичная.

Распайка разъема WAGO сверху вниз:
1 - TxD (передача, выход) - подключить к выводу T1IN MAX232 или RX китайского переходника.
2 - RxD (прием, вход) - подключить к выводу R1OUT MAX232 или TX китайского переходника.
3 - Vcc (питание +5V) - отсюда взять питание для MAX232 - для китайского переходника не используется.
4 - GND (общий)

При таком способе подключения все делается как для сети, только выбирать нужно S3 Serial RS232 driver. Все настройки по умолчанию, за исключением номера COM порта.

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 21 ноя 2014, 22:55

У контроллера Wago есть интересная возможность получения значений и записи переменных контроллера с помощью HTTP запросов к нему.

Получение значений переменных может выглядеть это так:
_http://admin:wago@192.168.100.181/READPI?ADR=QW2&FORMAT=%d - Прочитать состояние 16 выходов QX2.0 – QX2.15.
_http://admin:wago@192.168.100.181/READPI?ADR=QX2.0&FORMAT=%d - Прочитать состояние выхода QX2.0.
_http://admin:wago@192.168.100.181/READPI?ADR=IX0.0&FORMAT=%d - Прочитать состояние входа IX0.0.
Аналогично можно прочитать любую переменную.
Формат запроса очень прост – логин, пароль, адрес контроллера. Далее, через слеш, следует команда чтения «READPI» и параметры адрес переменной и формат вывода.
Формат вывода может быть «%d» - десятичный или «%x» - шестнадцатиричный.

Аналогично можно записать новое значение переменным MX и MW, использовав вместо команды чтения «READPI», команду «WRITEPI».

_http://admin:wago@192.168.100.181/WRITEPI?ADR1=MW1600&VALUE1=31&FORMAT1=%d - Записать десятичное значение 31 в переменную MW1600.
Стоит сразу сказать, что на GET запросы такого вида контроллер ругается, но выполняет, для записи надо использовать POST запросы.

Также, для общения с контроллером, можно использовать SSI скрипты расположенные на виртуальном диске контроллера. Вот пример SSI скрипта, найденный на каком то польском форуме. Этот скрипт отображает состояние выходов и с помощью переменной MW1600, позволяет переключать их состояние.

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

<html>
<head>
<script language="JavaScript">
<!--
function Start()
{
  var Tags = new Array (<!--#READPI ADR=MX1600.0&FORMAT=%d-->,
				<!--#READPI ADR=MX1600.1&FORMAT=%d-->, 
				<!--#READPI ADR=MX1600.2&FORMAT=%d-->,
				<!--#READPI ADR=MX1600.3&FORMAT=%d-->, 
				<!--#READPI ADR=MX1600.4&FORMAT=%d-->,
				<!--#READPI ADR=MX1600.5&FORMAT=%d-->);

  var Outs = new Array (<!--#READPI ADR=QX2.0&FORMAT=%d-->,
				<!--#READPI ADR=QX2.1&FORMAT=%d-->, 
				<!--#READPI ADR=QX2.2&FORMAT=%d-->,
				<!--#READPI ADR=QX2.3&FORMAT=%d-->, 
				<!--#READPI ADR=QX2.4&FORMAT=%d-->,
				<!--#READPI ADR=QX2.5&FORMAT=%d-->);
 
  for (var i = 0; i < Tags.length; i++) 
  {
    if (Tags[i]>0)
    {
      document.forms["DataTable"].elements["ADR1"].value='MX1600.'+i;
      document.forms["DataTable"].submit(); 
    }
  } 
  
  for (var i = 1; i < Outs.length+1; i++) 
  {
    if (Outs[i-1]==1) 
    {
      document.forms["Control"].elements["Button"+i].value="OFF";
    }
  }
}

function ChangeAndPost(TagNo)
{
  document.forms["DataTable"].elements["ADR1"].value="MX1600."+TagNo;
  document.forms["DataTable"].elements["VALUE1"].value="1";
  document.forms["DataTable"].submit(); 
}

//-->
</script>
<style type="text/css">
	p {font-family:"Arial", Helvetica, sans-serif;} 
</style>
</head>
<body onload="Start();">

<FORM name="Control">
<TABLE align="left" border="0">
<TR>
<TD align="left" width='100'><p>Ванна</p></TD>
<TD align="center" width='30'><p><!--#READPI ADR=QX2.0&FORMAT=%d--></p></TD>
<TD align="center" width='60'><input type="button" name="Button1" value="ON" onclick="ChangeAndPost('0')"></td>
</TR>
<TR>
<TD align="left"><p>Туалет</p></TD>
<TD align="center"><p><!--#READPI ADR=QX2.1&FORMAT=%d--></p></TD>
<TD align="center"><input type="button" name="Button2" value="ON" onclick="ChangeAndPost('1')"></td>
</TR>
<TR>
<TD align="left"><p>Предбанник</p></TD>
<TD align="center"><p><!--#READPI ADR=QX2.2&FORMAT=%d--></p></TD>
<TD align="center"><input type="button" name="Button3" value="ON" onclick="ChangeAndPost('2')"></td>
</TR>
<TR>
<TD align="left"><p>Комната</p></TD>
<TD align="center"><p><!--#READPI ADR=QX2.3&FORMAT=%d--></p></TD>
<TD align="center"><input type="button" name="Button4" value="ON" onclick="ChangeAndPost('3')"></td>
</TR>
<TR>
<TD align="left"><p>Спальня</p></TD>
<TD align="center"><p><!--#READPI ADR=QX2.4&FORMAT=%d--></p></TD>
<TD align="center"><input type="button" name="Button5" value="ON" onclick="ChangeAndPost('4')"></td>
</TR>
<TR>
<TD align="left"><p>Прихожая</p></TD>
<TD align="center"><p><!--#READPI ADR=QX2.5&FORMAT=%d--></p></TD>
<TD align="center"><input type="button" name="Button6" value="ON" onclick="ChangeAndPost('5')"></td>
</TR>
</table>
</FORM>

<!-- Форма для запись в контроллер -->
<FORM action="/WRITEPI" method="POST" name="DataTable">
<input type="hidden" name="ADR1" value="MB0">
<input type="hidden" name="VALUE1" value="0" >
<input type="hidden" name="FORMAT1" value="%d">
</FORM>

</body>
</html>
Правда, я его немного доработал под свою задачу.

Осталось научить контроллер обращаться с девайсами типа «мегадевайса» или «1Wire по Ethernet» и писать в базу данных, расположенную на сервере, но об этом позже, и так уже много букв. :)
Вложения
control.rar
(946 байт) 501 скачивание

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

Re: Контроллеры Wago в "Умном доме"

Сообщение Pagan » 23 ноя 2014, 00:19

Хорошее дело делаете :)
Ещё не плохо будет указать какие из модулей на этих контролёрах взаимозаменяемые. Ну и прочую информацию. Потому как очень мало данных по этой теме, а желающих попробовать применить возможности ПЛК для дома всё больше.
Так что спасибо вам за труды.

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 23 ноя 2014, 18:26

Pagan, спасибо на добром слове.
Про взаимозаменяемость модулей у меня информации пока нет.

И так, продолжим...
Не давал мне покоя способ общения с готовыми девайсами типа мегадевайса, вроде библиотеки для отправки GET запросов есть (HTTP_GET входит в состав библиотеки WagoLibHttp_02.lib), а что дальше? Как обрабатывать ответ девайса?

Решение нашлось после нескольких неудачных попыток получить значения влажности и температуры с датчика DHT-22, подключенного вот к этому девайсу - Управление вентиляцией по Ethernet.
Вот код функционального блока, решающего эту задачу. Объявление переменных:

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

FUNCTION_BLOCK FB_VENT_DHT
VAR_INPUT
	ServerName: STRING;
	Sensor: UINT;
END_VAR
VAR_OUTPUT
	Error: BOOL := FALSE;
	Humidity: REAL;
	Temperature: REAL;
	DewPoint: REAL;
END_VAR
VAR
	Http_1: HTTP_GET;
	Content: ARRAY [0..MAX_RECEIVE_TCP_CLIENT] OF BYTE;
	Length: UINT;
	Url: ARRAY [0..1] OF STRING := '/sec/?dht=1','/sec/?dht=2';
	pt:POINTER TO BYTE;
	tmp: STRING(5) := '';
	count: UINT;
	f_T_Rh: REAL;
END_VAR
VAR_IN_OUT
	Send: BOOL;
END_VAR
Основной код блока:

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

Error := FALSE;
IF (Sensor >=1 AND Sensor <= 2) THEN
	Http_1(
		sServerName:= ServerName,
		pabUrlData:= ADR(Url[Sensor-1]),
		uiUrlLength:= LEN(Url[Sensor-1]),
		tTimeOut:= T#1S,
		xSend:= Send,
		diError=> ,
		sStatus=> ,
		abContentData=> Content,
		uiContentLength=> Length);
	IF Http_1.diError > 0 THEN Error := TRUE; ELSE Error := FALSE; END_IF

	IF (Content[0]<16#3C AND Length > 0) THEN
		count := 0;
		pt:=ADR(tmp);
		WHILE Content[count]<>16#3B DO					(* ?????????? ?????? ?? ??????? ";" - ????????? *)
			pt^ := Content[count];
			count:=count+1;
			pt:=pt+1;
		END_WHILE
		Humidity := FLOAT_TO_REAL(tmp);

		count:=count+1;										(* ???????????? ?????? ";" *)
		tmp := '';
		pt:=ADR(tmp);
		WHILE (Content[count]<>0 AND count<Length) DO	(* ?????????? ?????? ?? ????? - ??????????? *)
			pt^ := Content[count];
			count:=count+1;
			pt:=pt+1;
		END_WHILE
		Temperature := FLOAT_TO_REAL(tmp);

		(*Формула обладает погрешностью ±0.4 °С в диапазоне температуры воздуха Т от 0°С до 60°С,
		температуры точки росы Тр от 0°С до 50°С, относительной влажности Rh от 1% до 100%.*)
		f_T_Rh := ((17.27 * Temperature) / (237.7 + Temperature)) + LN(Humidity / 100);
		DewPoint := (237.7 * f_T_Rh) / (17.27 - f_T_Rh) ;
	ELSE
	Error := TRUE;
	Humidity := 0;
	Temperature := 0;
	END_IF
ELSE
	Error := TRUE;
END_IF
В работе блока используется функция FLOAT_TO_REAL библиотеки OSCAT файл библиотеки - oscat_basic_333.lib

Вот так выглядит вызов этого блока на языке LD:
DHT2.JPG
DHT2.JPG (31.77 КБ) 20502 просмотра
Сообщение обновлено 25.11.2014. В код модуля добавлен расчет точки росы.

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 25 ноя 2014, 16:45

Pagan писал(а):Ещё не плохо будет указать какие из модулей на этих контролёрах взаимозаменяемые. Ну и прочую информацию. Потому как очень мало данных по этой теме, а желающих попробовать применить возможности ПЛК для дома всё больше.
Вот, случайно наткнулся на ссылку: _http://forum.skunksworks.net/Forum10/HTML/001125.html
Похоже проблем с использованием дискретных модулей нет, для аналоговых возможно потребуется бубен. :)

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 29 ноя 2014, 21:46

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

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

FUNCTION_BLOCK FB_VENT_OUTL
VAR_INPUT
	ServerName: STRING;
	Out: BYTE;
	In: BOOL;
END_VAR
VAR_OUTPUT
	Error: BOOL := FALSE;
END_VAR
VAR
	HttpGet: HTTP_GET;
	Length: UINT;
	Url: STRING(24);
	stmp: STRING(24);
	Val: STRING(1);
	MEM: BOOL;
	Send: BOOL;
END_VAR
VAR CONSTANT
	Url1: STRING := '/sec/?out=';
	Url2: STRING := '&val=';
END_VAR
И основной код:

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

Error := FALSE;
IF In AND NOT MEM THEN			(*Передний фронт*)
	Val:='1';
	Send:=TRUE;
END_IF
IF NOT In AND MEM THEN			(*Задний фронт*)
	Val:='0';
	Send:=TRUE;
END_IF

IF Send THEN
	Url := CONCAT (Url1,BYTE_TO_STRD(Out));
	stmp := CONCAT (Url,Url2);
	Url := CONCAT (stmp,Val);
	HttpGet(
		sServerName:= ServerName,
		pabUrlData:= ADR(Url),
		uiUrlLength:= LEN(Url),
		tTimeOut:= T#1S,
		xSend:= Send,
		uiContentLength=> Length);
END_IF
IF ((Length >0 AND Length <>2) OR HttpGet.diError <>0) THEN Error := TRUE; END_IF

MEM := In;
Этот блок по фронтам входного сигнала отправляет команды удаленному устройству на включение и выключение выхода.
В своей работе использует вот эту функцию:

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

FUNCTION BYTE_TO_STRD : STRING(4)
VAR_INPUT
	IN:BYTE;
END_VAR
VAR
	pt: POINTER TO BYTE;
	tmp: BYTE;
	str: STRING(4);
	fd: BOOL:=FALSE;
END_VAR

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

pt := ADR(str);

tmp:=0;
WHILE IN >= 100 DO					(*  *)
	tmp:=tmp+1;
	IN :=IN-100;
END_WHILE
IF tmp > 0 THEN
	tmp:= tmp+48;
	pt^ := tmp;
	pt:=pt+1;
	fd:=TRUE;
END_IF

tmp:=0;
WHILE IN >= 10 DO					(*  *)
	tmp:=tmp+1;
	IN :=IN-10;
END_WHILE
IF(( tmp > 0) OR fd) THEN
	tmp:= tmp+48;
	pt^ := tmp;
	pt:=pt+1;
END_IF

tmp:=0;
WHILE IN >= 1 DO						(*  *)
	tmp:=tmp+1;
	IN :=IN-1;
END_WHILE
tmp:= tmp+48;
pt^ := tmp;
pt:=pt+1;
pt^ := 0;
BYTE_TO_STRD :=str;
Почему то в стандартных библиотеках не нашлось функции преобразования байта в строку с десятичной цифрой. Перевод в двоичное и шестнадцатеричное число есть, а в десятичное нет. Пришлось написать самому...

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 13 дек 2014, 14:23

Немного отошел от написания логики - решил сделать резервную страничку для управления освещением которая храниться в самом контроллере. Думаю этот пример написания WEB приложений для контроллеров Wago будет интересен многим.
Сразу хочу оговориться, что скрипты на странице не работают в IE. Отладка проводилась в FireFox 17. Позже планирую это исправить, желающим исправить (обойти) баги IE самостоятельно, рекомендую посмотреть вот эту страницу XMLHTTPRequest: описание, применение, частые проблемы. В разделе "Частые проблемы" все подробно описано.
Есть еще одна проблема с IE - смена стилей. Она не описана в этой статье...


Анекдот на правах руководства к действию:
IE, это такая программа, которая служит для того, чтобы скачать себе браузер. :)

Вот что у меня получилось:
Light screen.JPG
Light screen.JPG (32.46 КБ) 19716 просмотров

Добавлено. 22:40
Решилась проблема с IE, теперь все работает. Проблем с утечкой памяти не заметил, возможно она появляется при условиях, которые в моих скриптах не используются.
Light.rar
(12.78 КБ) 455 скачиваний
На очереди PID регулятор для управления положением заслонки вентиляции.

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 13 дек 2014, 17:10

Просмотрел статью про еще раз, в коде осталась только одна проблема:
Утечки памяти

В Internet Explorer объект XmlHttpRequest принадлежит миру DOM/COM, а Javascript-функция - миру Javascript. Присваивание xmlhttp.onreadystatechange = function() { ... } задает неявную круговую связь: xmlhttp ссылается на функцию через onreadystatechange, а функция, через свою область видимости - видит (ссылается на) xmlhttp.

Невозможность обнаружить и оборвать такую связь во многих (до IE 6,7 редакции июня 2007?) версиях Internet Explorer приводит к тому, что XmlHttpRequest вместе с ответом сервера, функция-обработчик и всё замыкание прочно оседают в памяти до перезагрузки браузера.

Чтобы этого избежать, ряд фреймворков (YUI, dojo...) вообще не ставят onreadystatechange, а вместо этого через setTimeout проверяют его readyState каждые 10 миллисекунд. Это разрывает круговую связку xmlhttp <-> onreadystatechange, и утечка памяти не грозит даже в самых глючных браузерах.
Нужно ли ее "решать", да еще таким кривым способом, не знаю - те, кто пользуются ХР, преследуют определенные цели и почти наверняка не используют IE, а в Win7 и так должно все работать (не тестировал, у меня ХР :)).

Добавлено.
Отредактировал пост выше, перезалил архив.
Похоже в данном случае, описываемая проблема не проявляется.

radon
Сообщения: 9
Зарегистрирован: 01 июн 2014, 21:53

Re: Контроллеры Wago в "Умном доме"

Сообщение radon » 22 дек 2014, 18:37

У меня контроллер 750-841, отличий от 881 много?
Кстати с одним контроллером вышла проблема, он не определялся через tcp/ip никак, сброс настроек, мониторинг трафика, ничего не помогало. Пришлось покупать сервисный кабель кабель.

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 24 дек 2014, 19:45

radon писал(а):У меня контроллер 750-841, отличий от 881 много?
Нет. Я пользуюсь русским даташитом на 841 контроллер. 881 это более производительная замена 841 контроллера, но для домашнего применения это не критично.
ИМХО Отличия только в способе настройки, у 881 все делается через WEB интерфейс.
PS Сильно отличается контроллер 750-842...
radon писал(а):Пришлось покупать сервисный кабель.
Во втором посту данной темы распайка сервисного разъема. Проверено - все работает как с родным кабелем, по началу пользовался именно таким подключением.

На всякий случай, мой текущий проект, вдруг кому будет интересно взглянуть...
750-881.rar
(24.99 КБ) 513 скачиваний

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 18 янв 2015, 21:12

Что то со временем туго стало, не удается осуществить задуманное.
В качестве памятки:

SysLibRtc.lib - доступ к часам RTC контроллеров 750-841, 750-881 и может еще каким то. Входит в состав CodeSys по умолчанию.

Scheduler_03.lib - планировщик задач, позволяет планировать задачи по времени и дням недели. Доступна на гитхабе.

Building_HVAC_01.lib - набор библиотек на все случаи жизни для управления инженерными системами здания, может будет кому то интересно. Доступна на гитхабе.

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 07 мар 2015, 13:51

Давно не писал...
За это время доработал WEB - теперь выводятся аналоговые значения, обновляются AJAX'сом и изрядно "причесал" прошивку - разбил ее на отдельные модули, так удобнее и понятней.
WWW_20150307.rar
(16.53 КБ) 404 скачивания
2015.03.07_750-881.rar
исправлено несколько багов в самописных FB
(32.19 КБ) 407 скачиваний
Надеюсь кому то пригодится в качестве примера и сэкономит время - пришлось долго возится с аяксом.

PS Жаль времени на все не хватает.
Вложения
Screen.JPG
Screen.JPG (34.67 КБ) 18312 просмотров

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 20 июл 2015, 20:54

Думал тема умерла - никто не пишет, ан нет! Наработки просматривается и скачиваются...
Выкладываю последние архивы своей системы. Многое доработано, переписано и усовершенствовано. В процессе своих мытарств столкнулся с одним неприятным ограничением контроллера - одновременно можно открыть не более 3 HTTP соединений. В доке, конечно, это указано, но я думал это относится только к открытию страничек WEB интерфейса, что легко обходится настройкой прокси на апаче сервера. Как оказалось в это число входят и исходящие соединения с контроллера к другим девайсам.
Надо переходить на Modbus TCP (поддерживается 15 соединений)...
Из за этого пришлось полностью менять идеологию управления устройствами. Вот так теперь выглядит FB для управления заслонками вентиляции:
2015.03.07_FB_VENT.JPG
2015.03.07_FB_VENT.JPG (23.15 КБ) 16535 просмотров
Долго помучился со стилями на странице управления освещением, теперь (по мотивам статьи Андрея Рисуем план дома для управления освещением) она выглядит вот так:
2015.03.07_Light_800.JPG
2015.03.07_Light_800.JPG (28.81 КБ) 16535 просмотров
Для удобства сделал страничку, где можно наблюдать за изменением состояния всех IO, доступных контроллеру.
2015.03.07_Sensors_800.JPG
2015.03.07_Sensors_800.JPG (54.47 КБ) 16535 просмотров
Ну и наконец то разобрался с изменением настроек каких то блоков контроллера из WEB'а. На вторую и третью колонки внимание не обращайте, это оставлено, чтобы видеть границы колонок. Значения в них не обновляются. Вся вкусность в первой колонке... :)
2015.03.07_Seting_800.JPG
2015.03.07_Seting_800.JPG (38.7 КБ) 16535 просмотров
Из проблем WEB'а.
Скорее всего в IE отображение будет корявым, у меня ХР, поэтому нормально проверить интерфейс не получается, Слишком много "нового" в нем используется. Буду рад, если кто то проверит у себя на Win7 (можно просто открыть странички на компьютере не загружая их в контроллер) и напишет результат, а еще лучше, устранит увиденные баги. :D С версткой у меня явно проблемы...
Все отлаживалось в FireFox 30.
Вложения
2015.07.20_WWW.rar
(36.9 КБ) 302 скачивания
2015.07.20_750-881.rar
(1.02 МБ) 311 скачиваний

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 23 июл 2015, 20:32

Переписал FB_VENT.
Теперь, благодаря простенькому конвейеру-битовому автомату, этот FB не теряет входные сигналы при их одновременном появлении и сам распределяет запросы к модулю во времени. Добавил комментарии.
Объявление переменных:

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

FUNCTION_BLOCK FB_VENT
VAR_INPUT
	ServerName: STRING;
	Send_Period: WORD := 300;
	Out1: BOOL := FALSE;
	Out2: BOOL := FALSE;
	Out3: BOOL := FALSE;
	Out4: BOOL := FALSE;
	Out5: BOOL := FALSE;
	DU1: WORD := 50;
	Delta1: WORD := 1;
	DU2: WORD := 50;
	Delta2: WORD := 1;
	DHT_1: BOOL := FALSE;
	DHT_2: BOOL := FALSE;
	Hum_Limit: REAL := 5;
	Mes_Period: WORD := 10;
	DewPoint_Off: REAL := 16;
END_VAR
VAR_OUTPUT
	Error: WORD := 0;
	Humidity1: REAL := 0;
	Temperature1: REAL := 0;
	DewPoint1: REAL := 0;
	Humidity2: REAL := 0;
	Temperature2: REAL := 0;
	DewPoint2: REAL := 0;
	Exhaust_Fan: BOOL := FALSE;
END_VAR
VAR
	HttpGet: HTTP_GET;
	Content: ARRAY [0..MAX_RECEIVE_TCP_CLIENT] OF BYTE;
	Length: UINT;
	count: UINT;
	pt:POINTER TO BYTE;
	Url: STRING(24);
	Val: STRING(5);
	MEM1: BOOL:=FALSE;
	MEM2: BOOL:=FALSE;
	MEM3: BOOL:=FALSE;
	MEM4: BOOL:=FALSE;
	MEM5: BOOL:=FALSE;
	DHT_MEM1: BOOL:=FALSE;
	DHT_MEM2: BOOL:=FALSE;
	Send: BOOL;
	DUtmp1: INT;
	DUtmp2: INT;
	tmp: STRING(8) := '';
	f_T_Rh: REAL;
	T_Cicle: BLINK;
	R_Cicle: R_TRIG;
	T_Conv: BLINK;
	R_Conv: R_TRIG;
	Hum_tmp1: REAL;
	DWOR_TO_TIME: BOOL;
	Conv: ARRAY [0..13] OF BOOL := 14(FALSE);
	Conv_Index: WORD:=0;
	Index: WORD := 0;
END_VAR
VAR CONSTANT
	sUrl: ARRAY [0..13] OF STRING := '/sec/?out=1&val=1',
										'/sec/?out=1&val=0',
										'/sec/?out=2&val=1',
										'/sec/?out=2&val=0',
										'/sec/?out=3&val=1',
										'/sec/?out=3&val=0',
										'/sec/?out=4&val=1',
										'/sec/?out=4&val=0',
										'/sec/?out=5&val=1',
										'/sec/?out=5&val=0',
										'/sec/?srv=1&du=',
										'/sec/?srv=2&du=',
										'/sec/?dht=1',
										'/sec/?dht=2';
END_VAR
Текст самого блока:

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

(***********************************************************************************************************************)
(**                                  Анализ вохдных сигналов блока и постановка задач на конвейер                                   **)
(***********************************************************************************************************************)
(* DHT #1 *)
IF DHT_1 AND NOT DHT_MEM1 THEN Conv[12] := TRUE; END_IF	(*Передний фронт*)
DHT_MEM1 := DHT_1;
(* DHT #2 *)
IF DHT_2 AND NOT DHT_MEM2 THEN Conv[13] := TRUE; END_IF	(*Передний фронт*)
DHT_MEM2 := DHT_2;
(* Servo #1 *)
IF (DU1 >=0 AND DU1 <= 100  AND Delta1>0) THEN
	IF ((DU1>=(DUtmp1+Delta1)) OR (DU1<=(DUtmp1-Delta1))) THEN DUtmp1:=DU1; Conv[10] := TRUE; END_IF
ELSE Error.10 := TRUE; END_IF
(* Servo #2 *)
IF (DU2 >=0 AND DU2 <= 100  AND Delta2>0) THEN
	IF ((DU2>=(DUtmp2+Delta2)) OR (DU2<=(DUtmp2-Delta2))) THEN DUtmp2:=DU2; Conv[11] := TRUE; END_IF
ELSE Error.11 := TRUE; END_IF
(* Out 1 *)
IF Out1 AND NOT MEM1 THEN Conv[0] := TRUE; END_IF	(*Передний фронт*)
IF NOT Out1 AND MEM1 THEN Conv[1] := TRUE; END_IF	(*Задний фронт*)
MEM1 := Out1;
(* Out 2 *)
IF Out2 AND NOT MEM2 THEN Conv[2] := TRUE; END_IF	(*Передний фронт*)
IF NOT Out2 AND MEM2 THEN Conv[3] := TRUE; END_IF	(*Задний фронт*)
MEM2 := Out2;
(* Out 3 *)
IF Out3 AND NOT MEM3 THEN Conv[4] := TRUE; END_IF	(*Передний фронт*)
IF NOT Out3 AND MEM3 THEN Conv[5] := TRUE; END_IF	(*Задний фронт*)
MEM3 := Out3;
(* Out 4 *)
IF Out4 AND NOT MEM4 THEN Conv[6] := TRUE; END_IF	(*Передний фронт*)
IF NOT Out4 AND MEM4 THEN Conv[7] := TRUE; END_IF	(*Задний фронт*)
MEM4 := Out4;
(* Out 5 *)
IF Out5 AND NOT MEM5 THEN Conv[8] := TRUE; END_IF	(*Передний фронт*)
IF NOT Out5 AND MEM5 THEN Conv[9] := TRUE; END_IF	(*Задний фронт*)
MEM5 := Out5;
(***********************************************************************************************************************)
(**                                                               Конвейер отсылки команд модулю                                                               **)
(**      Необходим для исключения потери событий и распределения запросов к модулю во времени      **)
(***********************************************************************************************************************)
T_Conv(ENABLE:= TRUE,  TIMELOW:= WORD_TO_TIME(Send_Period-1), TIMEHIGH:= T#1ms );
R_Conv(CLK:= T_Conv.OUT );
IF (Send = FALSE) THEN										(*Предыдущее соединение звершено или закрыто по таймауту*)
	IF R_Conv.Q THEN
		IF (Conv[Conv_Index] = TRUE) THEN
			Url := CONCAT (sUrl[Conv_Index],'');
			(* Для этих индексов добавляем значение DU, которое было на момент постановки задачи *)
			IF Conv_Index = 10 THEN Url := CONCAT (sUrl[10],INT_TO_STRING(DUtmp1)); END_IF
			IF Conv_Index = 11 THEN Url := CONCAT (sUrl[11],INT_TO_STRING(DUtmp2)); END_IF
			Send:=TRUE;
			Conv[Conv_Index] := FALSE;
			Index := Conv_Index;
		END_IF
		(* Просматриваем конвейер до следующей задачи или, если задач нет, до конца очереди*)
		WHILE (Conv[Conv_Index] = FALSE AND Conv_Index <= 13) DO Conv_Index := Conv_Index+1; END_WHILE
		IF (Conv_Index > 13) THEN Conv_Index:=0; END_IF
	END_IF
END_IF
(***********************************************************************************************************************)
(**                                        Отсылка команды модулю, прием ответа и анализ ошибок                                        **)
(***********************************************************************************************************************)
IF Send THEN
	HttpGet(
		sServerName:= ServerName,
		pabUrlData:= ADR(Url),
		uiUrlLength:= LEN(Url),
		tTimeOut:= T#10s,									(*По умолчанию T#30s*)
		xSend:= Send,
		abContentData=> Content,
		uiContentLength=> Length);
	CASE Index OF
		0,1: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.0 := TRUE; ELSE Error.0 := FALSE;END_IF
		2,3: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.1 := TRUE; ELSE Error.1 := FALSE;END_IF
		4,5: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.2 := TRUE; ELSE Error.2 := FALSE;END_IF
		6,7: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.3 := TRUE; ELSE Error.3 := FALSE;END_IF
		8,9: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.4 := TRUE; ELSE Error.4 := FALSE;END_IF
		10: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.10 := TRUE; ELSE Error.10 := FALSE;END_IF
		11: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.11 := TRUE; ELSE Error.11 := FALSE;END_IF
		12: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.12 := TRUE; ELSE Error.12 := FALSE;END_IF
		13: IF (HttpGet.diError <> 0 OR Length = 0) THEN Error.13 := TRUE; ELSE Error.13 := FALSE;END_IF
	END_CASE
END_IF
(***********************************************************************************************************************)
(**                             Разбор ответа модуля и генерация ошибки при отсутствии датчика DHT                           **)
(***********************************************************************************************************************)
(* DHT #1 *)
IF (Index=12 AND Error.12=FALSE) THEN
	IF (Content[0]<16#3C AND Length > 0) THEN
		count := 0;
		pt:=ADR(tmp);
		WHILE Content[count]<>16#3B DO					(* Перебираем массив до символа ";" - Влажность *)
			pt^ := Content[count];
			count:=count+1;
			pt:=pt+1;
		END_WHILE
		pt^ := 0;
		Humidity1 := FLOAT_TO_REAL(tmp);
		count:=count+1;										(* Проскакиваем символ ";" *)
		tmp := '';
		pt:=ADR(tmp);
		WHILE (Content[count]<>0 AND count<Length) DO	(* Перебираем массив до конца - Температура *)
			pt^ := Content[count];
			count:=count+1;
			pt:=pt+1;
		END_WHILE
		pt^ := 0;
		Temperature1 := FLOAT_TO_REAL(tmp);
		(*Формула обладает погрешностью ±0.4 °С в диапазоне температуры воздуха Т от 0°С до 60°С,
		температуры точки росы Тр от 0°С до 50°С, относительной влажности Rh от 1% до 100%.*)
		f_T_Rh := ((17.27 * Temperature1) / (237.7 + Temperature1)) + LN(Humidity1 / 100);
		DewPoint1 := (237.7 * f_T_Rh) / (17.27 - f_T_Rh) ;
	ELSE
		IF Content[0]<>0 THEN Error.12 := TRUE; END_IF
		(*Humidity1 := 0;
		Temperature1 := 0;*)
	END_IF
END_IF
(* DHT #2 *)
IF (Index=13 AND Error.13=FALSE) THEN
	IF (Content[0]<16#3C AND Length > 0) THEN
		count := 0;
		pt:=ADR(tmp);
		WHILE Content[count]<>16#3B DO					(* Перебираем массив до символа ";" - Влажность *)
			pt^ := Content[count];
			count:=count+1;
			pt:=pt+1;
		END_WHILE
		pt^ := 0;
		Humidity2 := FLOAT_TO_REAL(tmp);
		count:=count+1;										(* Проскакиваем символ ";" *)
		tmp := '';
		pt:=ADR(tmp);
		WHILE (Content[count]<>0 AND count<Length) DO	(* Перебираем массив до конца - Температура *)
			pt^ := Content[count];
			count:=count+1;
			pt:=pt+1;
		END_WHILE
		pt^ := 0;
		Temperature2 := FLOAT_TO_REAL(tmp);
		(*Формула обладает погрешностью ±0.4 °С в диапазоне температуры воздуха Т от 0°С до 60°С,
		температуры точки росы Тр от 0°С до 50°С, относительной влажности Rh от 1% до 100%.*)
		f_T_Rh := ((17.27 * Temperature2) / (237.7 + Temperature2)) + LN(Humidity2 / 100);
		DewPoint2 := (237.7 * f_T_Rh) / (17.27 - f_T_Rh) ;
	ELSE
		IF Content[0]<>0 THEN Error.13 := TRUE; END_IF
		(*Humidity2 := 0;
		Temperature2 := 0;*)
	END_IF
END_IF
(***********************************************************************************************************************)
(**Включение вентилятора, при быстром росте влажности. Выключение при установленой точке росы. **)
(***********************************************************************************************************************)
T_Cicle(ENABLE:= TRUE,  TIMELOW:= DWORD_TO_TIME(WORD_TO_DWORD(Mes_Period)*1000), TIMEHIGH:= T#1ms );
R_Cicle(CLK:= T_Cicle.OUT);
IF R_Cicle.Q THEN
	IF (Humidity1>=(Hum_tmp1+ Hum_Limit)) THEN
		Hum_tmp1:=Humidity1;
		Exhaust_Fan := TRUE;
	END_IF
	IF (DewPoint1<= DewPoint_Off) THEN
		Hum_tmp1:=Humidity1;
		Exhaust_Fan := FALSE;
	END_IF
END_IF
Кроме этого добавил простенький алгоритм для определения скорости роста влажности и включения вентилятора.

25.07.2015 Изменен текст блока - теперь есть проверка перед отправкой команды, что выполнение предыдущей команды закончено.

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 29 июл 2015, 15:05

Обнаружился баг при работе с Modbus, если слейв выключен долгое время (сутки) - контроллер "зависает", после включения слейва все начинает работать. Удалось решить проблему заменой FB из библиотеки ModbusEthernet_04.lib на такую же из WagoLibModbus_IP_01.lib.
У библиотеки WagoLibModbus_IP_01.lib в описании написано "A modbus master for the Wago IPC and 750-841 based on the SysLibSocket library.", т.е. контроллеры 750-841 и 750-881 имеют какую то особенность при работе с сетью и надо стараться использовать библиотеки предназначенные для них.
Кроме того, оказалось, что блок из WagoLibModbus_IP_01.lib немного удобнее в плане диагностики ошибок.

PS Сейчас контроллер остался без слейва примерно на неделю - получится хорошее тестирование. :) По результатам отпишу в этом посте.

23.08.2015
Прошел почти месяц. Контроллер так и работает без слейва, каких либо проблем в работе замечено не было, теперь с уверенностью можно сказать, что для контролеров 750-841, 750-881 для работы с Modbus TCP надо использовать библиотеку WagoLibModbus_IP_01.lib.

Жаль что не все в жизни складывается как запланировал... :)

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 03 май 2016, 11:19

Столкнулся с той же проблемой, что описана вот здесь: viewtopic.php?p=21523#p21523
MerryKaze писал(а):Есть ли способ при добавлении модуля сразу скопом изменить привязку переменных к дискретным входам и выходам?
Решение простое, надо присваивать символьные имена выходам модулей и в программе пользоваться ими, а не адресами. После добавления модулей, адреса меняются, а символьные имена остаются. На прикрепленном скриншоте видно где это можно сделать для контроллера Wago.
Вложения
123.JPG
123.JPG (296.6 КБ) 11948 просмотров

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 10 май 2016, 20:41

По просьбе в соседней ветке viewtopic.php?p=21780#p21780 , выкладываю последний архив своего проекта:
2016.05.02_WWW.rar
Это WEB-интерфейс контроллера, заливается через FTP.
(44.76 КБ) 235 скачиваний
750-881.rar
Проект PLC.
(48.12 КБ) 238 скачиваний
Полный архив PLC слишком большой, кому надо давайте свою почту в ЛС - вышлю.
Изменения, относительно прошлого выложенного проекта, касаются в основном интерфейса - немного добавлено, исправлены некоторые ошибки. Посмотреть его возможно в офф-лайн режиме, распаковав архив и открыв файл Heating.ssi Firefox'ом или любым другим браузером (естественно кроме IE :))

nkh
Сообщения: 39
Зарегистрирован: 12 авг 2016, 11:13

Re: Контроллеры Wago в "Умном доме"

Сообщение nkh » 22 апр 2017, 21:17

Приветствую ТНК! Правильно ли я понимаю, что для опроса датчиков по l2C у тебя (можно на ты?) получилось подружить ваго и мегу?
А в каком сценарии не хватило 3х http запросов?
"Надо переходить на Modbus TCP (поддерживается 15 соединений)"
под мегу есть не стандартная прошивка с поддержкой modbus?

С уважением

THK
Модератор
Сообщения: 588
Зарегистрирован: 18 мар 2011, 19:00
Откуда: Серпухов, МО

Re: Контроллеры Wago в "Умном доме"

Сообщение THK » 23 апр 2017, 21:12

nkh писал(а):Правильно ли я понимаю, что для опроса датчиков по l2C у тебя (можно на ты?) получилось подружить ваго и мегу?
Если точнее, то подружил я не конкретно мегу, а свои девайсы с аналогичным API. Проблем с мегой тоже не будет.
nkh писал(а):А в каком сценарии не хватило 3х http запросов?
Здесь речь, скорее, не о сценариях, а о подходе к написанию программы для ваго. Опрос ВСЕХ устройств должен вестись последовательным перебором с закрытием соединения по его окончании.
В настоящий момент мой ваго общается с двумя термостатами (тема "1-Wire по Ethernet") и управляет вентиляцией. Плюс к этому на компе всегда открыт веб-интерфейс. Так что главное знать о ограничениях и не использовать возможности устройства на 100%. :) В любой момент времени, я использую не более 2-х соединений из 3 возможных.
nkh писал(а):"Надо переходить на Modbus TCP (поддерживается 15 соединений)"
под мегу есть не стандартная прошивка с поддержкой modbus?
Где-то на форуме встречал реализацию модбас на том же стеке, что и мега. Тему не вспомню, но человеку нужен был модбас, а веб ненужен, он реализовал свои хотелки и выложил их на форуме с подробным описанием. Повторить (переделать прошивку) его подвиг проблем не составит - дорожка проторена.:)

Ответить