Люди! Не дайте мозгу взорваться...
Написал небольшую тестовую программку. Объясните, пожалуйста, почему !YES работает, а !NO не работает? Разница только в том, что есть IF...
Скриншоты и файлы прикладываю...
Вид для печати
Люди! Не дайте мозгу взорваться...
Написал небольшую тестовую программку. Объясните, пожалуйста, почему !YES работает, а !NO не работает? Разница только в том, что есть IF...
Скриншоты и файлы прикладываю...
1.Зачем вызывают ФБ ?
2.Чем таймеры отличается от ФБ ?
3.Что такое TOF ?
4.А когда и с какими параметрами он вызывается у Вас ?
Ну и делаем выводы
Q внутри условия хоть как будет TRUE потому что само условие у вас как раз по переменной Q. А ещё мы не знаем, как там у вас CLK изменяется.Цитата:
Просто TOF как бы "подвисает" о включенном состоянии- т.е. CLK и Q остаются в состоянии TRUE. А почему такое происходит - загадка.
TON вверх ногами.Цитата:
Что такое TOF ?
CLK меняется просто - это нажатие кнопочки. Я все равно не понимаю.... В моем понимании, вся программа PLC_PRG вместе с ФБ и прочим крутятся в цикле. Т. е. я нажал кнопку, Q включилось и сразу же выключилось - это же выход детектора переднего фронта, и начал работать отсчет времени TOF. Ведь в !YES же все так и работает...:confused:
Честное слово, голова уже не работает... Написал достаточно большой кусок своей первой программы, понадобился таймер, и на тебе...:(
Нет. Как только Q перешёл в FALSE, таймер останавливается потому что вы его больше не вызываете — не заходите в условие. Вообще таймер под триггером это... как-то нетрадиционно что ли.Цитата:
Q включилось и сразу же выключилось - это же выход детектора переднего фронта, и начал работать отсчет времени TOF
!YES - это то, на чем я тренируюсь. Беру кусок кода и проверяю, как он работает.. А !NO - это то, что мне надо.
!NO на самом деле - это кусок длинного IF - ELSIF... В одном месте мне надо в течении 3-х секунд передавать TRUE одному ФБ... TOF мне показался наиболее подходящим... А как еще эту задачу можно решить?
WHILE по времени вообще пользоваться нельзя, как я понял - сторожевой таймер будет ругаться...
И еще один дурацкий вопрос: Где более правильно обзывать входы ПЛК? В глобальных переменных, или как я - в конфигураторе ПКЛ?
Я так понимаю, что если в глобальных переменных, то получится более "универсальный" код, однако при замене платформы адреса все равно съедут... Или я неправ?
Или может есть какой способ "перетаскивания" из конфигуратора ПЛК в GLOBAL_VARS ? Типа обозвал входы-выходы, написал комментарии - а оно бабах, и красота... :)
И что бы два раза не вставать - как вообще меняется платформа? Вот написал я под ПЛК110-60, а потом решил использовать этот же проект на ПЛК-100... В настройках целевой платформы я поменял платформу, а дальше?
Объявлять переменные можно где удобней. Особой разницы нет. Если вы меняете платформу, то в любом случае необходимо ручками переписывать переменные, хоть объявленные в конфигураторе, хоть по прямым адресам.
С условием по выходу триггера проще делать без таймера:Цитата:
Теперь осталось понять, как правильно вызывать таймер по IF...
Код:VAR
timeout: TIME;
output: BOOL;
END_VAR
IF что-нибудь THEN
timeout := TIME() + T#5s;
END_IF
output := TIME() >= timeout;
А у нас TIME() меньше 0 при старте ?
То что изображено - это NOT TOF.Q
К первому циклу уже больше, если не ошибаюсь.Цитата:
А у нас TIME() меньше 0 при старте ?
В данном случае немного иначе: «если „что-нибудь“ TRUE, то на следующие 5 секунд output сделать FALSE, в остальное время держать TRUE».Цитата:
"Если 'что-нибуть' TRUE, то через 5 сек. output будет TRUE"... Так?
Таймер в таких ситуациях задалбывает требованием его вызывать. Если б хоть можно было писать timer(IN := ..., NOT Q => output) — ан нет, хрен тебе (при том, что в диаграммах отрицание ставится на любой вход или выход). В итоге лишние строки. Конечно, когда условие включения таймера держится, то лучше использовать нормальные TON, TOF и т.п.
А ничего, что при постоянном что-нибудь=TRUE output будет иногда подниматься ?Код:VAR
timeout: TIME;
output: BOOL;
END_VAR
IF что-нибудь THEN
timeout := TIME() + T#5s;
END_IF
output := TIME() >= timeout;
При «постоянном что-нибудь=TRUE» output будет постоянно FALSE. Ну и вообще я не просто так ограничил применимость этого решения:Цитата:
С условием по выходу триггера
Авторы Arian-5 тоже так предполагали :)
Т.е. этот код зависит не только от "что-нибудь" ?
Цитата:
В 1996 году отличились французы. Из-за ошибок в программном обеспечении 4 июня был прерван полет космической ракеты Ariane 5. Убытки в результате составили более 500 миллионов долларов. А причина крылась в том, что по недосмотру переменная, которая описывала горизонтальную скорость ракеты, была представлена целым 16-битным числом. В результате, как только эта значение переменной превысило 32 768 (2 в 15-й степени), система управления ракетой, что называется, “подвисла”, а “сошедшую с ума” ракету пришлось уничтожить.
Цитата:
уже в 90-х годах. На этот раз пострадали бравые американские военные ракетчики, принимавшие участие в операции “Буря в пустыне”. К их удивлению, ракеты “Пэтриот”, использовавшиеся для перехвата в воздухе иракских ракет, периодически проходили мимо цели. Разбирательства начались после того, как пропущенная иракская ракета привела к гибели 28 американских солдат. Первоначально зародилось подозрение, что часть “Пэтриотов” технически неисправны. Однако созданная по этому поводу комиссия с удивлением обнаружила, что все обследованные ракеты абсолютно работоспособны. Вы уже, наверное, догадались, где пряталась ошибка? Конечно же, в программном обеспечении, использовавшимся американским зенитно-ракетным комплексом. Выяснилось, что система создавалась в расчете на то, что время ее непрерывной работы не будет превышать 14 часов, однако на практике комплексы непрерывно работали по 100 и более часов.Вроде бы пустяк, но оказалось, что используемое для определения времени программное обеспечение накапливало ошибки. За 100 часов работы набегала разница в 0,34 секунды. Программисты, оказывается, знали об этом, да посчитали факт несущественным...
Да хоть и триггером - те же проблемы. И тогда же :Цитата:
При «постоянном что-нибудь=TRUE» output будет постоянно FALSE. Ну и вообще я не просто так ограничил применимость этого решения ..c условием по выходу триггера
Бывает такая нездоровая фигня как стабильное питание и безаварийная работа. Ну мы ж сразу закладываем броски и ПНР бесконечно-периодический...Цитата:
ввиду, когда пройдет 49 с хвостиком суток от включения плк
Ну вот. А человек защиту на АЭС делал.
Дело в том, что TIME() возвращает не время, а кольцо всевла... времени. Тип TIME - 32 бита, и читаем про ArianЦитата:
А почему
А кто-нибудь вообще проверял, как стандартные таймеры воспринимают заход на второй круг? Забавно будет узнать, что и там гарантий нет =)Не лукавьте, заведённый от триггера таймер тут же остановится.Код:var
tof1 : TOF := ( PT := T#5s);
end_var
tof1( in := что-нибуть );
output := not tof1.q;
Но вообще соглашусь. Занимаясь круглосуточными процессами, надо знать про 49 суток и обходить стандартные средства только с большой осторожностью.
Вот. Конструктив.
А как через 0 (??). У неактивных отсчет сброшен - это гарантия.
1.TON - ET как бы и не может перейти PT. (есть конечно некоторая неясность - но зна-а-ачительно реже она может быть)
2.TOF - а тоже самое.
3.TP - а ему зачем быть другим.
Вроде какие-то флажки (M) имеют - наверное проблема ими так и решена.
PS
Прерывание по времени и i:=i+1. На одном этом и строится любое кол-во таймеров.
И 0 не страшен. + флажочек.Цитата:
следить за разностью
Ой, да ладно! Чё за ней следить?
http://images.devs-on.net/Image/sQhv...ysUntitled.png
Вам нужен отсчет от фронта ? - TP.Цитата:
заведённый от триггера таймер тут же остановится.
tp(in:=что-нибудь);
output:=not tp.q;
Ну нужно четкое задание - как часто могут быть импульсы (наложутся ли ?), какая длинна их может быть, может ли быть при старте (вкл.пит) 1 ? Все это надо учесть. И после этого - решать таймеры, time() или еще как.
Это-то я знал. Просто не так понял слова «следить за разностью». И облом со сравнением тут не отменяется.Цитата:
бинго, главное самому попробовать не правда ли
Отменяется.Цитата:
облом со сравнением тут не отменяется.
супротивЦитата:
if что-нить then
tm:=time() + 5s;
end_if
output := TIME() >= timeout;
как плотник супротив столяраЦитата:
if что-нить then
tm:=time();
end_if
output:=(time()-tm)>5s;
+флажок
Я не про это конкретно сравнение. Ну да ладно. Всё, что надо, прожевали. Удаляюсь.
Всем спасибо за участие! Буду пробовать дальше... :)
Ты это, аккуратней там с АЭС.. Вишь как бывает
Что бы два раза не вставать...
Я тут приложил свой первый проектик умнодомный... Что-то у меня там там в ФБ Prisut не хочет переменная назначаться... Очередная загадка...:confused:
Поможите, кто чем может. На всякие формулы и вычисления можно не обращать внимания - они работают как надо... :)
Утром глянул на написанное - действительно фигня какая-то... :mad:
Да и TOF здесь не подойдет... Попробую фомализовать задачу.
Добавил в ФБ Prisut входную переменную pp - сигнал с датчика движения..
IF NOT pp THEN (*пропало движение*)
"начинаем медленно уменьшать яркость (OUT1) до нуля";
ELSIF pp AND OUT1 > 0 THEN (*пропало движение, но кто-то обратно вошел или пошевелился*)
OUT1 := light; (*возвращаем яркость как было*)
END_IF
Как сделать медленный декремент? :confused:
Вот моя глушилка резких движений для аналогового выхода:AO1 — аналоговый выход, Power — уставка, 0.016 — максимальное изменение в вольтах за миллисекунду.Код:VAR
MaxOutputDelta: REAL;
PrevScanTimestamp: TIME;
END_VAR
MaxOutputDelta := TIME_TO_REAL(TIME() - PrevScanTimestamp) * 0.016;
AO1 := AO1 + LIMIT(-MaxOutputDelta, Power - AO1, MaxOutputDelta);
PrevScanTimestamp := TIME();
Так. Оставим пока в покое медленный декремент, продолжим мозгоштурм.
Программа:
Код:PROGRAM PLC_PRG
VAR
TT : INT := 100;
QQ : INT;
END_VAR
QQ := TT;
IF DI1 AND TT >0 THEN
TT := TT - 1;
ELSE
TT := QQ;
END_IF
В этом случае QQ будет равно тому, до чего успела уменьшится TT.
А как сохранить эту QQ ??? :confused:
Код:VAR RETAIN
QQ: INT;
END_VAR
Какая переменная? QQ ? Я же говорю, что она меняется так же, как ТТ... от 100 до 0..
Но, решение почти есть:
Осталось вписать его в мой проект... :)Код:PROGRAM PLC_PRG
VAR
TT : INT := 100;
QQ : INT;
INIT_VAR : BOOL := 1;
END_VAR
IF INIT_VAR THEN
QQ := TT;
INIT_VAR := 0;
END_IF
IF DI1 AND TT >0 THEN
TT := TT - 1;
ELSE
TT := QQ;
END_IF
Ну так поставьте задачу лучше. Что вы понимаете под сохранением в данном случае?В вашем решении можно выкинуть INIT_VAR вместе с ифом и написать TT, QQ: INT := 100 ничего при этом не потеряв.Цитата:
Но, решение почти есть