Формулы в V6 Beta

  • В этой теме 81 ответ, 4 участника, последнее обновление 2 года назад сделано a80808.
Просмотр 15 сообщений - с 61 по 75 (из 82 всего)
  • Автор
    Сообщения
  • #22665
    a80808
    Участник

    Итак:
    1. Вот по поводу возвращаемого значения. Была написана формула
    public CnlData TankEmu65010()
    {
    SetVal(65012, Val()+10);
    }

    В канале вызов как вы и советовали «без лишних скобок»
    EveryMin(TankEmu65010)

    В логах сообщение
    2022-03-26 15:14:34 [DELL6230][DELL6230$][ERR] Ошибка при компиляции исходного кода скриптов и формул:
    (353,16): error CS0161: ‘Scripts.TankEmu65010()’: not all code paths return a value
    Проверьте исходный код в файле Z:\SCADA\ScadaServer\Log\CalcEngine.cs
    2022-03-26 15:14:34 [DELL6230][DELL6230$][ERR] Нормальная работа невозможна

    2. Ставим формулу «с возвратом»
    public CnlData TankEmu65010()
    {
    return NewData(Val()+10,1);
    }

    В канале EveryMin(TankEmu65010)

    Все работает.
    Вопрос как передавать параметры…

    #22666
    a80808
    Участник

    По событиям — почему то события генерируются непрерывно, причем постоянно меняется состояние каналов — «недостоверный» — «определен». Непонятно почему, потому как состояние канала не меняется…

    События

    #22667
    a80808
    Участник

    Маска событий (унаследованная от 5 версии) 5

    #22668
    a80808
    Участник

    P.S. Все это работает на Win 7. Оказывается если нет Симулятора, производительность в норме. Видимо он прилично подгружает…

    #22669
    a80808
    Участник

    И еще — у меня создалось ощущение, что функция SetVal() не работает.
    Вот простейшая формула в скриптах:
    public CnlData TankEmu65010()
    {
    double capacity = Val(65010);
    capacity += 27;
    if (capacity > 930)
    {
    if (Val(65012) == 0)
    {
    SetVal(65012,1);
    }
    else
    {
    SetVal(65012,0);
    }
    capacity = 0;
    }
    return NewData(capacity,1);

    }
    Т.е она добавляет значение 27 к содержимому канала 65010, и при достижении значения 930 канал обнуляется. В момент обнуления канал 65012 должен изменить свое значение на противоположное (0 или 1). Так вот, канал 65012 никогда не меняется! Пробовал и в «чистом» виде и под EveryMin()…

    #22670
    manjey73
    Участник

    Поставьте на канал триггер, вполне возможно значение все таки меняется..

    #22671
    a80808
    Участник

    Нет, я его вывел на схему, изменений нет. Можно конечно событие навесить…

    #22672
    a80808
    Участник

    Изменяется. Тоько на очень короткое время.
    В результате понял, что нельзя делать SetVal() в расчетный канал, только во входной! Иначе значение сразу зануляется.
    Изменил тип канала на входной — все заработало. Похоже это эффект работы через формулы. Раньше расчет канала запускался раз в минуту, а теперь расчет в цикле походу…

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

    Передача параметра:
    Допустим метод имеет вид public CnlData TankEmu65010(double x) …
    Тогда вызов раз в минуту будет EveryMin(() => TankEmu65010(12.3))

    Т.к. в объявлении метода стоит возвращаемый тип CnlData, то return должен возвращать объект этого типа.

    Канал типа Входной и/или Выходной предназначен для получения или отправки данных контроллеру. Если канал рассчитывается по формулам на основе других каналов или его данные устанавливаются из других каналов, он должен быть Вычислимым.
    Если что-то не работает, давайте разбираться детально.

    #22688
    a80808
    Участник

    В том то и дело. Если я делаю канал расчетным (не тот, в котором формула (65010, он расчетный по определению), а тот, в который пишется значение через SetVal() (65012)) то значение в нем изменяется на очень короткое время, затем становится равным . Удалось «поймать» только «навесив» на канал событие. А вот если он входной то все работает как надо. В пятой версии это работало с каналом типа расчетный нормально.

    #22689
    a80808
    Участник

    Теперь про параметры. Вот абсолютно реальная смоделированная ситуация.
    Задача — эмулция заполнения баков с целью показать как это может быть отображено. По существу генератор «треугольника». Канал 65010 — это значение содержимого бака в куб.м. Канал 65012 — направление счета. Если 1 — бак сливается, 0 — наполняется (т.е. счет идет в плюс или минус) с каждой минутой к содержимому канала добавляется/вычитается определенная константа (27). 930 — верхний порог, 500 — нижний порог.
    если я в канале пишу формулу ежеминутного вызова функции расчета без перердачи параметра все работает.
    Вызов в канале 65010:
    EveryMin(TankEmu65010)

    Скрипт:
    public CnlData TankEmu65010()
    {
    double capacity = Val(65010);

    if (capacity > 930)
    {
    SetVal(65012,1);
    }
    if (capacity < 500)
    {
    SetVal(65012,0);
    }
    if (Val(65012)==1)
    {
    capacity -= 27;
    }
    else
    {
    capacity += 27;
    }

    return NewData(capacity,1);

    }

    Пытаюсь передать номер канала направления расчета как параметр функции.
    Канал 65010:
    EveryMin(TankEmu65010(6512))

    Скрипт:
    public CnlData TankEmu65010(int direct)
    {
    double capacity = Val(65010);

    if (capacity > 930)
    {
    SetVal(direct,1);
    }
    if (capacity < 500)
    {
    SetVal(direct,0);
    }
    if (Val(direct)==1)
    {
    capacity -= 27;
    }
    else
    {
    capacity += 27;
    }

    return NewData(capacity,1);

    }

    Получаю следующее сообщение об ошибке:
    2022-03-28 20:28:09 [DELL6230][DELL6230$][ERR] Ошибка при компиляции исходного кода скриптов и формул:
    (619,63): error CS1503: Argument 1: cannot convert from ‘Scada.Data.Models.CnlData’ to ‘System.Func<Scada.Data.Models.CnlData>’
    Проверьте исходный код в файле Z:\SCADA\ScadaServer\Log\CalcEngine.cs

    Строка 619 из CalcEngine.cs:
    public CnlData CalcCnlData65010() { return ToCnlData(EveryMin(TankEmu65010(65012))); }
    ^

    Убираю из канала параметр в вызове, но в скрипте определяю его какк внутреннюю переменную int:
    public CnlData TankEmu65010()
    {
    double capacity = Val(65010);
    int direct = 65012;

    if (capacity > 930)
    {
    SetVal(direct,1);
    }
    if (capacity < 500)
    {
    SetVal(direct,0);
    }
    if (Val(direct)==1)
    {
    capacity -= 27;
    }
    else
    {
    capacity += 27;
    }

    return NewData(capacity,1);

    }

    И все работает:
    для справки — в пятой версии вызов функции выглядел так:
    TankEmu(65010, 65012, 27, 500, 930)
    Соответственно формула:
    double TankEmu(int cnl_emu, int cnl_dir, int step, int dn_lim, int up_lim)
    {
    double capacity = Val(cnl_emu);

    if (capacity < dn_lim)
    {
    SetVal(cnl_dir, 1);
    }
    if (capacity > up_lim)
    {
    SetVal(cnl_dir, 0);
    }
    if (Val(cnl_dir) == 1)
    {
    capacity += step;
    }
    else
    {
    capacity -= step;
    }
    return capacity;
    }

    Т.е. практически все параметры передавались через вызов. Все работало.

    #22690
    a80808
    Участник

    В ВЕБ это выглядело так (сорри за каракули, сам рисовал 🙂 — не мое это рисование :))
    Баки

    #22695
    a80808
    Участник

    Почему тут нужны параметры — на станции баков великое множество и с разными параметрами. В случае расчета по косвенным данным (далеко не везде стоят расходомеры, рассчитывают по времени работы насоса) не писать же под каждый бак свою формулу…

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

    Пытаюсь передать номер канала направления расчета как параметр функции.

    Синтаксис передачи параметра для вызова раз в минуту писал выше в сообщении #22681.
    По поводу некорректной работы формулы: приложите скриншоты задействованных каналов и формул.

    #22704
    a80808
    Участник

    > Синтаксис передачи параметра для вызова раз в минуту писал выше в сообщении #22681.

    Михаил, я понимаю, что у вас нет времени вникать в мои формулы, написанные выше. С возвратом значения все нормально. Проблема в том, что если я в канале пишу формулу вызова без параметров — все работает, если я пытаюсь передать номер канала, в который надо писать через SetVal() — причем без разницы как я его потом объявляю в формуле — идет ошибка компиляции.

    Про входные/расчетные каналы понятно, но вот только если в канал (расчетный) записать что то функцией SetVal() — он мгновенно обнуляется. В пятой версии такого не было…

Просмотр 15 сообщений - с 61 по 75 (из 82 всего)
  • Вы должны авторизироваться для ответа в этой теме.