PDA

Просмотр полной версии : Задержка на языке ST



burn
10.07.2008, 12:35
Подскажите как сделать задержку на языке ST.
Аналог Sleep или Wait...

Малышев Олег
10.07.2008, 12:44
программа выполянется циклически

ну если кусочек надо сделать после определенного события

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

burn
10.07.2008, 12:53
программа выполянется циклически

ну если кусочек надо сделать после определенного события

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

Прошу прощения, но я ничего не понял:) можно комментарии к каждой строчке.

Например, я хочу, чтобы регистр менял значение через интервал в 1сек.

в обычной программе это выглядело бы примерно так:

FOR i:=1 TO 10 DO
reg:=i;
(* SLEEP 1 или что-то подобное *)
END_FOR

Gans
10.07.2008, 13:08
Прошу прощения, но я ничего не понял:) можно комментарии к каждой строчке.

Например, я хочу, чтобы регистр менял значение через интервал в 1сек.

в обычной программе это выглядело бы примерно так:

FOR i:=1 TO 10 DO
reg:=i;
(* SLEEP 1 или что-то подобное *)
END_FOR
Для того что бы разобраться просто надо ознакомится с документацией: файло «CoDeSys_V23_RU.pdf» там всё есть.
Например про функциональный блок «TON» можно прочитать на 10-54 стр., а про «R_TRIG» прочитать на 10-49 стр., «if …. Then….end_if» прочитать на 2-14 стр.
P. S. Более подробно вряд ли кто нибудь ответит, если только всё сделает за Вас :-)

Игорь Петров
10.07.2008, 13:42
...в обычной программе это выглядело бы примерно так:...

В смысле в программе на языке Си...

В МЭК программе цикл уже есть всегда. Напишите на ST простейшую программу x := x+1; и запустите, станет понятно.
Классически программа ПЛК выполняет много всяких разных операций одновременно. Все они в лоб пишутся подряд, одно за другим (цепи в LD или FBD или строки в ST) в одной программе, и крутятся в рабочем цикле. Поэтому таких мертвых задержек как в Си делать нельзя принципиально, иначе все станет на время этой задержки. Поэтому таймеры МЭК сначала запускаются в одном цикле вызова программы (по фронту входа), затем в других циклах идет опрос вышло ли время (единичка на выходе: IF...). Таймер МЭК для ПЛК это как некий внешний железный прибор, подключенный к входам/выходам. Запустили его, опрашиваем до готовности.

Подробнее тут (http://www.prolog-plc.ru/docs/st_c.pdf)

Kirill
11.07.2008, 09:09
Прошу прощения, но я ничего не понял:) можно комментарии к каждой строчке.



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;

Kiselev
17.07.2008, 12:46
Например, я хочу, чтобы регистр менял значение через интервал в 1сек.

в обычной программе это выглядело бы примерно так:

FOR i:=1 TO 10 DO
reg:=i;
(* SLEEP 1 или что-то подобное *)
END_FOR

если еще актуально, то мой вариант на эту тему:

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

незарегистрированный
23.07.2008, 19:23
Еще вариант

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 обойтись.

Филоненко Владислав
23.07.2008, 22:06
Перефразируя классиков, что только не сделают программисты ПЛК чтобы не использовать стандартные механизмы. Страна Кулибиных...Только надо ли на каждом углу велосипед изобретать?

Есть библиотека SysLibTime.lib, в которой доступно и время в секундах/минутах и т.д. и высокоточное системное время с разрешением 1 мкс.

незарегистрированный
23.07.2008, 23:16
Некоторые ученые полагают что яйца на бить с тупого конца.
Я же глубоко убежден что это неправильно. Только с острого.

Вы обалдеете, если узнаете, что любую вещь, первый раз, создал "кулибин". Без них бы в пещере у костра грелись.

Понятие "прерывание" возникло несколько раньше какого-то syslib...
Поэтому Ваши же слова я повторяю по отношению к Вам.
.........

PS
Помимо библиотек, существуют возможности самого ПЛК.

D_O_K
17.08.2008, 16:02
Нарушать работу цикла ПЛК нежелательно. Дело порой доходило до того, что в отсутствие языка 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.
Однако, в ряде случаев, использование сдвиговых регистров для организации командоаппаратов все еще остается актуальным.

Такая "кулибинщина", а не желание во что бы то ни стало "повесить" цикл ПЛК, действительно оправдана и к ней приходили многие разработчики прикладного ПО для ПЛК независимо друг от друга.

Написал об этом, чтобы проиллюстрировать общий подход к использованию модели ПЛК вне зависимости от прикладных задач.

"Тормозя" работу контроллера на единственной операции, вы тем самым лишаетесь возможности выполнять какие-то другие действия. Например, реализацию алгоритмов противоаварийных защит и интерфейса оператора.

Jolly
13.10.2017, 10:48
Здравствуйте! Вопрос по задержке. Кусок программы:
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 уже не переходят. Не могу разобраться в чем проблема...

capzap
13.10.2017, 10:53
перепишите первый кейс на

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);
а external_event выкинте из кода
либо в нулевом кейсе добавте myTON(IN:=FALSE);

Владимир Ситников
13.10.2017, 10:56
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 уже не переходят. Не могу разобраться в чем проблема...

Скорее всего, проблема в том, что вместо myTON.IN:=FALSE; нужно написать myTON(IN:=FALSE); -- иначе таймер так и не знает, что "ему нужно начать новый отсчёт времени".


А вообще, конечно, тема пересекается с идеей пауз (http://www.owen.ru/forum/showthread.php?t=27498).
Там это было бы:


PL1:=TRUE;
PL2:=FALSE;
MN1:=TRUE;
MN2:=FALSE;

ПАУЗА t#3s;

PL1:=FALSE;
PL2:=FALSE;
MN1:=FALSE;
MN2:=FALSE;

Jolly
13.10.2017, 11:38
Всем спасибо, получилось!