Files
PLC_Library/plc_src/POU/Общие/PIDcontrol.st
T

125 lines
4.2 KiB
Smalltalk
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(*
===============================================================================
Project : PLC_Library
Device : -
Path : Общие
Name : PIDcontrol
Type : FUNCTION_BLOCK
===============================================================================
*)
FUNCTION_BLOCK PIDcontrol (* ПИД-регулятор. *)
VAR_INPUT
ProcessVariable: REAL := 0.0; (* Измеренное значение параметра *)
Setpoint: REAL := 0.0; (* Заданное значение *)
Kp: REAL := 0.001; (* Пропорциональный коэффициент *)
Ki: REAL := 0.001; (* Интегральный коэффициент *)
Kd: REAL := 0.0; (* Дифференциальный коэффициент *)
Kdf: REAL := 1.0; (* Коэффициент фильтрации (1/Tdf) *)
DBmax: REAL := 0.01; (* Верхняя граница зоны нечувствительности *)
DBmin: REAL := - 0.01; (* Нижняя граница зоны нечувствительности *)
OutMax: REAL := 100.0; (* Максимальный выход *)
OutMin: REAL := 0.0; (* Минимальный выход *)
Ts: REAL := 0.1; (* Время дискретизации [с] *)
Manual: REAL := 25.0; (* Значение в ручном режиме *)
ManOn: BOOL := FALSE; (* Флаг ручного режима *)
Reset: BOOL := FALSE; (* Сброс интегратора *)
AntiWindup: BOOL := TRUE; (* Включить антивиндап *)
END_VAR
VAR_OUTPUT
Out: REAL := 0.0; (* Выходной сигнал *)
Err: REAL := 0.0; (* Ошибка регулирования *)
OutLimited: BOOL := FALSE; (* Флаг ограничения выхода *)
END_VAR
VAR (* Внутренние переменные, сохраняемые. *)
Er: REAL := 0.0; (* Текущая ошибка *)
Ppart: REAL := 0.0; (* Пропорциональная часть *)
Ipart: REAL := 0.0; (* Интегральная часть *)
Dpart: REAL := 0.0; (* Дифференциальная часть *)
PrevEr: REAL := 0.0; (* Ошибка на предыдущем шаге (для дифференциатора). *)
FirstScan: BOOL := TRUE; (* Флаг первого сканирования. *)
END_VAR
VAR_TEMP
Auto: REAL; (* Выход ПИД *)
Sw: REAL; (* Промежуточное значение *)
END_VAR
(*----- IMPLEMENTATION -----*)
(* === ИНИЦИАЛИЗАЦИЯ И СБРОС === *)
IF Reset OR FirstScan THEN
Ipart := 0.0;
Dpart := 0.0;
PrevEr := 0.0;
FirstScan := FALSE;
END_IF;
(* === ПРОВЕРКА ВХОДНЫХ ПАРАМЕТРОВ === *)
IF (OutMin >= OutMax) OR (DBmin >= DBmax) OR (Ts <= 0) THEN
Out := 0.0;
OutLimited := TRUE;
RETURN;
END_IF;
(* === РАСЧЕТ ОШИБКИ === *)
Er := Setpoint - ProcessVariable;
Err := Er;
(* ЗОНА НЕЧУВСТВИТЕЛЬНОСТИ *)
IF (DBmin < Er) AND (Er < DBmax) THEN
Er := 0.0;
END_IF;
(* === ПРОПОРЦИОНАЛЬНАЯ ЧАСТЬ === *)
Ppart := Kp * Er;
(* === ИНТЕГРАЛЬНАЯ ЧАСТЬ === *)
IF Ki <> 0.0 THEN
Ipart := Ipart + (Ki * Er * Ts);
Ipart := LIMIT(OutMin, Ipart, OutMax);
ELSE
Ipart := 0.0;
END_IF;
(* === ДИФФЕРЕНЦИАЛЬНАЯ ЧАСТЬ (фильтрованная) === *)
IF Kd <> 0.0 THEN
Dpart := Kd * Kdf * (Er - PrevEr) - Kdf * Dpart * Ts;
PrevEr := Er; (* Сохраняем ошибку для следующего шага *)
ELSE
Dpart := 0.0;
END_IF;
(* === ВЫЧИСЛЕНИЕ ВЫХОДА === *)
Auto := Ppart + Ipart + Dpart;
(* === РЕЖИМ РУЧНОЙ/АВТОМАТИЧЕСКИЙ === *)
IF ManOn THEN
Sw := Manual;
(* Сброс интегратора при переходе в ручной режим *)
IF AntiWindup THEN
Ipart := Sw - (Ppart + Dpart);
END_IF;
ELSE
Sw := Auto;
END_IF;
(* === ОГРАНИЧЕНИЕ ВЫХОДА И АНТИВИНДАП === *)
IF Sw >= OutMax THEN
Out := OutMax;
OutLimited := TRUE;
IF AntiWindup AND NOT ManOn THEN
Ipart := OutMax - (Ppart + Dpart);
END_IF;
ELSIF Sw <= OutMin THEN
Out := OutMin;
OutLimited := TRUE;
IF AntiWindup AND NOT ManOn THEN
Ipart := OutMin - (Ppart + Dpart);
END_IF;
ELSE
Out := Sw;
OutLimited := FALSE;
END_IF;
END_FUNCTION_BLOCK