Функции (формулы) для Rapid SCADA

Стартовая страница Форумы Понять, как работает ПО Формулы Функции (формулы) для Rapid SCADA

Просмотр 15 сообщений - с 91 по 105 (из 150 всего)
  • Автор
    Сообщения
  • #31145
    manjey73
    Участник
    // Таймер с задержкой выключения TOF
    public double TOF(double IN, double PT)
    {
    var ut = new UtilTimer() {et = 0L, flag = false};
    long ET = 0L;
    long _pt = Convert.ToInt64(PT);
    bool q = Val(CnlNum) > 0;
    bool _in = IN > 0;
    
    if (!CDSTimer.ContainsKey(CnlNum))
    {
    CDSTimer.Add(CnlNum, ut);
    }
    
    if (_in)
    {
    q = true;
    CDSTimer[CnlNum].flag = true;
    CDSTimer[CnlNum].et = 0L;
    ET = 0L;
    }
    else
    {
    if (CDSTimer[CnlNum].flag)
    {
    CDSTimer[CnlNum].flag = false;
    CDSTimer[CnlNum].et = Ticks();
    ET = 0L;
    }
     else
     {
       if (q) ET = Ticks() - CDSTimer[CnlNum].et;
     }
     if (ET >= _pt) q = false;
    }
    return Convert.ToDouble(q);
    }
    

    TOF в том же ключе, добавить к тексту вместе с таймером TON

    • Ответ изменён 2 года, 4 месяца назад пользователем manjey73.
    #31148
    manjey73
    Участник

    Ну и импульсный таймер TP из МЭК так же добавить

    // Импульс Таймер TP
    public double TP(double IN, double PT)
    {
    var ut = new UtilTimer() {et = 0L, flag = false};
    long ET = 0L;
    long _pt = Convert.ToInt64(PT);
    bool q = Val(CnlNum) > 0;
    bool _in = IN > 0;
    
    if (!CDSTimer.ContainsKey(CnlNum))
    {
    CDSTimer.Add(CnlNum, ut);
    }
    
    if (!CDSTimer[CnlNum].flag)
    {
     if (_in)
     {
     CDSTimer[CnlNum].flag = true;
     CDSTimer[CnlNum].et = Ticks();
     if (ET < _pt) q = true;
     }
    }
    else
    {
      if (q)
      {
      ET = Ticks() - CDSTimer[CnlNum].et;
      if (ET >= _pt) q = false;
      }
      else
      {
       if(!_in)
       {
       CDSTimer[CnlNum].flag = false;
       ET = 0L;
       }
     }
    }
    return Convert.ToDouble(q);
    }
    #31150
    Algomus
    Участник

    А какая циклограмма у последней формулы? По сути это генератор. Тогда должны быть длительность импульса и паузы, а так же фазы.

    #31151
    manjey73
    Участник

    @Algomus TP это другое, на вход подаётся либо постоянная 1 либо импульс лог 1 и он сразу включит выход и выключит после задержки.
    При чём если лог 1 останется на входе, то выход все равно выключится через заданное время.

    Я вот ещё не тестировал, но по идее под каждый вид таймера надо делать свой словарь, иначе наверное нельзя будет встроить один таймер в другой.
    Хотя не знаю, можно ли вообще, как-то не пробовал.
    В смысле делать составные формулы, а не поканальные.

    #31152
    Algomus
    Участник

    manjey73 Т.е. это одно вибратор? В некоторых случаях полезно графически показать функционал устройства. Как на фото реле от Меандр. https://s.leroymerlin.ru/upload/catalog/img/1/e/82810997/82810997.jpg

    • Ответ изменён 2 года, 4 месяца назад пользователем Algomus.
    #33140
    Z_h_e
    Участник

    Здравствуйте.
    Есть у меня некий канал входной 741, работает.
    Добавил канал 803, тоже входной и привязал его к тому же тэгу, что и 741 и 741 перестал обновляться.
    В общем-то не проблема, когда понял в чем дело. Стал для 803 использовать функцию Val(741).
    Вопрос «для повышения образованности». Нельзя в разных каналах одного и того же устройства указывать один ТЭГ?
    С выходным вроде такого нет. Тут можно дублировать тэги.

    #33141
    Romiros
    Участник

    Нельзя. Вы правильно применили формулу. И с точки зрения одного источника правды, то как сделаю в системе сейчас — это правильно. Такой подход не только у RapidScada.

    #33150
    Mikhail
    Модератор

    Добрый день!
    Кроме того, с точки зрения обмена данными между Сервером и Коммуникатором передавать одно и то же значение тега на 2 разных канала было бы не оптимально. Поэтому формула здесь более уместна.

    #33227
    RX9COZ
    Участник

    Добрый день ! Прошу помощи.

    Имеется некий контроллер насосов, с которого можно опросить три канала с булевским содержимым, допустим:

    101 — Режим Автоматического управления (тумблер на дверце шкафа)
    102 — Мотор-Автомат включён
    103 — Насос в работе

    Появилась задача сделать скрипт, т.к. просто формулой тут не обойтись (вернее можно, но только на 3 вида состояния насоса, а надо 4).
    Для корректного отображения на мнемосхеме нужно сделать расчётный канал, например 104, в котором будет храниться 4 состояние насоса (я сделал 4 картинки) с принимаемыми значениями канала от 0 до 3, где, допустим:

    0 — Насос не доступен (снят или выведен из эксплуатации итд)
    1 — Авария насоса
    2 — Готов к пуску
    3 — Насос в работе

    Если всё отключено, то канал 104 должен принимать значение 0 (недоступен). Если включить мотор-автомат (канал 102=1), то ничего не изменится, так же состояние будет 0. Если попытаться включить в автоматический режим (101=1) при выключенном мотор-автомате (102=0), то должна появиться авария, например это будет значение 1 в канале 104.
    Если канал 101 и канал 102 = 1, то в канал 104 должно быть записано 2.
    Если все каналы 101-103 = 1, то в канал 104 должно записаться 3.

    В общем-то логика достаточно простая, но до меня пока не доходит как правильно оформляется скрипт и как правильно его вызывать.
    На всяких разных Ардуино-подобных штуках я это неоднократно делал и всё работало, а тут что-то затуп. Наверное, просто не правильный синтаксис.
    Понятно что тут всё на связках if else делается.
    RapidSCADA v6

    #33228
    manjey73
    Участник

    Если у вас 101, 102, 103 никогда не меняются по положению, то есть даже если будет второй насос, третий и т.д. то 201, 202, 203 будут соответствовать в последовательности так же, как и в 101, 102, 103 то можно применить params

    public double AND(params int[] cnls) // тут вместо AND свои имя функции
    {

    // через foreach (int cnlNum in cnls) можно выполнить обработку, но в вашем случае вы всегда знаете что каналов будет всего 3
    наверное надо привести значения каналов к булям

    bool x1 = Val(cnl[0]) > 0 ? true : false;
    bool x2 = Val(cnl[1]) > 0 ? true : false;
    bool x3 = Val(cnl[0]) > 0 ? true : false;

    if (x1 & x2) Одно ваше число;
    if (x2 || x3) другое ваше число;
    в общем какая-то логика
    return КонвертТуДабл(ваше число);
    }

    вызов в формуле AND(101, 102, 103) и так далее
    Можно во входной формуле определить сразу значения ваших каналов или номеров каналов AND (int cnl1, int cnl2, int cnl3)
    И возвращать формула может в принципе bool но вам надо по сути int к которому вы можете привязать например перечисление

    #33229
    manjey73
    Участник

    Все выходное будет конвертировано в double автоматически.

    Вы объявляете public bool Scrip (параметры) { return bool }

    Scada сконвертирует ваш bool в double и запишет в базу
    Если надо по каким-то причинам использовать формулу внутри другой формулы старайтесь возвращать сразу double и учитывать это, иначе автоматическое конвертирование даст осечку и сервер не загрузится. Если использования в других формулах не будет можно без конвертирования.

    #33231
    RX9COZ
    Участник

    Я, честно сказать так и не понял, как правильно пишется функция/скрипт. Как функция берёт значения из канала, как возвращает вычисленное значение в канал (в другой или этот же), в каком типе данных и зависит ли этот тип данных от того, что прописано в свойствах канала. Как использовать возвращаемое функцией вычисленное значение в расчётном канале. Как объявляются переменные и их тип в функции.

    Но, как мне показалось, с моей задачей справилась достаточно простая входная формула в расчётном канале, применительно к примеру выше подходит вот эта:

    ((Val(101) + Val(102)) * Val(101)) + Val(103)
    

    Как раз получилось что я хотел. Перечисления получились такими:
    0 = недоступен
    1 = авария
    2 = готов
    3 = работа

    Формула сломается, если в канале 103 вдруг будет 1 просто так, но этого быть не может, т.к. контроллер без наличия 1 в каналах 101 и 102 не выдаст 1 в канале 103, так что вполне рабочий вариант я думаю ?

    • Ответ изменён 1 год, 12 месяцев назад пользователем RX9COZ.
    #33235
    Mikhail
    Модератор

    Вопросы в предыдущем сообщении очень обобщённые. Могу ответить, если их сформулировать как-то более конкретно на примере.

    #33238
    manjey73
    Участник

    Функция всегда возвращает значение в канал, из которого она вызвана.
    Объявляется как public myFunc(параметры)
    Параметры вы задаете сами, например (bool in1, double val1, int val2)
    Далее вы применяете эти входные параметры в своем коде логики
    Если у вас bool, то вы при вызове пишите true или false
    При этом если вы хотите передать в качестве булевой переменной значение какого-то канала, то вам придется сделать конвертирование
    myFunc (Convert.ToBoolean(Val(101), далее duble, далее int)
    Что соответственно не удобно. Проще in1 объявить как double, так как значение канала у нас всегда double, даже если мы там используем 0 и 1
    И уже внутри вашей функции объявить bool переменную сделав
    bool _in1 = in1 > 0? true: false;

    Если вы пишите функцию как public bool myFunc () то и возвращать вам надо bool, а уже в канал запись попадет как double (будет сконвертирована в double 0 или 1).
    Этот момент надо учитывать, когда вы захотите воспользоваться значением данного канала где-то еще. Как уже написал, если вы делаете какую-то функцию, результат которой вы захотите использовать в другой своей функции, то есть делать во входной формуле вложенную формулу, то надо возвращать double. В общем там можно этим играться и оперировать в зависимости от требуемого результата.

    В общем то гибкая система но есть как всегда НО.
    1. Нельзя без танцев с бубном сохранить переменных при перезапуске сервера
    2. Нельзя как в CodeSys вызывать в коде одну и ту же функцию с изменением параметров. Пример Blink в CodeSys работает всего лишь на одном объявленном таймере TP, меняя его характеристики. тут такое не прокатывает
    3. Нельзя без создания словарей с привязкой к каналам использовать одну и ту же функцию, проблема с сохранением промежуточных результатов.

    Ну это скорее уже другая история, нужна поддержка FBD языков МЭК. либо ST. Но там работает все несколько по иному, чем в программировании на C# или подобном.

    #33239
    RX9COZ
    Участник

    Для начала мне просто надо в расчётном канале вызвать функцию, с параметрами для канала 101, 102, 103 и чтобы функция получила значения этих параметров и записала в переменные какие-нибудь, чтобы дальше над ними колдовать. Пока не важно какой тип данных, double удобнее.
    Я просто не могу в расчётном канале вызвать функцию с исходными данными из других каналов. Видимо не понимаю синтаксиса или это не возможно.

    И как сама функция должна выглядеть. Например public double MyFunc (var1, var2, var3) и я хочу чтобы в эти переменные var1-var3 записались значения каналов 101-103. Как это сделать ?
    Дальше логикой я сам разберусь. Но вычисления так же в какую-то переменную надо запихнуть и потом результат вернуть функцией в расчётный канал.

Просмотр 15 сообщений - с 91 по 105 (из 150 всего)
  • Для ответа в этой теме необходимо авторизоваться.