В итоге мне никто так и не помог, ни посетители-специалисты в данной области, ни производители данного оборудования, знающие его вдоль и поперек, по крайней мере мне так кажется...в общем написал код, который в симуляторе делает то что мне нужно было, буду тестировать его на реальном оборудовании через несколько дней, но как мне кажется код должен работать нормально. Суть его такова - есть ПЛК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 не работает..




Ответить с цитированием