Просмотр полной версии : Не работает код, таймер
Пытаюсь сделать управление нагревателем, 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
чего за понты, ПИД-регулятором не хотели бы воспользоваться для своей задачи
и точно речь об овеновском плк, так то температуры у нас в REAL-ах, а в словах это у семена
Я не понимаю, где я ошибся, конкретный ПЛК/разрядность и т.д. это второстепенные вопросы. Меня больше интересует, как решить данную проблему.
http://www.owen.ru/forum/showthread.php?t=12117&p=77438&viewfull=1#post77438
Спасибо вам! Попробую разобраться что к чему.
да тут разбираться нечего, Ваш код не будет работать, потому что ))) надо смотреть эпюры
таймер прокрутится один раз и всё, я не нашел в коде где он перезапускается
Да я это уже понял) Не все мы рождаемся со всеми знаниями, некоторые приобретаем)
Я поправил код, но по какой-то причине не идет время в ET таймера operation_time, в эмуляции устанавливается IN в TRUE, PT тоже время присваивается, но отсчет не начинается. Подскажите, из-за чего так?
Time_step := Time_grow / capacity_ADC; (*Ýòî âðåìÿ èäåò íà òàéìåð, êîòîðûé âûçûâàåò ñèãíàë 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 øàãà ïðè 12-áèòíîì ÀÖÏ*)
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 øàãà ïðè 12-áèòíîì ÀÖÏ*)
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 øàãà ïðè 12-áèòíîì ÀÖÏ*)
ELSIF NOT Operation_time.Q THEN
Operation_time(IN := FALSE);
Out_elect_heat := 0;
END_IF
END_CASE
Чтобы работало надо чтобы после отработки таймера перед следующим запуском вход IN сбрасывался в FALSE.
У вас таймер с задержкой включения. Выход ET изменяется после поступления сигнала на вход IN до тех пор, пока таймер не выдаст сигнал на выходе Q. Следующий раз он будет изменяться только когда очередной раз сбросите и снова включите вход IN.
Подскажите, почему при эмуляции 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
ну вот поставте следующим образом и сравните результат
IF Timer1.Q THEN
(*что то там, в теле условия, только не переменные таймера*)
END_IF;
Timer1(IN:=NOT Timer1.Q, PT:=T#5s);
Подскажите, почему при эмуляции 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
Из-за того, что в вашем коде второе условие выполняется всегда, те переменные, которые вы изменили в первом условии тут же меняются во втором условии до вызова таймеров, в которых они используются.
Заработало как надо! Только скажите, не криво ли это выглядит и стоит ли так делать? Я замечаю, что пока не получается мыслить о процессе кодирования как кодирование конечного автомата. Я правильно понимаю, что за один цикл работы ПЛК входные/выходные переменные меняют значение один раз, а локальные переменные в коде могут меняться несколько раз?
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;
Заработало как надо! Только скажите, не криво ли это выглядит и стоит ли так делать? Я замечаю, что пока не получается мыслить о процессе кодирования как кодирование конечного автомата.
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
Я правильно понимаю, что за один цикл работы ПЛК входные/выходные переменные меняют значение один раз, а локальные переменные в коде могут меняться несколько раз?
Правильно.
Заработало как надо! Только скажите, не криво ли это выглядит и стоит ли так делать? Я замечаю, что пока не получается мыслить о процессе кодирования как кодирование конечного автомата. Я правильно понимаю, что за один цикл работы ПЛК входные/выходные переменные меняют значение один раз, а локальные переменные в коде могут меняться несколько раз?
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, возможно он заменит Ваш код
А могли бы вы мне дать посильное, небольшое и интересное задание, чтобы попрактиковаться в программировании на ST? Был бы очень признателен.
А могли бы вы мне дать посильное, небольшое и интересное задание, чтобы попрактиковаться в программировании на ST? Был бы очень признателен.
светофор собирите
светофор собирите
В принципе можно ведь написать на ST, а потом переменные к визуализации привязать?
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot