PDA

Просмотр полной версии : Не работает функциональный блок PID из стандартной библиотеки Util.lib - Контроллеры



Дмитрий_Кирсанов
06.04.2017, 22:30
Использую среду программирования Codesys v.2.3 для программирования ПЛК ОВЕН 110.60(М02).
Использую функциональный блок ПИД-регулирования из стандартной библиотеки Util.lib.
Во время работы программы переменная ПИД-регулятора ctu_PID.Y всегда равна 0, хотя согласно пред-настройкам входных переменных должна принимать другое значение. Кто-нибудь может проверить код выложенный ниже и объяснить мне как правильно подключать функциональные блоки из библиотек Codesys?



PROGRAM PLC_PRG
VAR CONSTANT
Curr_SetPoint: REAL := 12.5;
Low_Pressure_Set: REAL := 10.0;
High_Pressure_Set: REAL := 15.0;
END_VAR

VAR
ctu_PID: PID;
Curr_Dif_Pressure: REAL;
Tmp: REAL;
Is_Door_Open: BOOL;
END_VAR

Moving1 := Moving2 := 1;
Moving3 := Moving4 := Moving5 := 2;
Is_Door_Open := FALSE;
Curr_Dif_Pressure := 8.6;
ctu_PID.ACTUAL := Curr_Dif_Pressure;
ctu_PID.SET_POINT := Curr_SetPoint;
ctu_PID.Y_MIN := 0.0;
ctu_PID.Y_MAX := 1000;
Tmp := ctu_PID.Y;
IF(ctu_PID.OVERFLOW )
THEN
ctu_PID.RESET := TRUE;
END_IF;
IF NOT( Is_Door_Open)
THEN
IF(Curr_Dif_Pressure < Low_Pressure_Set)
THEN
Frequency1 := REAL_TO_WORD(Tmp);
Frequency2 := REAL_TO_WORD(Tmp);
Frequency3 := 0;
Frequency4 := 0;
Frequency5 := 0;
ELSIF(Curr_Dif_Pressure > High_Pressure_Set)
THEN
Frequency1 := 0;
Frequency2 := 0;
Frequency3 := REAL_TO_WORD(Tmp);
Frequency4 := REAL_TO_WORD(Tmp);
Frequency5 := REAL_TO_WORD(Tmp);
ELSE
Frequency1 := 300;
Frequency2 := 0;
Frequency3 := 300;
Frequency4 := 300;
Frequency5 := 0;
END_IF;
ELSE
Frequency1 := 300;
Frequency2 := 0;
Frequency3 := 300;
Frequency4 := 300;
Frequency5 := 0;
END_IF;


В ручном режиме ПИД-регулятор также не работает(скриншот ниже)

ASo
06.04.2017, 22:34
Вы нигде не вызываете ФБ ПИД. Вы не даете ему работать.

krollcbas
06.04.2017, 23:44
1. Крайне желательно обрабатывать PID в отдельной программе с отдельной от всего остального кода выделенной задачей с высшим приоритетом (100мс например)
2. ASo верно сказал. Вы нигде не вызываете экземпляр. Математика блока может работать только если блок циклически вызывается. Пример вызова ниже.


IF MODE_GVS=1 THEN SP_TE3:=TE3_M; GVS_MAN:=TRUE; ELSE GVS_MAN:=FALSE; END_IF;(*&#208;&#243;&#247;&#237;&#238;&#233;*)
IF MODE_GVS=2 THEN Y1_MANUAL:=Y1_M; END_IF;(*&#192;&#226;&#242;&#238;*)
IF Y1_MANUAL<0 THEN Y1_MANUAL:=0; END_IF;IF Y1_MANUAL>100 THEN Y1_MANUAL:=100; END_IF;
PID_Y1(
ACTUAL:= TE3_M, (* actual value, process variable *)
SET_POINT:= SP_TE3,(* desired value, set point *)
KP:= Y1_P,(* proportionality const. (P)*)
TN:= Y1_I, (* reset time (I) in sec *)
TV:= Y1_D, (* rate time, derivative time (D) in sec*)
Y_MANUAL:=Y1_MANUAL , (* Y is set to this value as long as MANUAL=TRUE *)
Y_OFFSET:= 0.1, (* offset for manipulated variable *)
Y_MIN:= 0.0, (* minimum value for manipulated variable *)
Y_MAX:= 100.0, (* maximum value for manipulated variable *)
MANUAL:= GVS_MAN, (* TRUE: manual: Y is not influenced by controller,FALSE: controller determines Y *)
RESET:= GVS_RESET, (* reset: set Y output to Y_OFFSET and reset integral part *)
Y=> Y1_M, (* manipulated variable, set value*)
LIMITS_ACTIVE=> Y1_LA,(* true set value would exceed limits Y_MIN, Y_MAX *)
OVERFLOW=> Y1_OW);(* overflow in integral part *)

Dimensy
07.04.2017, 09:08
а разве так можно?
Moving1 := Moving2 := 1;

Дмитрий_Кирсанов
07.04.2017, 09:32
а разве так можно?
Moving1 := Moving2 := 1;

пока ещё не знаю, но код компилируется

Дмитрий_Кирсанов
07.04.2017, 09:39
1. Крайне желательно обрабатывать PID в отдельной программе с отдельной от всего остального кода выделенной задачей с высшим приоритетом (100мс например)
2. ASo верно сказал. Вы нигде не вызываете экземпляр. Математика блока может работать только если блок циклически вызывается. Пример вызова ниже.


IF MODE_GVS=1 THEN SP_TE3:=TE3_M; GVS_MAN:=TRUE; ELSE GVS_MAN:=FALSE; END_IF;(*&#208;&#243;&#247;&#237;&#238;&#233;*)
IF MODE_GVS=2 THEN Y1_MANUAL:=Y1_M; END_IF;(*&#192;&#226;&#242;&#238;*)
IF Y1_MANUAL<0 THEN Y1_MANUAL:=0; END_IF;IF Y1_MANUAL>100 THEN Y1_MANUAL:=100; END_IF;
PID_Y1(
ACTUAL:= TE3_M, (* actual value, process variable *)
SET_POINT:= SP_TE3,(* desired value, set point *)
KP:= Y1_P,(* proportionality const. (P)*)
TN:= Y1_I, (* reset time (I) in sec *)
TV:= Y1_D, (* rate time, derivative time (D) in sec*)
Y_MANUAL:=Y1_MANUAL , (* Y is set to this value as long as MANUAL=TRUE *)
Y_OFFSET:= 0.1, (* offset for manipulated variable *)
Y_MIN:= 0.0, (* minimum value for manipulated variable *)
Y_MAX:= 100.0, (* maximum value for manipulated variable *)
MANUAL:= GVS_MAN, (* TRUE: manual: Y is not influenced by controller,FALSE: controller determines Y *)
RESET:= GVS_RESET, (* reset: set Y output to Y_OFFSET and reset integral part *)
Y=> Y1_M, (* manipulated variable, set value*)
LIMITS_ACTIVE=> Y1_LA,(* true set value would exceed limits Y_MIN, Y_MAX *)
OVERFLOW=> Y1_OW);(* overflow in integral part *)



По первому пункту, могли бы вы объяснить подробнее как это делается или дать ссылочку на путный гайд?
По второму пункту тоже пока ничего не получается. Могли бы вы подробнее указать на мои ошибки? Ниже привожу код и скриншот экрана при выполнении программы. Не пойму, что я делаю не так?



PROGRAM PLC_PRG
VAR CONSTANT
Curr_SetPoint: REAL := 12.5;
Low_Pressure_Set: REAL := 10.0;
High_Pressure_Set: REAL := 15.0;
END_VAR

VAR
ctu_PID: PID;
Curr_Dif_Pressure: REAL;
Tmp: REAL;
Is_Door_Open: BOOL;
END_VAR


ctu_PID(ACTUAL := 10.0, SET_POINT := 12.0, Y_MIN := 4, Y_MAX := 20, Y => Tmp);
ctu_PID;



30432

Василий Кашуба
07.04.2017, 12:43
По первому пункту, могли бы вы объяснить подробнее как это делается или дать ссылочку на путный гайд?
По второму пункту тоже пока ничего не получается. Могли бы вы подробнее указать на мои ошибки? Ниже привожу код и скриншот экрана при выполнении программы. Не пойму, что я делаю не так?



PROGRAM PLC_PRG
VAR CONSTANT
Curr_SetPoint: REAL := 12.5;
Low_Pressure_Set: REAL := 10.0;
High_Pressure_Set: REAL := 15.0;
END_VAR

VAR
ctu_PID: PID;
Curr_Dif_Pressure: REAL;
Tmp: REAL;
Is_Door_Open: BOOL;
END_VAR


ctu_PID(ACTUAL := 10.0, SET_POINT := 12.0, Y_MIN := 4, Y_MAX := 20, Y => Tmp);
ctu_PID;



30432
Вот так делается. 30434 , а вот так вызывается 30435

Dimensy
07.04.2017, 13:23
вызвать Фб можно по разному:
сначала установить параметры
ctu_PID.ACTUAL:=10.0;
ctu_PID.SET_POINT:=12.0;
...
а потом, где-нибудь вызываем
ctu_PID();

или сразу вызываем с параметрами
ctu_PID(ACTUAL := 10.0, SET_POINT := 12.0, Y_MIN := 4, Y_MAX := 20);

выходы так же можно читать по разному
при вызове ctu_PID(Y=>Tmp);
или после вызова Tmp:=ctu_PID.Y;

Dimensy
07.04.2017, 13:27
и еще, небольшой совет - используйте CFC, а на СТ какие-нибудь дополнительные или громоздкие вычисления

Дмитрий_Кирсанов
07.04.2017, 14:57
Вот так делается. 30434 , а вот так вызывается 30435

Василий Кашуба, могли бы вы выложить код от PID_REGUL(PRG)? Мне все еще не понятно как должно выглядеть его описание в PRG на ST (первое, это просто указание входов и выходов; второе, нужно писать программу ПИД-регулирования целиком)? Если второе, то для чего тогда подключать библиотеку Util.lib? Почему компилятор ругается: "ошибка 3700: POU с именем PID уже включен в библиотеку 'Util.lib'", когда в менеджер библиотек добавлена данная библиотека и я добавляю программу PID в POU? Как можно избежать необходимости описывать PID и ограничиться лишь только библиотечным описанием этого ФБ? Можете дать ссылку на доступный guide?

Василий Кашуба
07.04.2017, 15:33
Программка написана ещё в 2010 году, так что, библиотеки могут не совпадать. И ещё я пишу на CFC.