Подскажите как сделать задержку на языке ST.
Аналог Sleep или Wait...
Вид для печати
Подскажите как сделать задержку на языке ST.
Аналог Sleep или Wait...
программа выполянется циклически
ну если кусочек надо сделать после определенного события
myTON:TON;
myR_TRIG:R_TRIG;
myTON(IN:=external_event,PT:=t#10s500ms);
myR_TRIG(CLK:=myTon.Q);
if myR_TRIG.Q then
(*
действие после задержки - однократно
*)
end_if
Для того что бы разобраться просто надо ознакомится с документацией: файло «CoDeSys_V23_RU.pdf» там всё есть.
Например про функциональный блок «TON» можно прочитать на 10-54 стр., а про «R_TRIG» прочитать на 10-49 стр., «if …. Then….end_if» прочитать на 2-14 стр.
P. S. Более подробно вряд ли кто нибудь ответит, если только всё сделает за Вас :-)
В смысле в программе на языке Си...
В МЭК программе цикл уже есть всегда. Напишите на ST простейшую программу x := x+1; и запустите, станет понятно.
Классически программа ПЛК выполняет много всяких разных операций одновременно. Все они в лоб пишутся подряд, одно за другим (цепи в LD или FBD или строки в ST) в одной программе, и крутятся в рабочем цикле. Поэтому таких мертвых задержек как в Си делать нельзя принципиально, иначе все станет на время этой задержки. Поэтому таймеры МЭК сначала запускаются в одном цикле вызова программы (по фронту входа), затем в других циклах идет опрос вышло ли время (единичка на выходе: IF...). Таймер МЭК для ПЛК это как некий внешний железный прибор, подключенный к входам/выходам. Запустили его, опрашиваем до готовности.
Подробнее тут
myTON:TON; (*определение фун блока таймера*)
myR_TRIG:R_TRIG; (*определение фун блока детектора переднего фронта*)
myTON(IN:=external_event,PT:=t#10s500ms); (*инициализация ФБ таймера, если переменная external_event переходит в true, то начинается отсчет времени, по окончании отсчета выход Q переходит в true*)
myR_TRIG(CLK:=myTon.Q); (*детектирование переднего фронта выхода Q*)
if myR_TRIG.Q then (*если передний фронт есть, то выполняются действия внутри условия*)
(*
действие после задержки - однократно
*)
end_if;
если еще актуально, то мой вариант на эту тему:
FUNCTION_BLOCK example
VAR_INPUT
iVar: INT;
END_VAR
VAR_OUTPUT
END_VAR
VAR
timer: TON;
iReg: INT;
END_VAR
--------------------------------------
timer(IN:= NOT timer.Q, PT:=T#1s ); (* вызов таймера с самосбросом*)
IF timer.Q (* присваивание регистру (iReg) значения iVar будет происходить раз в 1 сек*)
THEN
iReg:=iVar;
END_IF
Еще вариант
i - глобальная переменная
Пишете ПРОГРАММУ MY_COUNT
i:=i+1;
Залезаете в task config..
Создаете новую задачу - MY_TASK1
к ней цепляете MY_COUNT
type ставите ciclyc
interval = одна секунда.
Вот и все.
Типа обработки прерывания.
В PLC_PRG спокойно читаете i
PS
Только кажется к MY_TASK2 придется прицепить
PLC_PRG c type = freewheeling.
Тут можно вообще без PLC_PRG обойтись.
Перефразируя классиков, что только не сделают программисты ПЛК чтобы не использовать стандартные механизмы. Страна Кулибиных...Только надо ли на каждом углу велосипед изобретать?
Есть библиотека SysLibTime.lib, в которой доступно и время в секундах/минутах и т.д. и высокоточное системное время с разрешением 1 мкс.
Некоторые ученые полагают что яйца на бить с тупого конца.
Я же глубоко убежден что это неправильно. Только с острого.
Вы обалдеете, если узнаете, что любую вещь, первый раз, создал "кулибин". Без них бы в пещере у костра грелись.
Понятие "прерывание" возникло несколько раньше какого-то syslib...
Поэтому Ваши же слова я повторяю по отношению к Вам.
.........
PS
Помимо библиотек, существуют возможности самого ПЛК.
Нарушать работу цикла ПЛК нежелательно. Дело порой доходило до того, что в отсутствие языка SFC в средах разработки некоторых ПЛК, программисты для организации последовательностей программных командоаппаратов делали следующее:
обявлялась переменная типа WORD или DWORD. Например с именем STEP_CONTROL.
А отдельные ее битовые поля использовались в качестве битов разрешения того или иного шага технологической последовательности:
STEP_CONTROL.0
STEP_CONTROL.1
STEP_CONTROL.2
...
При старте ПЛК переменная STEP_CONTROL инициализировалась значением "1". Т.е. программа приводилась в состояние "нулевого шага".
Так же, организовывалась переменная STEP_ON, которая переводилась из состояния "0" в состояние "1" тогда, когда срабатывал тот или иной критерий завершения шага последовательности.
При этом, занчение обрабатывалось функцией триггера "по фронту", что приводило в вызову функции "сдвиг влево" для переменной STEP_CONTROL, в результате чего технологическая последовательность перемещалась на следующий шаг.
Единичка, сдвигаемая в переменной STEP_CONTROL именовалась на внутреннем жаргоне в ряде производственных коллективов "пузырьком", а сам процесс написания отладки таких программ - "гонять пузырь".
С повышением культуры поставщиков инструментального ПО и приведением средств разрабоки к требованием МЭК такая необходимость отпала, поскольку стало возможным использовать средства языка описания технологических последовательностей SFC.
Однако, в ряде случаев, использование сдвиговых регистров для организации командоаппаратов все еще остается актуальным.
Такая "кулибинщина", а не желание во что бы то ни стало "повесить" цикл ПЛК, действительно оправдана и к ней приходили многие разработчики прикладного ПО для ПЛК независимо друг от друга.
Написал об этом, чтобы проиллюстрировать общий подход к использованию модели ПЛК вне зависимости от прикладных задач.
"Тормозя" работу контроллера на единственной операции, вы тем самым лишаетесь возможности выполнять какие-то другие действия. Например, реализацию алгоритмов противоаварийных защит и интерфейса оператора.
Здравствуйте! Вопрос по задержке. Кусок программы:
CASE FLG OF
0:
external_event:=TRUE;
PL1:=TRUE;
PL2:=FALSE;
MN1:=TRUE;
MN2:=FALSE;
FLG:=1;
1:
myTON(IN:=external_event, PT:=t#3s);
myR_TRIG(CLK:=myTon.Q);
IF myR_TRIG.Q THEN
PL1:=FALSE;
PL2:=FALSE;
MN1:=FALSE;
MN2:=FALSE;
FLG:=2;
END_IF
2:
external_event:=FALSE;
myTON.IN:=FALSE;
END_CASE
Смысл такой: при входе в CASE переменные PL1, PL2, MN1, MN2 принимают значения TRUE, FALSE, TRUE, FALSE соответственно на 3 секунды, потом все переходят в FALSE. В другой части программы они меняют свои значения. При повторном входе в CASE они опять принимают нужные значения TRUE, FALSE, TRUE, FALSE соответственно на 3 секунды, но в FALSE уже не переходят. Не могу разобраться в чем проблема...
перепишите первый кейс наа external_event выкинте из кодаЦитата:
1:
IF myR_myTON.Q THEN
PL1:=FALSE;
PL2:=FALSE;
MN1:=FALSE;
MN2:=FALSE;
FLG:=2;
END_IF
myTON(IN:=NOT myTON.Q, PT:=t#3s);
либо в нулевом кейсе добавте myTON(IN:=FALSE);
Скорее всего, проблема в том, что вместо myTON.IN:=FALSE; нужно написать myTON(IN:=FALSE); -- иначе таймер так и не знает, что "ему нужно начать новый отсчёт времени".
А вообще, конечно, тема пересекается с идеей пауз.
Там это было бы:
Код:PL1:=TRUE;
PL2:=FALSE;
MN1:=TRUE;
MN2:=FALSE;
ПАУЗА t#3s;
PL1:=FALSE;
PL2:=FALSE;
MN1:=FALSE;
MN2:=FALSE;
Всем спасибо, получилось!