Показано с 1 по 5 из 5

Тема: Управлене 2 насосами через ПЧ

  1. #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
    Вложения Вложения

  2. #2
    Пользователь Аватар для Сергей0308
    Регистрация
    25.06.2011
    Адрес
    Галактика Андромеды (M31)
    Сообщений
    9,434

    По умолчанию

    Цитата Сообщение от Биба Посмотреть сообщение
    есть 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
    Мне кажется дешевле ничего не трогать, в смысле, идеальный вариант!

    А чего хотят, чтобы при аварии одного из насосов запускался другой?
    Так поставьте проводок, в смысле, там выход ПЧ можно запрограммировать(назначить функцию) на аварию!
    Последний раз редактировалось Сергей0308; 11.10.2024 в 13:53.
    Если проблему можно решить за деньги, это не проблема, это расходы. Бог каждому посылает проблемы по его силам. Так что одно из двух. Либо ты можешь-таки
    справиться с проблемами, либо это не твои проблемы.

  3. #3

    По умолчанию

    Не уясню, что такое "варварство"...

    Для двух насосов отопления (ГВС), один из которых постоянно работает, поддерживая давления, когда-то использовал:
    - два ПЧВ со своими ПИД
    - ОДИН датчик давления
    - САУ-У

    Сейчас выпускаются специализированные приборы управления насосными группами как с использованием ПЧВ, так и без них.
    ОВЕН выпускает СУНА-121/122 - посмотрите их алгоритмы, может какой-то подойдёт.

    А если уж делать на ПР, то полноценно использовать и датчики сухого хода, и индивидуальные датчики-реле перепада давления (врезанные до обратных клапанов), и использовать защиты по перегрузке по току, по длительному отсутствию повышения давления при работающем насосе, учет наработки, историю ошибок, диспетчеризацию (по Modbus).

    Для повышающих насосов подпитки (для которых не было готового прибора САУ/СУНА) - использовал алгоритм диагностики САУ (с тремя задержками), автоматический ввод резерва, чередование по порядку включения (для других нужд исправлял на период работы).

    Посмотрите сначала готовый прибор. Датчика давления достаточно одного на 2 ПЧВ.

  4. #4

    По умолчанию

    Цитата Сообщение от Сергей0308 Посмотреть сообщение
    Мне кажется дешевле ничего не трогать, в смысле, идеальный вариант!
    Согласен!

    Цитата Сообщение от Сергей0308 Посмотреть сообщение
    А чего хотят, чтобы при аварии одного из насосов запускался другой?
    Так поставьте проводок, в смысле, там выход ПЧ можно запрограммировать(назначить функцию) на аварию!
    Чтобы как в нормальных станциях - сменялись насосы, не работали одновременно оба если нет необходимости, защиту от сухого хода, защиту от аварий насоса/ПЧ.
    Короче, полноценную станцию, но по цене ПР.

    Сейчас выпускаются специализированные приборы управления насосными группами как с использованием ПЧВ, так и без них.
    ОВЕН выпускает СУНА-121/122 - посмотрите их алгоритмы, может какой-то подойдёт.
    Спасибо за наводку, посмотрю.

  5. #5
    Пользователь Аватар для Сергей0308
    Регистрация
    25.06.2011
    Адрес
    Галактика Андромеды (M31)
    Сообщений
    9,434

    По умолчанию

    В соседней теме подобное рассматривали, в смысле, можно посмотреть механизм ротации, включение резервного на помощь первому насосу или при аварии первого насоса и т.п.:
    https://owen.ru/forum/showthread.php?t=40336
    Если проблему можно решить за деньги, это не проблема, это расходы. Бог каждому посылает проблемы по его силам. Так что одно из двух. Либо ты можешь-таки
    справиться с проблемами, либо это не твои проблемы.

Похожие темы

  1. Управление насосами КНС
    от Xalik в разделе Подбор Оборудования
    Ответов: 6
    Последнее сообщение: 23.12.2018, 17:18
  2. Управление насосами
    от Андрей Прокофьев в разделе Программируемые реле
    Ответов: 10
    Последнее сообщение: 31.07.2018, 16:09
  3. Управление насосами
    от xroi в разделе ПЛК1хх
    Ответов: 17
    Последнее сообщение: 10.11.2017, 21:27
  4. для управления насосами
    от gkip в разделе Подбор Оборудования
    Ответов: 17
    Последнее сообщение: 18.02.2010, 12:52
  5. насосами ПИД
    от kanava в разделе Помощь Разработчикам
    Ответов: 0
    Последнее сообщение: 29.10.2008, 09:47

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •