Стартовая страница › Форумы › Понять, как работает ПО › Формулы › Функции (формулы) для Rapid SCADA
- В этой теме 149 ответов, 17 участников, последнее обновление 1 год, 3 месяца назад сделано
Oleg.
-
АвторСообщения
-
16.02.2024 в 15:45 #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.
16.02.2024 в 15:57 #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); }16.02.2024 в 17:46 #31150Algomus
УчастникА какая циклограмма у последней формулы? По сути это генератор. Тогда должны быть длительность импульса и паузы, а так же фазы.
16.02.2024 в 19:40 #31151
manjey73Участник@Algomus TP это другое, на вход подаётся либо постоянная 1 либо импульс лог 1 и он сразу включит выход и выключит после задержки.
При чём если лог 1 останется на входе, то выход все равно выключится через заданное время.Я вот ещё не тестировал, но по идее под каждый вид таймера надо делать свой словарь, иначе наверное нельзя будет встроить один таймер в другой.
Хотя не знаю, можно ли вообще, как-то не пробовал.
В смысле делать составные формулы, а не поканальные.17.02.2024 в 06:24 #31152Algomus
Участникmanjey73 Т.е. это одно вибратор? В некоторых случаях полезно графически показать функционал устройства. Как на фото реле от Меандр. https://s.leroymerlin.ru/upload/catalog/img/1/e/82810997/82810997.jpg
-
Ответ изменён 2 года, 4 месяца назад пользователем
Algomus.
20.06.2024 в 21:12 #33140Z_h_e
УчастникЗдравствуйте.
Есть у меня некий канал входной 741, работает.
Добавил канал 803, тоже входной и привязал его к тому же тэгу, что и 741 и 741 перестал обновляться.
В общем-то не проблема, когда понял в чем дело. Стал для 803 использовать функцию Val(741).
Вопрос «для повышения образованности». Нельзя в разных каналах одного и того же устройства указывать один ТЭГ?
С выходным вроде такого нет. Тут можно дублировать тэги.20.06.2024 в 21:18 #33141Romiros
УчастникНельзя. Вы правильно применили формулу. И с точки зрения одного источника правды, то как сделаю в системе сейчас — это правильно. Такой подход не только у RapidScada.
21.06.2024 в 12:31 #33150
MikhailМодераторДобрый день!
Кроме того, с точки зрения обмена данными между Сервером и Коммуникатором передавать одно и то же значение тега на 2 разных канала было бы не оптимально. Поэтому формула здесь более уместна.26.06.2024 в 15:39 #33227RX9COZ
УчастникДобрый день ! Прошу помощи.
Имеется некий контроллер насосов, с которого можно опросить три канала с булевским содержимым, допустим:
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 v626.06.2024 в 16:02 #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 к которому вы можете привязать например перечисление26.06.2024 в 16:05 #33229
manjey73УчастникВсе выходное будет конвертировано в double автоматически.
Вы объявляете public bool Scrip (параметры) { return bool }
Scada сконвертирует ваш bool в double и запишет в базу
Если надо по каким-то причинам использовать формулу внутри другой формулы старайтесь возвращать сразу double и учитывать это, иначе автоматическое конвертирование даст осечку и сервер не загрузится. Если использования в других формулах не будет можно без конвертирования.27.06.2024 в 12:31 #33231RX9COZ
УчастникЯ, честно сказать так и не понял, как правильно пишется функция/скрипт. Как функция берёт значения из канала, как возвращает вычисленное значение в канал (в другой или этот же), в каком типе данных и зависит ли этот тип данных от того, что прописано в свойствах канала. Как использовать возвращаемое функцией вычисленное значение в расчётном канале. Как объявляются переменные и их тип в функции.
Но, как мне показалось, с моей задачей справилась достаточно простая входная формула в расчётном канале, применительно к примеру выше подходит вот эта:
((Val(101) + Val(102)) * Val(101)) + Val(103)
Как раз получилось что я хотел. Перечисления получились такими:
0 = недоступен
1 = авария
2 = готов
3 = работаФормула сломается, если в канале 103 вдруг будет 1 просто так, но этого быть не может, т.к. контроллер без наличия 1 в каналах 101 и 102 не выдаст 1 в канале 103, так что вполне рабочий вариант я думаю ?
-
Ответ изменён 1 год, 12 месяцев назад пользователем
RX9COZ.
27.06.2024 в 12:51 #33235
MikhailМодераторВопросы в предыдущем сообщении очень обобщённые. Могу ответить, если их сформулировать как-то более конкретно на примере.
27.06.2024 в 13:46 #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# или подобном.
27.06.2024 в 15:32 #33239RX9COZ
УчастникДля начала мне просто надо в расчётном канале вызвать функцию, с параметрами для канала 101, 102, 103 и чтобы функция получила значения этих параметров и записала в переменные какие-нибудь, чтобы дальше над ними колдовать. Пока не важно какой тип данных, double удобнее.
Я просто не могу в расчётном канале вызвать функцию с исходными данными из других каналов. Видимо не понимаю синтаксиса или это не возможно.И как сама функция должна выглядеть. Например public double MyFunc (var1, var2, var3) и я хочу чтобы в эти переменные var1-var3 записались значения каналов 101-103. Как это сделать ?
Дальше логикой я сам разберусь. Но вычисления так же в какую-то переменную надо запихнуть и потом результат вернуть функцией в расчётный канал. -
Ответ изменён 2 года, 4 месяца назад пользователем
-
АвторСообщения
- Для ответа в этой теме необходимо авторизоваться.