Страница 2 из 2 ПерваяПервая 12
Показано с 11 по 17 из 17

Тема: Алгоритм поддержания уровня количеством включённых насосов

  1. #11

    По умолчанию

    Цитата Сообщение от kondor3000 Посмотреть сообщение
    Не нужен тут ПИД, ротация 4 насосов и включение по уровню давно выложены тут, последний вариант.
    https://owen.ru/forum/showthread.php?t=38920&page=2#13
    Спасибо

    Не очень люблю ответы в виде кода в файлах, лучше бы добавлять пояснения в сообщении. Особенно принятые алгоритмические решения.
    Потому, что идею беру с благодарностью, а реализацию буду дополнять защитами (например, останов работы по причине неправильной последовательности электродов)

    Если не сложно, дополните примеры очень краткими пояснениями на пару тройку строк.

    Как понимаю, количество насосов определяется по 4 дискретным уровням (аналоговым уставкам) и на каком-то из них и уравняется баланс между притоком и оттоком воды в резервуар (+/-1 насос).

    Тоже решение. Предполагаю, будет работать, только уровни подобрать с учётом максимальной скорости заполнения.

    Реализуется просто. Могу сделать два варианта - Ваш и по интегральному критерию - и предоставить заказчику выбирать. Интегральный критерий сложен для восприятия, а тут достаточно сказать, что баланс наступит около одной из 4 уставок.

  2. #12

    По умолчанию

    Цитата Сообщение от FPavel Посмотреть сообщение
    Реализуется просто. Могу сделать два варианта - Ваш и по интегральному критерию - и предоставить заказчику выбирать. Интегральный критерий сложен для восприятия, а тут достаточно сказать, что баланс наступит около одной из 4 уставок.
    Каскад с интегралом выложен тут, переключение тем быстрее, чем больше разница температур ( у вас от уровня) https://owen.ru/forum/showthread.php?t=38453&page=10#93
    Ротация с уровнем и переключением по времени, это упрощённая версия, но смысл тот же. В примерах всё подписано, разобраться не сложно.
    Уровень можно сделать как по аналогу, так и по дискретным сигналам, там всё просто.
    Последний раз редактировалось kondor3000; Вчера в 14:14.

  3. #13

    По умолчанию

    Цитата Сообщение от Валенок Посмотреть сообщение
    Учтено. Если внимательно смотрели
    Спасибо, да, внимательно прочитал и разобрался перед ответом - увидел диапазон 0-5 для отключённых состояний.

    У меня до сих пор были задания на одновременную работу не более 2 насосов, а там выбор делал просто по двухпозиционному алгоритму с гистерезисом и задержками (правда, сравнивал не отклонения, а токи и частоту - чтобы работа была не на максимуме мощности).

    Теперь же разрешено задействовать все имеющиеся насосы. Своего опыта и мнения нет, изучаю опыт других. Даже на алгоритме пока остановиться не могу.

    Поэтому благодарен всем за советы и мнения о достоинствах и недостатках алгоритмов.

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

    По умолчанию

    Вот здесь выкладывал проекты с ротацией насосов и каскад:
    https://owen.ru/forum/showthread.php...l=1#post420896
    https://owen.ru/forum/showthread.php...l=1#post420791
    https://owen.ru/forum/showthread.php...l=1#post322722
    Кстати, много раз это обсуждалось в разный темах!
    Если у Вас значение регулируемого параметра резко не может меняться всё будет работать 100 лет, в смысле, лучше не мудрить, а то и перемудрить можно!
    Последний раз редактировалось Сергей0308; Вчера в 18:02.
    Если проблему можно решить за деньги, это не проблема, это расходы. Бог каждому посылает проблемы по его силам. Так что одно из двух. Либо ты можешь-таки
    справиться с проблемами, либо это не твои проблемы.

  5. #15

    По умолчанию

    Цитата Сообщение от Сергей0308 Посмотреть сообщение
    Вот здесь выкладывал проекты с ротацией насосов и каскад:
    Спасибо

    Посмотрю.
    Хочу сделать несколько вариантов и на практике проверить - какой подойдёт, тот и оставлю.
    Сейчас пробую собрать каскад по КТР-121
    https://docs.owen.ru/product/ktr121/...70#topic-82275
    Чуть позже сделаю по предложению kondor3000 - поиск баланса притока и оттока по нескольким уровням, отстоящим от задания - дискретным уровням
    https://owen.ru/forum/showthread.php...l=1#post479184
    И Ваши посмотрю и реализую.

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

    С ротацией вопросов в целом нет, вдобавок, заказчик настаивает на отказе от ротации в работе - только при останове или при переключениях мощности под управлением каскада.

    За объект регулирования ничего не знаю - в ТЗ только схема автоматизации и электрическая функциональная, краткое описание функционала алгоритмов.

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

    По умолчанию

    Цитата Сообщение от FPavel Посмотреть сообщение
    Спасибо

    Посмотрю.
    Хочу сделать несколько вариантов и на практике проверить - какой подойдёт, тот и оставлю.
    Сейчас пробую собрать каскад по КТР-121
    https://docs.owen.ru/product/ktr121/...70#topic-82275
    Чуть позже сделаю по предложению kondor3000 - поиск баланса притока и оттока по нескольким уровням, отстоящим от задания - дискретным уровням
    https://owen.ru/forum/showthread.php...l=1#post479184
    И Ваши посмотрю и реализую.

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

    С ротацией вопросов в целом нет, вдобавок, заказчик настаивает на отказе от ротации в работе - только при останове или при переключениях мощности под управлением каскада.

    За объект регулирования ничего не знаю - в ТЗ только схема автоматизации и электрическая функциональная, краткое описание функционала алгоритмов.
    Вот здесь разруливание одновременного запуска делал:
    https://owen.ru/forum/showthread.php...l=1#post432040
    Если проблему можно решить за деньги, это не проблема, это расходы. Бог каждому посылает проблемы по его силам. Так что одно из двух. Либо ты можешь-таки
    справиться с проблемами, либо это не твои проблемы.

  7. #17

    По умолчанию

    Цитата Сообщение от Сергей0308 Посмотреть сообщение
    Вот здесь разруливание одновременного запуска делал:
    https://owen.ru/forum/showthread.php...l=1#post432040
    Классно - выделение номера изменившегося бита при помощи CD32 - я и не знал, когда бы она пригодилась.

    Похоже, CD32 - ещё и выделяет приоритет номера насоса (номер бита), чтобы можно было менять состояние только у одного насоса.
    Я полностью не разобрался с CD32 и парным к нему DC32 и поэтому сделал рассыпухой для каждого отдельного насоса и приоритет обеспечивается жёстко определённым порядком строк.
    У меня на 5 насосов на ST - из-за необходимости уверенности в порядке выполнения
    исключение одновременных переключений:
    Код:
    ///<Description>ФБ предотвращает одновременный пуск или останов нескольких (пяти) агрегатов, разделяя изменения состояний заданной паузой</Description>
    ///<Author>!!FPA!!</Author>
    ///<GroupName>Насосы</GroupName>
    
    FUNCTION_BLOCK NotAllAtOnce5_
    
        VAR_INPUT
            ///<Description>Разрешение работы. При FALSE все выходы одновременно выключаются.</Description>
            bEnable: BOOL;
            ///<Description>Запрос включения агрегата 1</Description>
            bRequest1: BOOL;
            ///<Description>Запрос включения агрегата 2</Description>
            bRequest2: BOOL;
            ///<Description>Запрос включения агрегата 3</Description>
            bRequest3: BOOL;
            ///<Description>Запрос включения агрегата 4</Description>
            bRequest4: BOOL;
            ///<Description>Запрос включения агрегата 5</Description>
            bRequest5: BOOL;
            ///<Description>Задержка между переключениями</Description>
            nDelay_s: UDINT;
        END_VAR
    
        VAR_OUTPUT
            ///<Description>Команда включения агрегата 1</Description>
            bStart1: BOOL;
            ///<Description>Команда включения агрегата 2</Description>
            bStart2: BOOL;
            ///<Description>Команда включения агрегата 3</Description>
            bStart3: BOOL;
            ///<Description>Команда включения агрегата 4</Description>
            bStart4: BOOL;
            ///<Description>Команда включения агрегата 5</Description>
            bStart5: BOOL;
        END_VAR
    
        VAR
            tDelay: TIME;
    
            bStartPrevious1: BOOL;
            bStartPrevious2: BOOL;
            bStartPrevious3: BOOL;
            bStartPrevious4: BOOL;
            bStartPrevious5: BOOL;
    
            tpPause: SYS.TP;
    
            bSwitchEn: BOOL; // разрешение изменить состояние
    
        END_VAR
    
        // преобразование типа и пересчёт значения в [с]
        tDelay := UDINT_TO_TIME(nDelay_s * 1000);
        // ограничение минимального значения
        IF tDelay < T#1s THEN
            tDelay := T#1s;
        END_IF
        // присвоение таймеру для уменьшения параметров в следующих вызовах
        tpPause(T := tDelay);
    
        IF bEnable THEN
            // обработка для агрегата 1
            bSwitchEn := NOT(tpPause.Q) AND (bRequest1 <> bStart1);
            IF bSwitchEn THEN
                bStart1 := bRequest1;
            END_IF
            tpPause(I := bSwitchEn); // обновление значения выхода таймера для следующего обработчика
    
            // обработка для агрегата 2
            bSwitchEn := NOT(tpPause.Q) AND (bRequest2 <> bStart2);
            IF bSwitchEn THEN
                bStart2 := bRequest2;
            END_IF
            tpPause(I := bSwitchEn); // обновление значения выхода таймера для следующего обработчика
    
            // обработка для агрегата 3
            bSwitchEn := NOT(tpPause.Q) AND (bRequest3 <> bStart3);
            IF bSwitchEn THEN
                bStart3 := bRequest3;
            END_IF
            tpPause(I := bSwitchEn); // обновление значения выхода таймера для следующего обработчика
    
            // обработка для агрегата 4
            bSwitchEn := NOT(tpPause.Q) AND (bRequest4 <> bStart4);
            IF bSwitchEn THEN
                bStart4 := bRequest4;
            END_IF
            tpPause(I := bSwitchEn); // обновление значения выхода таймера для следующего обработчика
    
            // обработка для агрегата 5
            bSwitchEn := NOT(tpPause.Q) AND (bRequest5 <> bStart5);
            IF bSwitchEn THEN
                bStart5 := bRequest5;
            END_IF
            tpPause(I := bSwitchEn); // обновление значения выхода таймера для следующего обработчика
        ELSE
            // отсчёт от момента выключения, для паузы при быстром переключении bEnable
            tpPause(I := bStart1 OR bStart2 OR bStart3 OR bStart4 OR bStart5);
            // выключить все агрегаты
            bStart1 := FALSE;
            bStart2 := FALSE;
            bStart3 := FALSE;
            bStart4 := FALSE;
            bStart5 := FALSE;
        END_IF
        bStartPrevious1 := bStart1;
        bStartPrevious2 := bStart2;
        bStartPrevious3 := bStart3;
        bStartPrevious4 := bStart4;
        bStartPrevious5 := bStart5;
    END_FUNCTION_BLOCK


    каскад с интегральным критерием (a-la КТР-121):
    Код:
    /// <Description>ФБ каскадного регулирования инерционной нагрузкой - позволяет увеличивать и уменьшать количество одновременно работающих агрегатов</Description>
    /// <Author>!!FPA!!</Author>
    /// <GroupName>Регуляторы</GroupName>
    
    FUNCTION_BLOCK Cascade5_
    
        VAR_INPUT
            /// <Description>Разрешение работы. При FALSE выход рабен нулю - все агрегаты одновременно выключаются.</Description>
            bEnable: BOOL;
            /// <Description>Запрос включения регулятора</Description>
            bRequest: BOOL;
            /// <Description>Исправность агрегата 1 к работе</Description>
            bReady1: BOOL;
            /// <Description>Исправность агрегата 2 к работе</Description>
            bReady2: BOOL;
            /// <Description>Исправность агрегата 3 к работе</Description>
            bReady3: BOOL;
            /// <Description>Исправность агрегата 4 к работе</Description>
            bReady4: BOOL;
            /// <Description>Исправность агрегата 5 к работе</Description>
            bReady5: BOOL;
            /// <Description>Измеренное значение регулируемой величины</Description>
            rPV: REAL;
            /// <Description>Задание регулятора</Description>
            rSP: REAL;
            /// <Description>Зона нечувствительности (симметричная в каждую сторону)</Description>
            rDB: REAL;
            /// <Description>Значение параметро-временного интеграла, по достижении которого ступень включается</Description>
            rQSub: REAL;
            /// <Description>Значение параметро-временного интеграла, по достижении которого ступень отключаются</Description>
            rQAdd: REAL;
            /// <Description>Задержка начала расчета интеграла на подключение ступени, c</Description>
            nDelayAdd: UDINT;
            /// <Description>Задержка начала расчета интеграла на отключение ступени, c</Description>
            nDelaySub: UDINT;
            /// <Description>Снижение измеренного значения от задания для принудительного запуска агрегата</Description>
            rSP_DeltaOn: REAL;
            /// <Description>Максимальное измеренное значения для принудительного отключения всех агрегатов</Description>
            rSP_Off: REAL;
        END_VAR
    
        VAR_OUTPUT
            nAmount: UDINT;
            nMax: UDINT;
            bAddRequest: BOOL;
            bSubRequest: BOOL;
            bCalcEn: BOOL;
            nTimeCount: UDINT;
            rQCalcAdd: REAL;
            rQCalcSub: REAL;
        END_VAR
    
        VAR
            bInitDone: BOOL;
            nAmountPrevious: UDINT;
            nTimeNow: UDINT;
            nTimePrevious: UDINT;
            nTimeDelta: UDINT;
            rTimeDelta: REAL;
        END_VAR
    
        // подсчёт готовых агрегатов
        nMax := BOOL_TO_UDINT(bReady1) +
        BOOL_TO_UDINT(bReady2) +
        BOOL_TO_UDINT(bReady3) +
        BOOL_TO_UDINT(bReady4) +
        BOOL_TO_UDINT(bReady5);
        // вычисление длительности предыдущего цикла
        nTimeNow := TIME_TO_UDINT(get_time());
        IF NOT bInitDone THEN
            nTimePrevious := nTimeNow;
            nTimeCount := 0;
            nAmount := 0;
            nAmountPrevious := 0;
            bInitDone := TRUE;
        END_IF
        nTimeDelta := nTimeNow - nTimePrevious;
        rTimeDelta := UDINT_TO_REAL(nTimeDelta) * 0.001;
        nTimePrevious := nTimeNow;
    
        IF bEnable AND bRequest THEN
            // если значение опустилось слишком низко - включаем первый агрегат
            // и не ждём значительного снижения до появления запроса от интегрального критерия
            IF (nAmount = 0) AND (rPV <= rSP - rSP_DeltaOn) THEN
                nAmount := 1;
            END_IF
            // если значение поднялось слишком высоко - отключаем все агрегаты
            // и не ждём значительного повышения до появления запроса от интенрального критерия
            IF (nAmount > 0) AND (rPV > rSP_Off) THEN
                nAmount := 0;
            END_IF
            // при входе в зону нечувствительности обнуляются интегральные критерии
            IF (rPV < rSP + rDB) AND (rPV > rSP - rDB) THEN
                rQCalcSub := 0;
                bSubRequest := FALSE;
                rQCalcAdd := 0;
                bAddRequest := FALSE;
                bCalcEn := TRUE;
            END_IF
            // вычисление интегрального критерия
            IF bCalcEn THEN
                // запрос - по возможности добавить количество работающих агрегатов
                IF (rPV <= rSP - rDB) THEN
                    // обнуление интеграла противоположного направления
                    rQCalcSub := 0;
                    bSubRequest := FALSE;
                    // вычисление интегрального критерия
                    rQCalcAdd := rQCalcAdd + (rSP - rDB - rPV) * rTimeDelta;
                    bAddRequest := (rQCalcAdd >= rQAdd);
                    // ограничение вычислений от переполнения
                    IF bAddRequest THEN
                        rQCalcAdd := rQAdd;
                    END_IF
                END_IF
                // запрос - по возможности сократить количество работающих агрегатов
                IF (rPV >= rSP + rDB) THEN
                    // обнуление интеграла противоположного направления
                    rQCalcAdd := 0;
                    bAddRequest := FALSE;
                    // вычисление интегрального критерия
                    rQCalcSub := rQCalcSub + (rPV - rSP - rDB) * rTimeDelta;
                    bSubRequest := (rQCalcSub >= rQSub);
                    // ограничение вычислений от переполнения
                    IF bSubRequest THEN
                        rQCalcSub := rQSub;
                    END_IF
                END_IF
            END_IF
            IF nAmount > nMax THEN
                nAmount := nMax;
                nAmountPrevious := nMax;
            END_IF
            // если есть запрос и возможность увеличения количества - увеличиваем
            IF (nAmount < nMax) AND bAddRequest THEN
                bAddRequest := FALSE;
                rQCalcAdd := 0;
                bCalcEn := FALSE;
                nAmount := nAmount + 1;
            END_IF
            // если есть запрос и возможность уменьшения количества - уменьшаем
            IF (nAmount > 0) AND bSubRequest THEN
                bSubRequest := FALSE;
                rQCalcSub := 0;
                bCalcEn := FALSE;
                nAmount := nAmount - 1;
            END_IF
            // если интегрирование запрещено - значит выполняется какой-то отсчёт
            // поверяем его завершение
            IF NOT bCalcEn THEN
                nTimeCount := nTimeCount + nTimeDelta;
                IF (rPV <= rSP - rDB) AND (nTimeCount >= nDelayAdd * 1000) THEN
                    bCalcEn := TRUE;
                END_IF
                IF (rPv >= rSP + rDB) AND (nTimeCount >= nDelaySub * 1000) THEN
                    bCalcEn := TRUE;
                END_IF
            ELSE
                // если количество агрегатов изменилось, то делаем паузу в вычислениях
                bCalcEn := (nAmount = nAmountPrevious);
                nTimeCount := 0;
            END_IF
        ELSE
            // при запрете работы или отключении регулирования
            nAmount := 0;
            bCalcEn := FALSE;
        END_IF
        nAmountPrevious := nAmount;
    END_FUNCTION_BLOCK


    И пример использования
    Там же упрощённый каскадный регулятор - по сетке уставок включает всё меньше насосов последовательно с каждым увеличивающимся диапазоном.


    Проверял только в эмуляции. Может ещё и не все ошибки выловил.
    Вложения Вложения

Страница 2 из 2 ПерваяПервая 12

Похожие темы

  1. Алгоритм работы 3-х насосов на ST
    от K.K. в разделе СПК210, СПК1xx [М01]
    Ответов: 17
    Последнее сообщение: 06.12.2024, 09:46
  2. Ответов: 22
    Последнее сообщение: 29.11.2020, 16:23
  3. Алгоритм поддержания температуры на выходе
    от IloNA в разделе Помощь Разработчикам
    Ответов: 13
    Последнее сообщение: 15.12.2016, 18:58
  4. Система поддержания уровня воды
    от Lexey-ru в разделе Трёп (Курилка)
    Ответов: 34
    Последнее сообщение: 09.06.2014, 21:02
  5. контроллер для поддержания уровня давления в контуре гвс
    от san822 в разделе Подбор Оборудования
    Ответов: 9
    Последнее сообщение: 26.10.2009, 13:02

Ваши права

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