Поправил скрипт, поправил неточности в библиотеке

This commit is contained in:
2026-07-31 11:20:45 +03:00
parent d3da512178
commit 3d52fdec57
44 changed files with 1956 additions and 51 deletions
+125
View File
@@ -0,0 +1,125 @@
(*
===============================================================================
Project : PLC_Library
Device : -
Path : Общие
Name : PIDcontrol
Type : FUNCTION_BLOCK
Exported : 2026-07-31 11:16:16
===============================================================================
*)
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