PDA

Просмотр полной версии : Не работает код, таймер



pyonth
12.11.2013, 21:35
Пытаюсь сделать управление нагревателем, 2 режима. Первый: Нагрев, второй: Поддержание температуры на заданном уровне. Я попробовал описать функциональный блок, но он не работает. Подскажите, как будет правильно реализовать? Может, тут надо таймеры в отдельный функциональный блок как-то вынести?


FUNCTION_BLOCK Heater
VAR_INPUT
Temper_k :WORD; (*Температура с термопары*)
Time_grow :TIME; (*Время изменения мощности, скорость нагрева*)
Temper_oper: UINT; (*Температура, которую задает оператор*)
Time_work_elect_heat :TIME; (*Время поддержания температуры*)
END_VAR
VAR_OUTPUT
Out_elect_heat :WORD; (*Мощность нагревателя*)
END_VAR
VAR
Timer_grow : TON;
Operation_time: TON;
Time_step :TIME; (*Время приращения мощности ТЭНа*)
capacity_ADC :UINT := 4096; (*Разрядность АЦП*)
step_grow :UINT := 128; (*Приращение АЦП*)
heating_mode :UINT; (*Режим нагревателя, 0 - нагрев, 1 - поддержание температуры*)
END_VAR


Time_step := Time_grow / capacity_ADC; (*Это время идет на таймер, который вызывает сигнал Timer*)
Timer_grow(IN := 1, PT := Time_step);
Operation_time(IN := 1, PT := Time_work_elect_heat);
CASE heating_mode OF
0:
IF Timer_grow.Q AND (Temper_k < Temper_oper) AND Out_elect_heat < capacity_ADC THEN
Out_elect_heat := Out_elect_heat + step_grow; (*32 шага при 12-битном АЦП*)
ELSIF Timer_grow.Q AND (Temper_k > Temper_oper) AND Out_elect_heat > 0 THEN
heating_mode :=1;
END_IF
1:
IF Operation_time.Q AND (Temper_k < Temper_oper) AND Out_elect_heat < capacity_ADC THEN
Out_elect_heat := Out_elect_heat + step_grow; (*32 шага при 12-битном АЦП*)
ELSIF Operation_time.Q AND (Temper_k > Temper_oper) AND Out_elect_heat > 0 THEN
Out_elect_heat := Out_elect_heat - step_grow; (*32 шага при 12-битном АЦП*)
ELSE
Out_elect_heat := 0;
END_IF
END_CASE

capzap
12.11.2013, 22:03
чего за понты, ПИД-регулятором не хотели бы воспользоваться для своей задачи
и точно речь об овеновском плк, так то температуры у нас в REAL-ах, а в словах это у семена

pyonth
12.11.2013, 22:07
Я не понимаю, где я ошибся, конкретный ПЛК/разрядность и т.д. это второстепенные вопросы. Меня больше интересует, как решить данную проблему.

capzap
12.11.2013, 22:30
http://www.owen.ru/forum/showthread.php?t=12117&p=77438&viewfull=1#post77438

pyonth
12.11.2013, 22:32
Спасибо вам! Попробую разобраться что к чему.

capzap
12.11.2013, 22:41
да тут разбираться нечего, Ваш код не будет работать, потому что ))) надо смотреть эпюры
таймер прокрутится один раз и всё, я не нашел в коде где он перезапускается

pyonth
12.11.2013, 22:55
Да я это уже понял) Не все мы рождаемся со всеми знаниями, некоторые приобретаем)

pyonth
13.11.2013, 11:03
Я поправил код, но по какой-то причине не идет время в ET таймера operation_time, в эмуляции устанавливается IN в TRUE, PT тоже время присваивается, но отсчет не начинается. Подскажите, из-за чего так?


Time_step := Time_grow / capacity_ADC; (*&#221;&#242;&#238; &#226;&#240;&#229;&#236;&#255; &#232;&#228;&#229;&#242; &#237;&#224; &#242;&#224;&#233;&#236;&#229;&#240;, &#234;&#238;&#242;&#238;&#240;&#251;&#233; &#226;&#251;&#231;&#251;&#226;&#224;&#229;&#242; &#241;&#232;&#227;&#237;&#224;&#235; Timer*)
Timer_grow(IN := TRUE, PT := Time_step);
CASE heating_mode OF
0:
IF Timer_grow.Q AND (Temper_k < Temper_oper) AND Out_elect_heat < capacity_ADC THEN
Timer_grow(IN := FALSE);
Operation_time(IN := FALSE);
Out_elect_heat := Out_elect_heat + step_grow; (*32 &#248;&#224;&#227;&#224; &#239;&#240;&#232; 12-&#225;&#232;&#242;&#237;&#238;&#236; &#192;&#214;&#207;*)
ELSIF Timer_grow.Q AND (Temper_k >= Temper_oper) AND Out_elect_heat > 0 THEN
Timer_grow(IN := FALSE);
Operation_time(IN := TRUE, PT := Time_work_elect_heat);
heating_mode := 1;
END_IF
1:
IF Operation_time.Q AND Timer_grow.Q AND (Temper_k < Temper_oper) AND Out_elect_heat < capacity_ADC THEN
Timer_grow(IN := FALSE);
Out_elect_heat := Out_elect_heat + step_grow; (*32 &#248;&#224;&#227;&#224; &#239;&#240;&#232; 12-&#225;&#232;&#242;&#237;&#238;&#236; &#192;&#214;&#207;*)
ELSIF Operation_time.Q AND Timer_grow.Q AND (Temper_k >= Temper_oper) AND Out_elect_heat > 0 THEN
Timer_grow(IN := FALSE);
Out_elect_heat := Out_elect_heat - step_grow; (*32 &#248;&#224;&#227;&#224; &#239;&#240;&#232; 12-&#225;&#232;&#242;&#237;&#238;&#236; &#192;&#214;&#207;*)
ELSIF NOT Operation_time.Q THEN
Operation_time(IN := FALSE);
Out_elect_heat := 0;
END_IF
END_CASE

amn
13.11.2013, 11:58
Чтобы работало надо чтобы после отработки таймера перед следующим запуском вход IN сбрасывался в FALSE.

У вас таймер с задержкой включения. Выход ET изменяется после поступления сигнала на вход IN до тех пор, пока таймер не выдаст сигнал на выходе Q. Следующий раз он будет изменяться только когда очередной раз сбросите и снова включите вход IN.

pyonth
13.11.2013, 20:13
Подскажите, почему при эмуляции Timer1 досчитывает до конца и дальше эмуляция не идет? Я так подозреваю, потому что нет последующего изменения IN на TRUE, после FALSE. Хотя, может в чем-нибудь другом причина?


PROGRAM PLC_PRG
VAR
Timer1 : TON;
Timer2 :TP;
T1: BOOL := TRUE;
T2: BOOL;
END_VAR

Timer1(IN:=T1, PT:=T#5s);
Timer2(IN:=T2, PT:=T#10s);
IF Timer1.Q THEN
T1 := FALSE;
T2 := TRUE;
END_IF
IF NOT Timer2.Q THEN
T1 := TRUE;
T2 := FALSE;
END_IF

capzap
13.11.2013, 20:44
ну вот поставте следующим образом и сравните результат

IF Timer1.Q THEN
(*что то там, в теле условия, только не переменные таймера*)
END_IF;
Timer1(IN:=NOT Timer1.Q, PT:=T#5s);

amn
13.11.2013, 21:43
Подскажите, почему при эмуляции Timer1 досчитывает до конца и дальше эмуляция не идет? Я так подозреваю, потому что нет последующего изменения IN на TRUE, после FALSE. Хотя, может в чем-нибудь другом причина?


PROGRAM PLC_PRG
VAR
Timer1 : TON;
Timer2 :TP;
T1: BOOL := TRUE;
T2: BOOL;
END_VAR

Timer1(IN:=T1, PT:=T#5s);
Timer2(IN:=T2, PT:=T#10s);
IF Timer1.Q THEN
T1 := FALSE;
T2 := TRUE;
END_IF
IF NOT Timer2.Q THEN
T1 := TRUE;
T2 := FALSE;
END_IF

Из-за того, что в вашем коде второе условие выполняется всегда, те переменные, которые вы изменили в первом условии тут же меняются во втором условии до вызова таймеров, в которых они используются.

pyonth
13.11.2013, 22:43
Заработало как надо! Только скажите, не криво ли это выглядит и стоит ли так делать? Я замечаю, что пока не получается мыслить о процессе кодирования как кодирование конечного автомата. Я правильно понимаю, что за один цикл работы ПЛК входные/выходные переменные меняют значение один раз, а локальные переменные в коде могут меняться несколько раз?


Timer1(IN:=T1, PT:=T#5s);
Timer2(IN:=T2, PT:=T#10s);
IF Timer1.Q THEN
T1 := FALSE;
T2 := TRUE;
END_IF
IF NOT Timer2.Q AND NOT inv THEN
T1 := TRUE;
T2 := FALSE;
END_IF
inv := NOT inv;

amn
14.11.2013, 01:21
Заработало как надо! Только скажите, не криво ли это выглядит и стоит ли так делать? Я замечаю, что пока не получается мыслить о процессе кодирования как кодирование конечного автомата.


Timer1(IN:=T1, PT:=T#5s);
Timer2(IN:=T2, PT:=T#10s);
IF Timer1.Q THEN
T1 := FALSE;
T2 := TRUE;
END_IF
IF NOT Timer2.Q AND NOT inv THEN
T1 := TRUE;
T2 := FALSE;
END_IF
inv := NOT inv;

Главное понимать, как это работает.
Я бы сделал так:

TP1(IN:=TRUE , PT:=T#10s);
TON1;
F_TRIG1(CLK:=TP1.Q);
IF F_TRIG1.Q THEN
TON1(IN:=TRUE , PT:=T#5s);
END_IF
IF TON1.Q THEN
TP1(IN:=FALSE);
TON1(IN:=FALSE);
END_IF
или так:

TOF1(IN:=FALSE);
F_TRIG1(CLK:=TP1.Q);
IF NOT TOF1.Q THEN
TP1(IN:=TRUE , PT:=T#10s);
END_IF
IF F_TRIG1.Q THEN
TP1(IN:=FALSE);
TOF1(IN:=TRUE , PT:=T#5s);
END_IF



Я правильно понимаю, что за один цикл работы ПЛК входные/выходные переменные меняют значение один раз, а локальные переменные в коде могут меняться несколько раз?
Правильно.

capzap
14.11.2013, 08:03
Заработало как надо! Только скажите, не криво ли это выглядит и стоит ли так делать? Я замечаю, что пока не получается мыслить о процессе кодирования как кодирование конечного автомата. Я правильно понимаю, что за один цикл работы ПЛК входные/выходные переменные меняют значение один раз, а локальные переменные в коде могут меняться несколько раз?


Timer1(IN:=T1, PT:=T#5s);
Timer2(IN:=T2, PT:=T#10s);
IF Timer1.Q THEN
T1 := FALSE;
T2 := TRUE;
END_IF
IF NOT Timer2.Q AND NOT inv THEN
T1 := TRUE;
T2 := FALSE;
END_IF
inv := NOT inv;

прочтите назначение ПОУ BLINK, возможно он заменит Ваш код

pyonth
14.11.2013, 18:34
А могли бы вы мне дать посильное, небольшое и интересное задание, чтобы попрактиковаться в программировании на ST? Был бы очень признателен.

capzap
14.11.2013, 18:56
А могли бы вы мне дать посильное, небольшое и интересное задание, чтобы попрактиковаться в программировании на ST? Был бы очень признателен.

светофор собирите

pyonth
14.11.2013, 19:49
светофор собирите

В принципе можно ведь написать на ST, а потом переменные к визуализации привязать?