есть 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


Ответить с цитированием
