Вложений: 1
Управлене 2 насосами через ПЧ
есть 2 ПЧ управляющие 2 насосами на подъемной станции холодного водоснабжения. Сейчас на каждом из них настроен ПИД регулятор и к каждому подключен свой датчик давления. Заказчику кажется это варварством и он хочет автоматизацию(но по дешевле). предложил ему ПР200 с аналоговыми выходами.
Суть вопроса:
Написал ФБ для этих ПЧ и вроде все нормально работет, но вот в части логики переключения насосов, как мне кажется, перемудрил но ничего более адекватного родить не смог.
Найдутся ли господа которы бы помогли переработать код и сделать его изящней?
Код:
FUNCTION_BLOCK PID_Controller_
var_input
Run: bool; // разрешение на работу
Setpoint: real; // Уставка (целевое значение)
Feedback: real; // Входной сигнал обратной связи (4-20 мА)
Kp: real; // Пропорциональный коэффициент
Ki: real; // Интегральный коэффициент
Kd: real; // Дифференциальный коэффициент
Maxdat: real; // предел датчика 4-20
Frequency: udint; // вход для времени дискретизации (мс)
AlarmFM1: bool; // NС контакт ошибки ПЧ
AlarmFM2: bool; // NС контакт ошибки ПЧ
Time_Pump: udint; // время смены основного насоса (ч)
low_inlet_press: bool; // защита от сухого хода (NC)
which_pump: udint:= 0; // выбор работы: 0- оба насоса со сменой; 1-только 1 насос; 2-только 2 насос; 3- оба насоса без смены 1 основной; 4- оба насоса без смены 2 основной
end_var
var_output
ScaledOutput : real; // Масштабированный выходной сигнал в бар
FM1: real; // выходной сигнал на AO1
FM2: real; // выходной сигнал на AO2
AlarmOut_b: bool; // красный светодиод
AlarmOut_U: udint; // переменная на экран: 0- нет аварий; 1-авария 1 насоса; 2-авария 2 насоса; 3-сухой ход; 4- авария обоих насосов
end_var
var
Error: real; // Ошибка
PreviousError: real:= 0.0; // Предыдущая ошибка
Integral: real:= 0.0; // Интегральная составляющая
Derivative: real; // Дифференциальная составляющая
MinOutput: real:= 0; // Минимальное значение выходного сигнала
MaxOutput: real:= 1; // Максимальное значение выходного сигнала
TP_1: SYS.TP;
OutputSignal_RAW: real; // не масштабированный входной сигнал обратной связи
OutputSignal_LOW: real; // масштабированный входной сигнал обратной связи для основного/единственного насоса
OutputSignal_HIGH: real; // масштабированный входной сигнал обратной связи для резевного насоса
T_time: time;
PumpSw: SYS.blink;
switch_Pump: bool; // основной/резервный по времени
Time_switch: time;
pip: bool; // разрешение на вычисление
end_var
T_time:= udint_to_time(Frequency);
Time_switch:= udint_to_time(Time_Pump*3600000);
ScaledOutput := ((Feedback-4)*MaxOutput)/16 ; // Масштабирование
if Run then // генератор импульса
TP_1(I:= not pip, T:= T_time, Q => pip);
else
TP_1(I:= false);
pip:= false;
OutputSignal_RAW:= 0;
end_if
if pip and Run then
OutputSignal_RAW:= OutputSignal_RAW;
elsif not pip and Run then // Вычисление ошибки с масштабированием входного сигнала (4-20 мА)
Error:= Setpoint - ScaledOutput; // расчет ошибки
Integral:= Integral + Error; // Интегральная составляющая
Derivative:= Error - PreviousError; // Дифференциальная составляющая
OutputSignal_RAW:= Kp * Error + Ki * Integral + Kd * Derivative; // Вычисление выходного сигнала
PreviousError:= Error; // Сохранение текущей ошибки для следующего шага
elsif not Run then
OutputSignal_RAW:= 0;
end_if
OutputSignal_LOW:= OutputSignal_RAW/100; // масштабирование для АО
IF OutputSignal_LOW < MinOutput then // ограничение от 0 до 1
OutputSignal_LOW:= MinOutput;
elsif OutputSignal_LOW > MaxOutput then
OutputSignal_LOW:= MaxOutput;
end_if
OutputSignal_HIGH:= (OutputSignal_RAW-100)/100; // масштабируем для АО
IF OutputSignal_HIGH < MinOutput then // ограничение от 0 до 1
OutputSignal_HIGH:= MinOutput;
elsif OutputSignal_HIGH > MaxOutput then
OutputSignal_HIGH:= MaxOutput;
end_if
// логика насосов
if AlarmFM1 and AlarmFM2 and low_inlet_press then // если нет ошибок
AlarmOut_b:= false;
AlarmOut_U:= 0;
if Run and which_pump= 0 then // стандартный режим
PumpSw (I:= true,Th:= Time_switch,Tl:= Time_switch,Q=>switch_Pump);
if switch_Pump then
FM1:= OutputSignal_LOW;
FM2:= OutputSignal_HIGH;
else
FM2:= OutputSignal_LOW;
FM1:= OutputSignal_HIGH;
end_if
elsif run and which_pump= 1 then
FM1:= OutputSignal_LOW;
FM2:= 0;
elsif run and which_pump= 2 then
FM1:= 0;
FM2:= OutputSignal_LOW;
elsif run and which_pump= 3 then
FM1:= OutputSignal_LOW;
FM2:= OutputSignal_HIGH;
elsif run and which_pump= 4 then
FM1:= OutputSignal_HIGH;
FM2:= OutputSignal_LOW;
else
FM1:= 0;
FM2:= 0;
PumpSw (I:= false);
end_if
// реакции на ошибки
elsif not AlarmFM1 and not AlarmFM2 and low_inlet_press then // авария 1 и 2 насоса
FM1:= 0;
FM2:= 0;
AlarmOut_b:= true;
AlarmOut_U:= 4;//
elsif not AlarmFM1 and low_inlet_press then // авария 1 насоса
if Run then
if which_pump= 0 or which_pump>= 2 then
FM1:= 0;
FM2:= OutputSignal_LOW;
AlarmOut_b:= true;
AlarmOut_U:= 1;//
elsif which_pump= 1 then
FM1:= 0;
FM2:= 0;
AlarmOut_b:= true;
AlarmOut_U:= 1;//
elsif which_pump= 2 then
FM1:= 0;
FM2:= OutputSignal_LOW;
AlarmOut_b:= false;
AlarmOut_U:= 0;//
end_if
elsif not run and which_pump= 2 then
FM1:= 0;
FM2:= 0;
AlarmOut_b:= false;
AlarmOut_U:= 0;//
else
FM1:= 0;
FM2:= 0;
AlarmOut_b:= true;
AlarmOut_U:= 1;//
end_if
elsif not AlarmFM2 and low_inlet_press then // авария 2 насоса
if Run then
if which_pump= 0 or which_pump>= 3 then
FM1:= OutputSignal_LOW;
FM2:= 0;
AlarmOut_b:= true;
AlarmOut_U:= 2;//
elsif which_pump= 2 then
FM1:= 0;
FM2:= 0;
AlarmOut_b:= true;
AlarmOut_U:= 2;//
elsif which_pump= 1 then
FM1:= OutputSignal_LOW;
FM2:= 0;
AlarmOut_b:= false;
AlarmOut_U:= 0;//
end_if
elsif not run and which_pump= 1 then
FM1:= 0;
FM2:= 0;
AlarmOut_b:= false;
AlarmOut_U:= 0;//
else
FM1:= 0;
FM2:= 0;
AlarmOut_b:= true;
AlarmOut_U:= 2;//
end_if
elsif not low_inlet_press then // сухой ход
FM1:= 0;
FM2:= 0;
AlarmOut_b:= true;
AlarmOut_U:= 3;//
end_if
END_FUNCTION_BLOCK