ПИД-регулятор
August 3, 2021

Регулирование задвижкой без датчика положения

Стандартные ПИД-регуляторы в средах разработки программ для контроллеров предназначены для управления исполнительными механизмами с аналоговым входом, такими как преобразователь частоты или задвижка с заданием степени открытия. Для подобного исполнительного механизма достаточно просто соединить его вход с выходом регулятора. Рассмотрим более простую версию ПИД-регулятора – ПИ-регулятор, дискретная формула которого имеет следующий вид:

Что же делать если у нашей задвижки нет датчика положения или он недостаточно надежен для регулирования и используется только для индикации? В этом случае следует управлять задвижкой в инкрементном режиме – сигналы «больше» и «меньше». Для этого воспользуемся формулой инкрементного ПИ-регулятора, которая получается путем дифференцирования предыдущей формулы:

Фактически это ПД-регулятор, сигнал с которого будет проинтегрирован самой инкрементной задвижкой и на выходе мы получим пропорционально-интегральный закон регулирования.

Выход регулятора для удобства выразим в процентах от −100% до +100%. Он является входным значением для широтно-импульсной модуляции (ШИМ). Для ШИМ необходимо задать период. Он должен быть значительно больше цикла программы. Выход регулятора устанавливает долю времени от периода ШИМ, в течение которого задвижка открывается или закрывается. Положительные значения соответствуют открытию задвижки, а отрицательные – закрытию.

PWM.png

Далее фрагмент реальной программы регулятора температуры пара на языке CoDeSys в среде программирования Schneider SoMachine.

Глобальные переменные

VAR_GLOBAL
END_VAR
VAR_GLOBAL
	// Длительность цикла - секунды
	Cycle: REAL := 0.05;
	// Температура перегретой воды - градусы
	T: REAL;
	// Отказ датчика температуры
	T_err: BOOL;
	// Значение выхода регулятора
	Y: REAL;
	// Автоматический режим регулятора активен
	Reg_auto: BOOL;
	// Применить новые значения параметров
	Set_parameters: BOOL;
	// Активна новая сигнализация
	New_Alarm: BOOL;
	// Флаг первого цикла программы
	First_Cycle: BOOL := true;
END_VAR

Программа регулятора - описательная часть

PROGRAM Regulator
VAR
	// Рассогласование
	E: REAL;
	// Рассогласование - старое значение
	E_old: REAL;
	// Температура - старое значение
	T_old: REAL;
	// Изменение рассогласования
	dE: REAL;
	// Изменение рассогласования - старое значение
	dE_old: REAL;
	// Точное время между соседними измерениями
	dt_izm: REAL;
END_VAR
VAR RETAIN
	// Задание периода между соседними измерениями, секунды
	Period_reg: REAL := 5.0;
END_VAR
VAR
	// Новое задание периода между соседними измерениями, секунды
	Period_reg_new: REAL;
	// Количество циклов, соответствующее времени между соседними измерениями
	Period_reg_cycles: INT;
	// Счетчик циклов
	i: INT;
END_VAR
VAR RETAIN
	// Коэффициент усиления регулятора
	Kp: REAL := 100.0;
	// Постоянная времени регулятора, секунды
	Tn: REAL := 300.0;
END_VAR
VAR
	// Температура перегретой воды - задание, градусы
	T_set: REAL := 140.0;
	// Коэффициент усиления регулятора - новое значение	
	Kp_new: REAL;
	// Температура перегретой воды - задание, градусы - новое значение
	Tn_new: REAL;
END_VAR
VAR RETAIN
	// Зона нечувствительности, градусы
	Zona: REAL := 0.3;
END_VAR
VAR
	// Зона нечувствительности, градусы - новое значение
	Zona_new: REAL;
END_VAR

Программа регулятора - исполнительная часть

// Установка новых коэффициентов регулятора
IF GVL.Set_parameters THEN
	Kp := Kp_new;
	Tn := Tn_new;
	Period_reg := Period_reg_new;
	Zona := Zona_new;
END_IF
// Если регулятор находится в автоматическом режиме
IF GVL.Reg_auto THEN
	// Расчет количества циклов между соседними измерениями
	Period_reg_cycles := REAL_TO_INT(Period_reg / GVL.Cycle);
	// Точное время между соседними измерениями (после округления по количеству циклов) 
	dt_izm := GVL.Cycle * Period_reg_cycles;
	// Начало нового цикла регулятора
	IF i = 0 THEN
		// Рассогласование
		E := T_set - GVL.T;
		
		// Зона нечувствительности		
		IF ABS(E) < Zona THEN
			E := 0;
		ELSE
			IF E > 0 THEN
				E := E - Zona;
			ELSE
				E := E + Zona;
			END_IF 
		END_IF
			
		// Изменение рассогласования
		dE := E - E_old;
		// Выход регулятора, %
		GVL.Y := Kp * (dE / dt_izm + E / Tn);
		
		// Верхнее ограничение регулятора = 100%	
		IF GVL.Y > 100 THEN
			GVL.Y := 100;
		END_IF
	
		// Нижнее ограничение регулятора = -100%
		IF GVL.Y < -100 THEN
			GVL.Y := -100;
		END_IF
		
		// Замена старых значений новыми
		E_old := E;
		dE_old := dE;
		T_old := GVL.T;
	END_IF
	
	// Счетчик циклов контроллера
	i := i + 1;
	// Определение конца цикла регулятора
	IF i >= Period_reg_cycles THEN
		i := 0;
	END_IF
END_IF

Программа позиционера задвижки - описательная часть

PROGRAM Valve
VAR
	// Счетчик циклов
	Count: INT;
END_VAR
VAR RETAIN
	// Период ШИМ, секунды
	Period_PWM: REAL := 5.0;
END_VAR
VAR
	// Период ШИМ - новое значение, секунды
	Period_PWM_new: REAL;
	// Период ШИМ, циклы
	Period_PWM_cycles: INT;
	// Значение ШИМ, циклы
	Value: INT;
END_VAR
VAR RETAIN
	// Минимальное время движения клапана, секунды
	Min_value: REAL := 0.15;
END_VAR
VAR
	// Минимальное время движения клапана - новое значение, секунды
	Min_value_new: REAL;
	// Минимальное время движения клапана, циклы
	Min_value_cycles: INT;
	// Открыть клапан - дискретный выход
	Open: BOOL;
	// Закрыть клапан - дискретный выход
	Close: BOOL;
	// Открыть клапан - команда оператора
	Open_manual: BOOL;
	// Закрыть клапан - команда оператора
	Close_manual: BOOL;
	// Открыть клапан полностью - команда оператора
	Open_manual_full: BOOL;
	// Закрыть клапан полностью - команда оператора
	Close_manual_full: BOOL;
	// Остановаить клапан - команда оператора
	Stop_manual: BOOL;
	// Клапан открыт
	Opened: BOOL;
	// Клапан открыт
	Closed: BOOL;
	// Открытие клапана
	Closing: BOOL;
	// Закрытие клапана
	Opening: BOOL;
	// Авария клапана
	Alarm: BOOL;
	RS1: RS;
	RS2: RS;
END_VAR

Программа позиционера задвижки - исполнительная часть

// Применение новых настроек
IF GVL.Set_parameters THEN
	Period_PWM := Period_PWM_new;
	Min_value := Min_value_new;
END_IF;
// Расчет периода ШИМ в циклах
Period_PWM_cycles := REAL_TO_INT(Period_PWM / GVL.Cycle);
// Расчет минимального времени движения клапана в циклах
Min_value_cycles := REAL_TO_INT(Min_value / GVL.Cycle);
// Автоматический режим регулятора
IF GVL.Reg_auto THEN
	// Значение ШИМ в циклах
	Value := REAL_TO_INT(GVL.Y / 100 * Period_PWM_cycles);
	// Определение направления движения клапана
	IF (Value > 0) THEN
		Open := TRUE;
	ELSE 
		Close := TRUE;
	END_IF;
	// Если счетчик циклов меньше минимального значения или больше значения ШИМ, то остановить движение клапана
	IF ABS(Value) < Min_value OR ABS(Value) < Count THEN
		Open := FALSE;
		Close := FALSE;
	END_IF;
	
	// Счетчик циклов контроллера
	Count := Count + 1;
	// Определение конца периода ШИМ
	IF Count > Period_PWM_cycles THEN
		Count := 0;	
	END_IF;
	// Конечный выключатель закрытого состояния
	IF GVL.T < 81 OR Closed THEN
		Close := FALSE;
	END_IF;
	// Конечный выключатель открытого состояния
	IF GVL.T > 179 OR Opened THEN
		Open := FALSE;
	END_IF;
// Ручной режим работы регулятора
ELSE
	// Триггер полного открытия
	RS1(SET := Open_manual_full , RESET1 := (Opened OR Open_manual OR Close_manual OR Close_manual_full OR Stop_manual));
 	Opening := RS1.Q1 ;
	
	// Триггер полного закрытия
	RS2(SET := Close_manual_full , RESET1 := (Closed OR Open_manual OR Close_manual OR Open_manual_full OR Stop_manual));
 	Closing := RS2.Q1 ; 
	// Открыть
	IF (Open_manual OR Opening) AND NOT Opened THEN
		Open := TRUE;
	ELSE
		Open := FALSE;
	END_IF;
	
	// Закрыть
	IF (Close_manual OR Closing) AND NOT Closed THEN
		Close := TRUE;
	ELSE
		Close := FALSE;
	END_IF;
END_IF;

Ссылки

Энциклопедия АСУТП. Дискретная форма регулятора
Википедия. ПИД-регулятор
Овен ТРМ12. Руководство по эксплуатации