1exan Выкладываю. Вот в виде кода. На CodeSys 3.5 работает норм.
ДОПОЛНЕНИЕ: ВОПРОС СНЯТ. Всё-таки глюк был именно в моём исходном соде на CodeSys 3.5. Вот видео: https://cs-cs.net/ExxChange/CSDrvPwrDir-BugDemo.avi
На нём видно, что после выключения первого реле второе "мигает", а должно работать с задержкой.
Здесь он уже портирован на OWL, и там переменные типа TIME на входах переведены в UDINT и мсек.
PHP код:
FUNCTION_BLOCK CSDrivePwrDir //имя функционального блока.
(*
TODO: Проверить глюк реле Dir при командах остановки: оно тут кратковременно включается, хотя не должно!
TODO: Добавить отсчёт времени работы блока (через BLINK по секундно)
*)
(* Универсальный блок драйвера сигналов Power/Direction для управления кранами, шторами и другими
устройствами, которые управляются сигналами Питание (реле 1) и Направление (реле 2).
По входу такой блок принимает множество настроек и видов команд для управления по длительности
или от начала до конца. Внутри блока находится конечный автомат, который правильно отслеживает
нужные состояния блока.
Сам блок поддерживает состояния выдержки перед подачей команд Питания и Направления и противоположных
команд открытия и закрытия, чтобы реле их управления не слипались.
Блок портирован из CodeSys 3.5. Copyright © 2023-2024 Cs-Cs.Net Lab https://cs-cs.net *)
VAR_INPUT
//Команды управления блоком
OpValue : BOOL; //Команда: Открыть-Закрыть ПО УРОВНЮ (TRUE - Открыть, FALSE - Закрыть), активируется по WorkModeByValue
CmdStop : BOOL; //Команда: Немедленно остановить операцию, наплевав на остальные команды
CmdOpenPart : BOOL; //Команда: Открывать, пока действует уровень (TRUE - идёт процесс ОТкрытия, FALSE - стоп)
CmdClosePart : BOOL; //Команда: Закрывать, пока действует уровень (TRUE - идёт процесс ЗАкрытия, FALSE - стоп)
CmdOpenFull : BOOL; //Команда: Открыть полностью до конца (TRUE - команда начинает выполняться по фронту)
CmdCloseFull : BOOL; //Команда: Закрыть полностью до конца (TRUE - команда начинает выполняться по фронту)
//Настройка главного режима работы блока
WorkModeByValue : BOOL := FALSE; //Включить управление блоком ПО УРОВНЮ (OpValue) - команды импульсного управления будут недоступны
//Настройки режимов работы блока
UseStopByFullSame : BOOL := FALSE; //Останавливать текущую операцию (аналог CmdStop) при повторном нажатии на кнопку CmdxxxFull
UseStopByFullRev : BOOL := FALSE; //Останавливать текущую операцию (аналог CmdStop) при нажатии на противоположную кнопку CmdxxxFull
UseWorkTimer : BOOL := TRUE; //Использовать подачу команд по таймеру (для уровней и Полных), иначе - всегда (TimeWorkTime)
UseDelayITL : BOOL := TRUE; //Использовать задержку между противоположными командами (TimeDelayITL)
UseDelayDIR : BOOL := TRUE; //Использовать задержки между командами Питания и Направления (TimeDelayDIR)
UseReverseDIR : BOOL := FALSE; //Инвертировать сигнал открытия (будет FALSE - Открыть, TRUE - Закрыть)
//Времена режимов работы блока
TimeWorkTime : UDINT := 25; //Время длительности выполнения одной операции (секунд)
TimeDelayITL : UDINT := 250; //Время выдержки при подаче противоположных команд (Открыть <> Закрыть, UseDelayITL) (мсек)
TimeDelayDIR : UDINT := 500; //Время выдержки между сигналами Питание и Направление (UseDelayDIR) (мсек)
END_VAR
VAR_OUTPUT
//Выходные переменные
RelayPower : BOOL; //Сигнал на реле: Питание
RelayDir : BOOL; //Сигнал на реле: Направление
StateInOp : BOOL; //Статус: Текущая операция выполняется (любая)
StateOpening : BOOL; //Статус: Идёт открытие
StateClosing : BOOL; //Статус: Идёт закрытие
TimeRemainOp : UDINT; //Оставшееся время до конца операции (секунд)
END_VAR
END_FUNCTION_BLOCK
ДОПОЛНЕНИЕ: Убрал код реализации. Не хочу его сильно прям вот распространять. Да и на OWL он плохо работает ещё.
PS. Как так ты красиво код вставил?