Никаких выводов не сделали, зачем вам 8 таймеров, если одного за глаза, только время меняйте и запускайте снова, так же по шагам.
Даже пример готовый выкладывал, только кол-во шагов уменьшить осталось и нужные выходы включать.
Никаких выводов не сделали, зачем вам 8 таймеров, если одного за глаза, только время меняйте и запускайте снова, так же по шагам.
Даже пример готовый выкладывал, только кол-во шагов уменьшить осталось и нужные выходы включать.
Последний раз редактировалось kondor3000; 11.02.2024 в 17:24.
Я повторно предлагаю вам попробовать SFC, чтобы решать подобные задачи
Можно конечно применить эрзац SFC на ST:
Код:FUNCTION_BLOCK SFC VAR_INPUT xInBtnStart, xInBtnStop: BOOL; InTime: INT; END_VAR VAR_OUTPUT OutState: enState; xOutError, xOutCtrl, xOutAdd: BOOL; END_VAR VAR Init: BOOL; NewState: enState := gc_step_0; tTime: TIME; fbBtnStart, fbBtnStop: R_TRIG; fbTON: TON; END_VAR (* КОД ВЫПОЛНЯЕМЫЙ ВСЕГДА *) fbBtnStart(CLK := xInBtnStart); fbBtnStop(CLK := xInBtnStop); xOutError := FALSE; IF NOT Init THEN Init := TRUE; NewState := gc_step_0; ELSE CASE NewState OF (* Шаг 1 *) gc_step_0: (* ДЕЙСТВИЯ ПРИ ВХОДЕ В ШАГ *) IF NewState <> OutState THEN OutState := NewState; END_IF; (* ДЕЙСТВИЯ *) xOutCtrl := xInBtnStart; (* call sw ctrl timer *) fbTON(IN := TRUE, PT := T#10s); (* ПЕРЕХОДЫ *) IF fbBtnStart.Q AND fbTON.Q THEN NewState := gc_step_1; fbTON(IN := FALSE); (* ELSIF УСЛОВИЕ THEN NewState := НОВОЕ СОСТОЯНИЕ; ELSIF УСЛОВИЕ THEN NewState := НОВОЕ СОСТОЯНИЕ; *) END_IF; (* (* ДЕЙСТВИЯ ПРИ ВЫХОДЕ ИЗ ШАГА *) IF NewState <> OutState THEN END_IF; *) (* Шаг 2 *) gc_step_1: (* ДЕЙСТВИЯ ПРИ ВХОДЕ В ШАГ *) IF NewState <> OutState THEN fbTON.PT := T#30s; IF InTime > 0 THEN fbTON.PT := REAL_TO_TIME(InTime * 1000.0); END_IF; END_IF; (* ДЕЙСТВИЯ *) OutState := NewState; xOutCtrl := TRUE; (* call sw ctrl timer *) fbTON(IN := TRUE); (* ПЕРЕХОДЫ *) IF fbBtnStop.Q THEN NewState := gc_step_0; ELSIF fbTON.Q THEN NewState := gc_step_2; fbTON(IN := FALSE); (* ELSIF УСЛОВИЕ THEN NewState := НОВОЕ СОСТОЯНИЕ; ELSIF УСЛОВИЕ THEN NewState := НОВОЕ СОСТОЯНИЕ; *) END_IF; (* (* ДЕЙСТВИЯ ПРИ ВЫХОДЕ ИЗ ШАГА *) IF NewState <> OutState THEN END_IF; *) (* Шаг 3 *) gc_step_2: (* ДЕЙСТВИЯ ПРИ ВХОДЕ В ШАГ *) IF NewState <> OutState THEN OutState := NewState; END_IF; (* ДЕЙСТВИЯ *) xOutError := TRUE; xOutCtrl := FALSE; (* ПЕРЕХОДЫ *) IF fbBtnStop.Q THEN NewState := gc_step_0; (* ELSIF УСЛОВИЕ THEN NewState := НОВОЕ СОСТОЯНИЕ; ELSIF УСЛОВИЕ THEN NewState := НОВОЕ СОСТОЯНИЕ; *) END_IF; (* (* ДЕЙСТВИЯ ПРИ ВЫХОДЕ ИЗ ШАГА *) IF NewState <> OutState THEN END_IF; *) (* ОШИБКА СОСТОЯНИЯ *) ELSE OutState := gc_step_0; END_CASE; (* КОД ВЫПОЛНЯЕМЫЙ ВСЕГДА *) xOutAdd := NewState = gc_step_0 OR gc_step_1; END_IF;
Вы про GetTime? Если да, то я не понимаю как это работает.
Таймер.png
Шаг 7, это когда все узлы установки нормально запущены, то есть установка полностью в работе.
7шаг.png
Что не понятного тут? В зависимости от входящего шага State, меняется время для таймера, для каждого шага своё время. Например для шага State=1 время t0=5.
Время в таймере надо задавать в ms, так как время конвертируется PT= UDINT_TO_TIME (CurMinute),
если не умножить на 1000, то вы получите 5ms, и шаги просто пролетят с 1 до 12 за пол секунды.
Умножение на 1000 это перевод времени в секунды, 5*1000=5000ms=5секунд,
а умножение на 60000 перевод в минуты 5*60000=300 000ms=300 секунд=5 минут
Переменная Zad и переключает либо отсчёт в секундах, либо в минутах. Там ведь даже подписано!
Всё что нужно сделать, запустить эмуляцию, нажать Старт и смотреть как работает.
Последний раз редактировалось kondor3000; 11.02.2024 в 19:15.
Вы в этой строчке записывате значение во ВХОДНУЮ ПЕРЕМЕННУЮ "ALARM_STOP" (в принципе, не возбраняется)
чтобы потом здесьКод:IF TON8_OUT THEN ALARM_STOP:=TRUE; step:=0;END_IF
сбросить SR1Код:IF START AND SR1_OUT AND AUTO AND step=0 AND TP1_OUT THEN step:=1;END_IF TP1(IN:=SR1_OUT, PT:=T#20s , Q=>TP1_OUT , ET=> ); SR1(SET1:=START , RESET:=ALARM_STOP , Q1=>SR1_OUT );
Но здесь значение ВХОДНОЙ ПЕРЕМЕННОЙ "ALARM_STOP" уже будет иметь то значение, что пришло на этот вход (ALARM_STOP) СНАРУЖИ.
И если это FALSE, то соответственно сброса SR1 не происходит
Ну в основном конечно это реализация входных/выходных действий и таймера шагов. Может кто-то уже занимался этим или исходник библиотеки SFC имел
Это наверно больше вопрос удобства - логика выполнения же не меняется от этого.
Мне удобнее, когда все действия шага в одном месте
Вот смотрю на варианты и всегда вижу почерк автора...
Кто-то (как ТС) выход таймера через => делает, но использует лишнюю переменную.
Кто-то (как и я) через TIMER.Q...
Сколько людей, столько и решений одной задачи. Поэтому надо свое придумывать, или перенимать наиболее понравившуюся манеру написания...