PDA

Просмотр полной версии : Опрос модулей Мх110 по RS485



deniska13
05.11.2019, 20:50
Здравствуйте, уважаемые коллеги. Столкнулся с такой проблемой, когда в сети около 10 модулей ввода/вывода, то при пропадании связи с некоторыми из них по разным причинам (нет питания на модуле, так как он расположен в другом шкафу), возникает "тормоза" при опросе тех модулей, что находятся в данный момент в сети. Вопрос вот в чем: можно ли программно "убирать" из списка опрашиваемых модулей ПЛК, те что в данный момент не доступны. Например при обращении к модулю и получении ошибки 81, 5 раз подряд (ну или 3 раза) он исключается из сети, далее если с ним все в порядке (устранили проблемы с питанием или настройкой) на панели нажимаем кнопку сброс и опрос возобновляется. Кто-нибудь решал подобную задачу? Что можете посоветовать?

deniska13
06.11.2019, 00:34
syslibcom
....

если не сложно, могли бы Вы привести пример?

deniska13
06.11.2019, 00:56
https://owen.ru/forum/showthread.php?t=13580
наверно там есть что-нить

ничего не нашел подобного...идея была такая: цикл case...0: проверяем счетчик опросов если он не true значит даем команду старт (255) и запускаем таймер на 50мс, когда таймер досчитал, даем команду на останов опроса (254) и переходим на 1:...итд по каждому модулю (10 шт.) ... в случае если есть ошибка 81, счетчик увеличивается на 1 (он будет true когда счетчик досчитает до 3)...
Правда не могу пока понять как быстро все это будет работать в реальной жизни, что думаете? Или может как-то это можно упростить...

deniska13
06.11.2019, 10:00
Пойдет. Но с конфигурацией - дроч. Разберетесь с syslibcom и модбас - не пожалеете в дальнейшем.


Нормуль. Задача с кочующим оборудованием - штатная. К ней многие приходят и в том или ином виде решают. Наваяете какую-нибудь либу и дальше будете это делать парой строчек.

PS
Лично я не "убираю из опроса" а увеличиваю цикл опроса конкретного девайса при "дисконекте" (до нескольких сек). Стандартное в общем решение.

А как можно увеличить цикл опроса устройства, которое не на связи? Как Вы это делаете? Библиотекой syslibcom и модбас или же есть конкретные регистры?

deniska13
06.11.2019, 13:46
Пойдет. Но с конфигурацией - дроч. Разберетесь с syslibcom и модбас - не пожалеете в дальнейшем.


Нормуль. Задача с кочующим оборудованием - штатная. К ней многие приходят и в том или ином виде решают. Наваяете какую-нибудь либу и дальше будете это делать парой строчек.

PS
Лично я не "убираю из опроса" а увеличиваю цикл опроса конкретного девайса при "дисконекте" (до нескольких сек). Стандартное в общем решение.

Цикл опроса у МВ110-16Д, находится в регистре 48, то есть мы просто в него пишем 5сек и все? Этого достаточно чтобы улучшить работу сети? И какое время будет оптимальным при 10 модулях + панель слайв?

deniska13
06.11.2019, 14:34
Вы про конфигурацию ? Через нее - не совсем неудобно.

нет, это Вы писали что увеличиваете цикл опроса, вот я и спросил как это делаете)

deniska13
06.11.2019, 14:35
8( Это Вы как этому пришли ?

в инструкции к модулю написано, на 48 странице, регистр 48 - максимальный сетевой тайм-аут...или это не то что нужно?)

Andrew_Stranger
06.11.2019, 15:40
Опрашивает контроллер, причем здесь конфигурация модулей

deniska13
06.11.2019, 16:00
Опрашивает контроллер, причем здесь конфигурация модулей

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

deniska13
07.11.2019, 19:01
Этот параметр для устройств ВВОДА (16Д) не имеет смысла. Ну лампочка авария может на нем загорется. Да и хсней.
Для устройств ВЫВОДА наоборот, четкий и нужный смысл - через сколько времени от последнего запроса выходы переводятся в аварийное состояние (обычно отключение Do/обнуление Ao). Если этот параметр = 0, то выходы висят в последнем задании до конца света, что неправильно в общем случае.

Замедление опросов через конфигурацию можно, но неудобно. Разве ж только весь обмен уровня "светофора".
Чтоб понять как программно - нужно пригласить десяток гостей домой и накормить их помидорами с парным молоком. Если все останутся довольны то написать диспетчер запросов 80-ого уровня не составит труда.

А вот тот способ, что я описывал ранее через цикл CASE если по команде опрашивать модули, будет работать? """цикл case...0: проверяем счетчик опросов если он не true значит даем команду старт (255) и запускаем таймер на 50мс, когда таймер досчитал, даем команду на останов опроса (254) и переходим на 1:...итд по каждому модулю (10 шт.) ... в случае если есть ошибка 81, счетчик увеличивается на 1 (он будет true когда счетчик досчитает до 3)..."""" просто время опроса модуля может зависеть от цикла программы ПЛК, если время цикла меньше чем время работы таймера, то получается опрос модуля может быть чуть чуть дольше, что так же приведет к тормозам в сети, как мне кажется..

deniska13
07.11.2019, 22:24
Вы уже 2й раз описываете. Напишите сам код. Кто-нибудь и поправит если чего.

VAR
COUNT:ARRAY [1..10] OF INT; (*массив количества опросов каждого модуля из 10*)
COMM_MV110: ARRAY [1..10] OF BOOL; (*массив ошибок связи каждого модуля*)
(*ошибка = FALSE если в регистре LAST ERROR Значение 81 при опросе модуля*)
TEAM_MV110_i: BYTE; (*для каждого модуля своя команда - условное объявление, по факту привязана к адресу UnModDev*)
TMR_TEAM:TP; (*ТАЙМЕР ОПРОСА МОДУЛЯ*)
TIME_TEAM:TIME := T#50ms; (*ВРЕМЯ ОПРОСА МОДУЛЯ*)
END_VAR


IF I < 10 THEN I := I + 1;
IF NOT COMM_MV110[I] THEN COUNT[I] := COUNT[I] + 1;END_IF
IF COUNT[I] <= 3 THEN TMR_TEAM(IN := TRUE, PT := TIME_TEAM);
IF TMR_TEAM.Q THEN TEAM_MV110_i := 255;
ELSE TEAM_MV110_i := 254; TMR_TEAM(IN := FALSE, PT := TIME_TEAM); END_IF
ELSE TEAM_MV110_i := 254; END_IF ELSE I := 0; END_IF

Код набросал очень быстро в блокноте, даже не проверял если честно, но думаю идея должна быть видна. Пока писал понял что можно использовать массивы чем case и такое решение выглядит короче.

deniska13
08.11.2019, 09:59
А что ожидаете от TP ?

И да, уважайте других - пишите с нормальными уступами. CODE /CODE - есть.

VAR
COUNT:ARRAY [1..10] OF INT; (*массив количества опросов каждого модуля из 10*)
COMM_MV110: ARRAY [1..10] OF BOOL; (*массив ошибок связи каждого модуля*)
(*ошибка = FALSE если в регистре LAST ERROR Значение 81 при опросе модуля*)
TEAM_MV110_i: BYTE; (*для каждого модуля своя команда - условное объявление, по факту привязана к адресу UnModDev*)
TMR_TEAM:TP; (*ТАЙМЕР ОПРОСА МОДУЛЯ*)
TIME_TEAM:TIME := T#50ms; (*ВРЕМЯ ОПРОСА МОДУЛЯ*)
END_VAR

IF I < 10 THEN
I := I + 1;
IF NOT COMM_MV110[I] THEN
COUNT[I] := COUNT[I] + 1; END_IF
IF COUNT[I] <= 3 THEN
TMR_TEAM(IN := TRUE, PT := TIME_TEAM);
IF TMR_TEAM.Q THEN
TEAM_MV110_i := 255;
ELSE TEAM_MV110_i := 254; TMR_TEAM(IN := FALSE, PT := TIME_TEAM); END_IF
ELSE TEAM_MV110_i := 254; TMR_TEAM(IN := FALSE, PT := TIME_TEAM); END_IF ELSE I := 0; END_IF

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

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

deniska13
08.11.2019, 21:19
В итоге мне никто так и не помог, ни посетители-специалисты в данной области, ни производители данного оборудования, знающие его вдоль и поперек, по крайней мере мне так кажется...в общем написал код, который в симуляторе делает то что мне нужно было, буду тестировать его на реальном оборудовании через несколько дней, но как мне кажется код должен работать нормально. Суть его такова - есть ПЛК110, есть модули МВ110-16Д в количестве 10шт., находятся на удалении от ПЛК110, в PLC Configutation применена стандартная конфигурация, знаю про библиотеку Modbus, но времени на ее изучение не было, хотя походим способом я реализую чтение\запись на ПЛК BECKHOFF, но сейчас не об этом. ПЛК110 у нас мастер, модули все слэйв, в конфигурации создаем Universal modbus device, настраиваем модули (скорость, адрес, стоп бит итд...) режим работы по команде, адрес управления опросом модуля по команде присваиваем массиву команд для удобства и собственно все. Количество повторов опроса модуля у меня стоит 5, после 5 неудачных попыток (подряд!) модуль убирается из опроса (программно добавлю переменную с выводом крестика на панели на против соотв. модуля что он убран из опроса, тут это не реализовано), если ошибки шли не подряд, например 2 ошибки затем опрос прошел без ошибки, предыдущие неудачные попытки стираются...

PROGRAM PLC_PRG
VAR
COUNT_TEAM: ARRAY [1..10] OF INT; (*МАССИВ КОЛИЧЕСТВА ОШИБОК ПРИ ОПРОСЕ МОДУЛЯ, 1 ИНДЕКС МАССИВА ЭТО КОЛ-ВО
ОШИБОК ОПРОСА 1 МОДУЛЯ*)
COM_ERR: ARRAY [1..10] OF BOOL; (*МАССИВ ОШИБОК МОДУЛЕЙ - FALSE ОШИБКА ОПРОСА i - ОГО МОДУЛЯ*)
CMD_MODULE: ARRAY [1..10] OF BYTE; (*МАССИВ КОМАНД: 1 ИНДЕКС ЭТО КОМАНДА ДЛЯ 1 МОДУЛЯ - итд*)
TEAM_START:BYTE := 255; (*КОМАНДА НАЧАЛА ОПРОСА МОДУЛЯ*)
TEAM_STOP:BYTE := 254; (*КОМАНДА ПРЕКРАЩЕНИЯ ОПРОСА МОДУЛЯ*)
TMR_TEAM:TP; (*ТАЙМЕР ОПРОСА МОДУЛЯ*)
TIME_TEAM: TIME := T#50ms; (*ВРЕМЯ РАБОТЫ ТАЙМЕРА ОПРОСА МОД*)
I:INT := 1; (*ИНДЕКС ЦИКЛА*)
ERR_UNIT:WORD; (*ПЕРЕМЕННАЯ ОШИБКА ПРИВЯЗАННАЯ К АДРЕСУ РЕГИСТРА LAST ERROR*)
BUTTON_RESET_ALR_MODULE:BOOL; (*КНОПКА СБРОСА НЕУДАЧНЫХ ПОПЫТОК ОПРОСА МОДУЛЯ С ПАНЕЛИ*)
J:INT; (*ПЕРЕМЕННАЯ ВЫБОРА МОДУЛЯ ДЛЯ СБРОСА НЕУДАЧНЫХ ПОПЫТОК ОПРОСА*)
TRIG_COM_ERR:R_TRIG; (*ТРИГГЕР*)
END_VAR

IF BUTTON_RESET_ALR_MODULE THEN (*ВЫБИРАЕМ НА ПАНЕЛИ АДРЕС МОДУЛЯ J ДЛЯ КОТОРОГО ХОТИМ СДЕЛАТЬ СБРОС КНОПКОЙ*)
COUNT_TEAM[ J ] := 0; (*СОБСТВЕННО СБРОС*)
END_IF
TRIG_COM_ERR(CLK := COM_ERR[ I ]); (*ЕСЛИ ФИКСИРУЕМ ИЗМЕНЕНИЕМ С FALSE НА TRUE*)
IF TRIG_COM_ERR.Q AND COUNT_TEAM[ I ] < 5 THEN
COUNT_TEAM[ I ] := 0; (*ОБНУЛЯЕМ СЧЕТЧИК ОШИБОК*)
END_IF
IF ERR_UNIT = 81 AND CMD_MODULE[ I ] = TEAM_START THEN (*ЕСЛИ ФИКСИРУЕМ ОШИБКУ ВО ВРЕМЯ ОПРОСА i АДРЕСА МОДУЛЯ ТО*)
COM_ERR[ I ] := FALSE; (*ВЫСТАВЛЯЕМ БИТ ОШИБКИ*)
ELSIF ERR_UNIT = 0 THEN (*ЕСЛИ ОШИБКИ ВО ВРЕМЯ ОПРОСА НЕТ ТО*)
COM_ERR[ I ] := TRUE; (*ВЫСТАВЛЯЕМ БИТ ВСЕ ХОРОШО*)
END_IF

IF I <= 10 THEN
IF NOT COM_ERR[ I ] THEN
COUNT_TEAM[ I ] := COUNT_TEAM[ I ] + 1;
END_IF
IF COUNT_TEAM[ I ] < 5 THEN
TMR_TEAM(IN := TRUE, PT := TIME_TEAM);
IF TMR_TEAM.Q THEN
CMD_MODULE[ I ] := TEAM_START;
ELSIF NOT TMR_TEAM.Q THEN
CMD_MODULE[ I ] := TEAM_STOP; TMR_TEAM(IN := FALSE, PT := TIME_TEAM);
IF I < 10 THEN
I :=I + 1;
ELSE I := 1;
END_IF
END_IF
ELSE CMD_MODULE[ I ] := TEAM_STOP; TMR_TEAM(IN := FALSE, PT := TIME_TEAM);
IF I < 10 THEN
I :=I + 1;
ELSE I := 1;
END_IF
END_IF
END_IF


Если вдруг кому интересно, или есть какие-либо предложения-замечания пишите)
Заранее извиняюсь если код расположен не наглядно, не знаю как это здесь сделать, TAB не работает..

deniska13
08.11.2019, 21:41
Ну так заработало ?

в симуляторе -да, в реальности пока не могу сказать, нужно тестировать на объекте, через несколько дней поеду, протестирую, в руках подобного оборудования нет, поэтому не проверить. Если вдруг у кого есть и есть время, может протестирует код раньше чем я доеду до объекта)

deniska13
18.11.2019, 13:38
Ну так заработало ?

программа не работает, при отправке команды FF, обмена данными не происходит...