(* =============================================================================== 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