добрый день,
судя по описанию в справке RISING_EDGE можно использовать только на ФБД и ЛД. А если на СТ пишу, то как им воспользоваться? Или только циклическая запись остается мне?
Вид для печати
добрый день,
судя по описанию в справке RISING_EDGE можно использовать только на ФБД и ЛД. А если на СТ пишу, то как им воспользоваться? Или только циклическая запись остается мне?
Пост для экстрасенсов? Ладно, побуду экстрасенсом.
Когда вы ставите канал в режим работы по фронту (он же RISING™ EDGE®), то у вас в таблице привязки появляется битовая запись, к которой вы можете привязать булевую переменную. В дальнейшем на каком угодно языке в нужные вам моменты вы переводите эту переменную из FALSE в TRUE, чем и образуете передний фронт.
Кратовато написал я, конечно, но вы поняли правильно что я имел в виду. Попробовал, вроде работает, но не понял на какое время минамально необходимо держать в состоянии ТРУ триггерную переменную? пробовал сбрасывать на следующем цикле, не хватает ей времени, видимо. Если ставлю ТРУ и не снимаю, то срабатывает.
Да.Цитата:
Кратовато
А зачем именно вам этот режим работы? У меня вот он используется всего для трёх регистров, через которые панель передаёт команды оператора на другой ПЛК, и я спокойно могу ставить хоть целую секунду — быстрее оператор всё равно не работает. Пробовал снижать значение до 50 мс — работало.
Хочу использовать его для релейного модуля му110-16Р, писать туда в цикле нет никакого желания - всю полосу забивают несколько релейных модулей, т.к. из-за наличия ПЧВ пришлось снизить частоту до 38200 кбод. Смысла писать постоянно одно и то же значение в течении нескольких часов нет никакого.
Ну значит у вас обработка выхода триггера происходит раньше, чем вызов этого триггера, поэтому выход обрабатывается в следующем цикле ПЛК, когда он уже FALSE.
Я ради теста в пустом проекте сейчас сделал вот так - работает так, как надо, как ожидалось.
Либо обнуляеете вход до вызова триггера.Код:PROGRAM PLC_PRG
VAR
re: R_TRIG;
a, b: BOOL;
END_VAR
a; (*это чтобы онлайн присвоить ей правду*)
re (clk := a);
IF a THEN
a := FALSE;
END_IF;
IF re.q THEN
b := TRUE;
END_IF;
END_PROGRAM
b := true; - это действие, которое выполняется по триггеру.
Тут всё предельно просто, прочитайте повнимательнее.
Lode Runner не слишком громоздко для ловли переднего фронта?
Код:VAR
uno,duo : BOOL;
END_VAR
IF uno AND NOT duo THEN
;(*любые действия выполняющиеся однократно по переднему фронту переменной uno*)
END_IF;
duo:=uno;
Видимо я чего-то сильно не понимаю в особенностях программирования на МЭК.
почему такой код не работает:
а такой работает:Код:VAR_GLOBAL
f: BOOL := FALSE;
t: Standard.TON;
END_VAR
IF (f = FALSE) THEN
f:=TRUE;
t(IN:=f, PT:=T#2S);
END_IF
IF (t.Q) THEN
f := FALSE;
END_IF
Код:VAR_GLOBAL
f: BOOL := FALSE;
t: Standard.TON;
END_VAR
(*IF (f = FALSE) THEN *)
f:=TRUE;
t(IN:=f, PT:=T#2S);
(*END_IF*)
IF (t.Q) THEN
f := FALSE;
END_IF
???
Не понятно, что вы хотели добиться?
хотел, что бы t.q сработало.
т.е. вопрос, почему однократная инициализация глобальной переменной не приводит к срабатыванию таймера?
Понятно?Код:VAR_GLOBAL
f: BOOL := FALSE;
t: Standard.TON;
END_VAR
IF (f = FALSE) THEN // При первом вызове данного ЕСЛИ мы войдем внутрь условия и начнем выполнять ФБ таймера.
f:=TRUE; // При последующих вызовах данной программы внутрь условия мы не зайдем, так как f = TRUE.
t(IN:=f, PT:=T#2S); // Чтобы таймер досчитал до 2сек., его надо вызывать. Он у вас вызвался 1 только раз, дальше вы к этому таймеру не обращаетесь
END_IF
IF (t.Q) THEN // Соответственно таймер до конца не досчитал и t.q не появилось.
f := FALSE;
END_IF
Ну и немного теории по работе контроллера:
Вложение 15364
Прогон программы ПЛК и организация памяти: (а) действие ПЛК; (б) последовательность выполнения программы; (в) организация памяти ПЛК
Я себе несколько по другому это представлял. Видимо, предыдущий опыт программирования в не-МЭК средах сказывается.
Теперь вроде все встает на свои места.
т.е. обращение к t.Q для проверки его состояния не является обращением к самому таймеру?
что тогда считать обращением к ФБ? для ТОН достаточно будет обновлять значение IN, или надо еще и РТ обновлять?
Если вы хотите обратиться к выходу таймера - пишите t.Q
Чтобы таймер работал (считал, выполнялся) надо его вызывать. Т.е. таймер должен вызываться безусловно, всегда. Если таймер надо перезапустить, следует переменную на входе IN хотя бы на один такт изменить с 1 на 0 и обратно.
В следующем коде пример периодического сигнала (выход t.q) с длиной импульса = один такт.
Код:VAR_GLOBAL
f: BOOL := FALSE;
t: Standard.TON;
END_VAR
t(IN:=f, PT:=T#2S);
IF (t.Q) THEN
f := FALSE;
ELSE
f := TRUE;
END_IF
Лучше, конечно, говорить о вызове, а не об обращении. «Обновлять» (а правильнее — присваивать значение) обязательно только с переменными типа VAR_IN_OUT. На примере с таймером можно один раз сделать timer(IN := TRUE, PT := T#3s), а дальше просто timer(); или даже timer; (за такое я хочу убивать), чтобы таймер работал. Однако timer.Q уже не будет вызовом ФБ таймера, это обращение к переменной ФБ без вызова.Цитата:
т.е. обращение к t.Q для проверки его состояния не является обращением к самому таймеру?
Отвыкаем писать бессмысленный код. Всё сводится к t(IN := NOT t.Q, PT := T#2s). Самосброс называется. Идиома.Цитата:
Код:VAR_GLOBAL
f: BOOL := FALSE;
t: Standard.TON;
END_VAR
t(IN:=f, PT:=T#2S);
IF (t.Q) THEN
f := FALSE;
ELSE
f := TRUE;
END_IF