На объекте сложилась крайне сложная ситуация - постоянные сбои оборудования - программа время от времени не видит сработок датчиков. Никакой закономерности в наступлении подобных ослеплений не наблюдается. В шкафу ПЛК100+МДВВ, сигналы получаем и воздействия выдаем через МДВВ. 115200, 8, четность, экран. Силовая коммутация расположена здесь же, но ошибки связи крайне редки - порядка одной на 10000 опросов. Естественно, при ошибке связи цикл работы пропускается. ST. Цикл программы, как правило, не превышает 5 мс. Используется встроенная визуализация, но компьютер к ПЛК, как правило, не подключен. Логирования нет.
Все работало удовлетворительно до тех пор, пока заказчик не начал увеличивать скорость работы конвейера. Употреблялось даже слово "идеально". Текущее состояние дел именуется "не работает и не работало никогда"...
Так как этот участок конвейера работает автоматически (когда работает), - для диагностики неисправностей используются таймеры. Все двигатели включаются на время, в течение которого ожидается сработка соответствующего датчика. Если событие не наступило - диагностируется ошибка, работа механизмов блокируется и включается звонок, числом звонков в серии указывающий место сбоя. "Идеально" было, когда механизмы (и, соответственно, таймеры) включались поочередно - этот участок проезжало только одно изделие. После ускорения на этом участке конвейера одновременно находятся несколько изделий (и одновременно включены несколько таймеров TON) - тут-то и начались огромные проблемы (и изрядные финансовые убытки). Ложных сработок нет - есть пропуски сигналов, причем с разных датчиков (хотя вероятности пропуска сигналов неодинаковы для разных датчиков, - так, некоторые в пропуске сработок замечены не были).
В течение трех суток были предприняты все мыслимые и немыслимые меры обеспечения корректности работы оборудования - экранирование (раньше, как выяснилось, работало с неподключенными экранами датчиков - и ничего), замена БП (Овен. Один канал выдавал 18 В вместо положенных 24), МДВВ (производитель примененных в них реле заявляет 50000 сработок, а один из выходов отработал 60000) и ПЛК; были убраны китайские твердотельные реле, коммутировавшие пускатели; многократно проверялись датчики (транзисторные npn оптические на отражение от объекта, Китай. Особо проверялись на ложное размыкание при работе на движущийся объект с неровной поверхностью); заменялись пускатели, и т.д., и т.п. Программа перекраивалась два десятка раз, но спорадические сбои повторяются с дивной регулярностью (90% которых происходят во время отсутствия программиста на объекте).
Наконец была выявлена пренеприятная особенность - одновременная активность нескольких таймеров значительно увеличивает вероятность появления ошибок. Так, при "идеальной" работе единовременно работало не более трех таймеров, а после разгона конвейера одновременно могут быть включены до 7-8 TON, расположенных в массиве.
Исключение из программы двух таймеров принесло значительное облегчение, однако, стоило мне после вторых бессонных суток покинуть объект, - скорость задрали еще выше, и глюки посыпались вновь.
Кажется, где-то я натыкался на обещание вроде "использование множества таймеров приводит к милым сюрпризам", но никак не могу найти, где именно. Кто-нибудь может подтвердить проблемы при одновременной работе множества таймеров?
P.S. Завтра утром - момент истины. Если работа не будет налажена - меня со всем оборудованием Овен отправят в топку.
P.P.S. Запуск таймеров выглядит так:
Код:
IF front(guillotineLoaded) AND NOT guillotineOn AND NOT acceleratorOn THEN
guillotineOn := start(which := tmGuillotine);
acceleratorOn := start(tmAccel);
start(tmWndToTranspDown);
END_IF;
Внутри функции start:
Код:
tmTONs[which](in := FALSE, pt := WORD_TO_TIME(c + tmDelays[which]));
tmTONs[which](in := TRUE);
Останов так:
Код:
IF front(distributorLoaded) AND transporterOn THEN
transporterOn := stop(tmTransporter);
positionTransporter(FALSE);
END_IF;
Внутри функции stop:
Код:
tmTONs[which].IN := FALSE;
Хммм... ФБ не вызывается при останове, но ведь раньше все работало?! Да и сейчас, как правило, работает. Часами и даже сменами. А вызываются все ФБ в каждом цикле проги в массиве:
Код:
(* Даем процессорное время таймерам оборудования и заполняем столбец обратного отсчета в массиве статистики *)
FOR i := 1 TO TIMERS_UP_BOUND DO
tmTONs[i]();
tmStat[TIMERS_CURRENT, i] := TIME_TO_WORD(tmTONs[i].PT - tmTONs[i].ET);
IF tmTONs[i].ET = t#0ms THEN
tmStat[TIMERS_CURRENT, i] := 0;
END_IF;
END_FOR;
Проверка таймаута:
Код:
IF acceleratorOn AND tmTONs[tmAccel].Q THEN
acceleratorOn := err(_ERR_ACCELERATOR_TIMEOUT_);
END_IF;
Функция err устанавливает переменную номера ошибки, при ненулевом значении которой программа просто не вызывается.