Большое спасибо за пример с таймингами... Только я не понял, зачем
- вроде нигде не фигурирует в текстах...Код:isnan: ARRAY [0..3] OF BYTE:=0,0,128,127;
В данный момент прикрутил следующие костыли:
Как поведет себя эта конструкция, если контроллер будет нагружен - вопрос. Сейчас, на одной лампе - работает достаточно плавно...Код:(* Плавное включение полного света *) IF Full THEN IF Count_R < 100 THEN RRR := RRR + 0.2; Count_R := REAL_TO_INT(RRR); ELSE Full := FALSE; RRR := 0; END_IF END_IF
Что касается неработающего примера - то там энкодер не использую - просто кнопки. И энкодер прикручен к обычным входах, не быстрым...
Да, насколько я понял, в тайминге скорость нарастания\ падения регулируется tik(IN:=NOT tik.Q, PT:=T#50ms); Так?
Вместо всего этого...Надо писать так:Код:IF i <= Limit_Reg THEN i := LIMIT(0, i + REAL_TO_INT(TIME_TO_REAL(TIME() - PrevScanTimestamp) * Speed_Reg * (BOOL_TO_REAL(btn_up) - BOOL_TO_REAL(btn_dn))), Limit_Reg); AO7 := ARR[i]; ELSIF (i=0 AND btn_dn) THEN AO7 := ARR[0]; ELSE AO7 := ARR[i]; END_IF PrevScanTimestamp := TIME();Остальной код ничего не делает. Если вы не нажимаете ни одну кнопку, второе слагаемое будет нулём и i будет постоянным. Когда вы упрётесь в Limit_reg или в нуль, i всё равно не выпрыгнет за пределы, т.к. там функция LIMIT. Попробуйте исправленный вариант и сообщите результаты.Код:i := LIMIT(0, i + REAL_TO_INT(TIME_TO_REAL(TIME() - PrevScanTimestamp) * Speed_Reg * (BOOL_TO_REAL(btn_up) - BOOL_TO_REAL(btn_dn))), Limit_Reg); AO7 := ARR[i]; PrevScanTimestamp := TIME();
Раз уж пошла такая пьянка, подскажите, есть ли более простой способ узнать длительность нажатия кнопки, кроме как ловить передний и задний фронты?
Сейчас у меня это так:
Как-то не изящно смотрится..Код:VAR Btn : BOOL; Fr: R_TRIG; Bk: F_TRIG; In: TIME; Out:TIME; Long : TIME; END_VAR Btn := DI1; Fr(CLK:=Btn); (* Передний фронт *) Bk(CLK:=Btn); (* Задний фронт *) IF Fr.Q THEN In := TIME(); END_IF IF Bk.Q THEN Out := TIME(); END_IF Long := Out - In;![]()
Угумс:Ну или вариант для тех, кого в детстве пугали таймерами:Код:VAR stopwatch: TON; result: TIME; btn: BOOL; END_VAR IF NOT btn AND stopwatch.IN THEN result := stopwatch.ET; END_IF stopwatch(IN := btn, PT := DWORD_TO_TIME(NOT 0));Код:VAR timestamp, result: TIME; btn: BOOL; END_VAR IF btn AND timestamp = T#0s THEN timestamp := TIME(); ELSIF NOT btn AND timestamp <> T#0s THEN result := TIME() - timestamp; timestamp := T#0s; END_IF
Последний раз редактировалось Yegor; 01.10.2012 в 20:17.
Очередной дурацкий вопрос - как "мигнуть" светом? Мигнуть - это не выключить-включить, а притушить на 30% и вернуть обратно... Или при малой яркости прибавить 30% и вернуть.. Проблема - в скорости цикла. Т.е. если в одном цикле я уменьшаю яркость, а в следующем увеличиваю - лампа не успевает отработать. Пропускать некоторое количество циклов счетчиком - не самый удачный вариант, но другие пока не лезут в голову... А как два раза мигнуть?
Я себе для «морзянки» лампочками и зумерами вот чо написал:Код:FUNCTION_BLOCK BLINK_SEQ (* Custom sequence blinker *) VAR_INPUT SEQ: ARRAY [0..15] OF TIME; (* The sequence to blink upon (even are ON times, odd are OFF times) *) ENABLED: BOOL; (* Rising edge starts blinking *) END_VAR VAR_OUTPUT OUT: BOOL; END_VAR VAR i: INT; starter: R_TRIG; sequencer: TON; END_VAR starter(CLK := ENABLED); IF starter.Q THEN i := 0; END_IF IF ENABLED AND i < 15 THEN sequencer(IN := TRUE, PT := SEQ[i]); IF sequencer.Q THEN i := i + 1; WHILE SEQ[i] = T#0s AND i < 15 DO i := i + 1; END_WHILE sequencer(IN := FALSE); END_IF OUT := (i MOD 2 = 0) AND ENABLED AND SEQ[MAX(0, i - 1)] > T#0s; ELSE OUT := FALSE; END_IF