Всем привет!
Есть задача управлять 3х ходовым клапаном 0-10 В по ПИД закону с ПЛК160 [М02] в режиме охлаждения.
Подскажите, пожалуйста, какой ФБ и с какой библиотеки лучше использовать ?
Всем привет!
Есть задача управлять 3х ходовым клапаном 0-10 В по ПИД закону с ПЛК160 [М02] в режиме охлаждения.
Подскажите, пожалуйста, какой ФБ и с какой библиотеки лучше использовать ?
https://content.helpme-codesys.com/e...oller/PID.html
Util -> PID
В составе CoDeSys есть справки на английском и русском.
Также, можно вместо проекта открыть библиотеку и посмотреть устройство на ST.
Есть ограничения - для работы нужно ненулевые K и Tи, иначе код не выполняется - такое входное условие на ST.
FUNCTION_BLOCK PID1
VAR_INPUT
input:INT; (* входная величина*)
setPoint: INT; (* уставка *)
minOut: WORD; (* минимальное значение выходного сигнала*)
maxOut: WORD; (* максимальное*)
Kp: WORD; (* пропорциональный коэффициент*)
Ki:WORD; (* интегральный коэффициент*)
Kd: WORD; (* дифференциальный коэффициент*)
dts: REAL; (* время дискретизации*)
direction:BOOL; (* направление 0: нормальное - увеличение выходного сигнала, приводит к увеличению входного*)
(* 1: обратное - увеличение выходного сигнала приводит к уменьшению входного *)
reset:BOOL; (* сброс значений выхода, интегральной суммы, дифференциальной суммы*)
END_VAR
VAR_OUTPUT
output:REAL; (* выходное значение*)
outInt:WORD;
out:WORD;
END_VAR
VAR
init: BOOL:=TRUE;
error : INT; (* ошибка регулирования*)
prevInput: INT; (* предыдушее значение*)
prevErr: INT;
pid_integral: REAL;
pid_diferens:REAL;
minOutReal:REAL;
maxOutReal:REAL;
pidKp: REAL; (* пропорциональный коэффициент*)
pidKi:REAL; (* интегральный коэффициент*)
pidKd: REAL; (* дифференциальный коэффициент*)
END_VAR
pidKp:=WORD_TO_REAL(Kp)/1000;
pidKi:=WORD_TO_REAL(Ki)/1000;
pidKd:=WORD_TO_REAL(Kd)/1000;
IF init = TRUE OR reset=TRUE THEN
init:=FALSE;
pid_integral:=0; (* начальные значения*)
prevErr:=0; (* ошибка для последующих вычислений*)
END_IF
error:=setPoint - input; (* вычисляем текущую ошибку*)
IF direction =1 THEN error:=0-error; END_IF (* если обратная характеристика*)
IF pidKi=0 THEN (* если интеграл коэф равен нулю*)
pid_Integral:=0; (* обнуляем интегральную составляющую*)
ELSE
pid_Integral:=pid_integral + error * dts *pidKi; (* вычисляем интегральную составляющую*)
IF pid_integral < minOut THEN (* ограничиваем интегральную составляющую снизу *)
minOutReal:=WORD_TO_REAL(minOut); (* преобразуем *)
pid_integral:=minOutReal; (* и ограничиваем*)
END_IF
IF pid_integral > maxOut THEN (* ограниваем интегральную сверху*)
maxOutReal:=WORD_TO_REAL(maxout); (* преобразуем*)
pid_integral:=maxOutReal; (* и ограниваем*)
END_IF
END_IF
pid_diferens:=(error-prevErr)/dts; (* диференциальная составляющая*)
prevErr:=error; (* сохраняем текущую ошибку, для будуших вызовов*)
output:= error*pidKp +pid_integral+ pid_diferens*pidKd; (* вычисляем значение выхода*)
IF output < minOut THEN minOutReal:=WORD_TO_REAL(minOut); output:=minOutReal; END_IF (* ограничиваем выход снизу *)
IF output > maxOut THEN maxOutReal:=WORD_TO_REAL(maxout); output:=maxOutReal; END_IF (* ограничиваем выход сверху*)
outint:=REAL_TO_WORD(output); (* преобразуем*)
out:=outint; (* и выдаем на выход*)
(* максимальную температуру на выходе приточной системы ----------------------------------------------------------------------------------*)
IF p1_pid5_tdiscr>p1_pid5_tdiscr_set THEN (* если наступило время расчет пид*)
p1_pid5_tdiscr:=0; (* обнуляем текушее время, выполняем расчет*)
p1_pid5_zima_max (input:=p1_Tvihod, (* температура канала*)
setPoint:=Tvihod_max_calc, (* максимальная температура канала*)
kp:=pid_zima_max_Kp, ki:=pid_zima_max_Ki, kd:=pid_zima_max_Kd, dts:=p1_pid5_tdiscr_set,
direction:=0, minOut:=0, maxOut:=Umax);
P1_zima_umax_calc:=p1_pid5_zima_max.out; (* выгружаем на выход*)
END_IF
Работа в эмуляции на скрине 1 Работа ПИД из Util.jpg
Работа PID из Util
Спасибо!!!