Стартовая страница › Форумы › Понять, как работает ПО › Усреднение обрабатываемых данных
Помечено: Вам какой вариант подходит больше?
- В этой теме 17 ответов, 5 участников, последнее обновление 2 месяца назад сделано
Mikhail.
-
АвторСообщения
-
03.12.2017 в 02:01 #8056
Danila_Razlivanov
УчастникДоброго времени суток. Возник такой вопрос, есть ли возможность посчитать среднее значение получаемого параметра, скажем, за сутки? То есть, в зависимости от изменения, к примеру, расхода, изменяется количество твердого в перекачиваемой жидкости. Т.к. в разные моменты времени, опять же в зависимости от расхода, значение расчитываемой величины (количества твердого) будем меняться, есть необходимость обсчитать это значение, к примеру, за сутки. Подскажите, есть ли такая возможность, и какие варианты её реализации? Заранее благодарен.
04.12.2017 в 10:26 #8058Mikhail
МодераторДобрый день!
За час и за минуту рассчитать среднее можно, поставить галочку усреднения для входного канала.Если нужно рассчитать среднее за сутки или за любой заданный интервал времени, то потребуется завести дополнительные входные каналы для суммирования данных и для подсчёта количества измерений. И ещё один канал, который будет вычислять среднее путём деления значений первых двух каналов.
Кроме того, в определённые моменты времени необходимо сбрасывать счётчики.04.12.2017 в 10:32 #8059Mikhail
МодераторПримеры формул для аналогичной задачи:
// Среднее значение за период double PerAvg(int sumCnlNum, int cntCnlNum) { if (Stat() == 2) // архивный { return Val(); } else { double sum = Val(sumCnlNum); double cnt = Val(cntCnlNum); return cnt < 1 ? 0 : sum / cnt; } } // Статус среднего значения за период double PerAvgStat(int cntCnlNum) { return Stat() == 2 ? 2 : (Val(cntCnlNum) < 1 ? 0 : 1); } // Обработать полученное от контроллера значение double ProcVal(double coef, params int[] sumCnlNums) { double cur = Cnl >= 0 ? Cnl * coef : 0; foreach (int sumCnlNum in sumCnlNums) { int cntCnlNum = sumCnlNum + 1; double newSum = Val(sumCnlNum) + cur; double newCnt = Val(cntCnlNum) + 1; SetVal(sumCnlNum, newSum); SetVal(cntCnlNum, newCnt); } return cur; } // Обнулить значение в начале суток double ResetOnDayBeg() { return DayBeg() ? 0 : Val(); }
19.04.2019 в 08:04 #11454baur
УчастникВсем привет,
1)
как можно эту формулу переделать в счетчик который не сбрасывается2)
За час и за минуту рассчитать среднее можно, поставить галочку усреднения для входного канала.
то есть создаем 2 канала (минутный ТС, часовой ТС), формула = Val(нужный номер канала) + галочка усреднение?
19.04.2019 в 08:27 #11455baur
Участнику нас уже есть сигнал текущая переработка (т/час), мы не можем его трогать.
Надо усреднить отдельно через дорасчетный канал (минутный, часовой) а еще лучше создать отдельный счетчик (сумматор)-
Этот ответ был изменен 5 лет, 10 месяцев назад от
baur.
19.04.2019 в 08:53 #11459Mikhail
МодераторДля работы со средними значениями были разработаны и протестированы специальные формулы. Их можно скопировать отсюда. Как их использовать написано в комментариях в начале файла.
12.12.2024 в 16:47 #36118Aeromixture
УчастникНе совсем понятно как использовать этот код. Если копировать весь класс то он не помещается в ограничение в 4000 символов. Если копировать часть кода ничего не работает.
12.12.2024 в 17:26 #36119a80808
УчастникВам это нужно на экране или в отчете? Гибкий отчет сам считает среднее. Как вариант суммировать в какой то канал значения, например каждый час, а потом раз в сутки делить это на 24
Это все для 5.8, в шестерке должно быть проще…13.12.2024 в 14:19 #36166Mikhail
МодераторКод выше подразумевает, что Вы завели 2 дополнительных расчётных канала:
— Для суммы значений.
— Для количества значений.Этот подход удобен, когда величин для расчёта средних значений не так много.
Код для версии 5. Для версии 6 его нужно немного доработать.13.12.2024 в 14:20 #36167Mikhail
МодераторДа, как вариант — гибким отчётом посчитать среднее за период отчёта.
13.12.2024 в 14:21 #36168Mikhail
МодераторРасскажите подробнее про свою задачу, чтобы было понятнее как её удобнее решать.
15.12.2024 в 20:28 #36185Aeromixture
УчастникНужно среднее значение за промежуток времени. Конкретно за прошедший день и месяц.
15.12.2024 в 20:30 #36186Aeromixture
УчастникНужно выводить на экран среднее значение за сутки и месяц. Не скользящее среднее.
15.12.2024 в 22:11 #36187a80808
УчастникСуммировать в канале, потом делить на число измерений
Вот я делал для другого проекта (правда версия 5, но можно переделать):
«…
На стороне Scada была реализована следующая схема:
1. (3210) Канал ТС принимающий состояния входа, определяющего работу насоса (0/1) – Событие/Текст перечисления/Вкл-Откл/Запись событий/Событие по изменению;
2. (60081) (Минутный ТИ) Канал, подсчитывающий мнгновенную (минутную) производительность (подачу), т.е. если насос включен — значение канала равно константе производительности, выключен = 0 (Val(3210)==0?(100*0.8):0);
3. (60100) (Дорасчетный ТИ) Канал, подсчитывающий суммарную подачу, т.е. суммирует подачу всех насосов одной насосной;
4. Дальше идет блок каналов суммирования за определенный период:
a. (60103) (Дорасчетный ТИ) – с начала дня (здесь формула, о ней ниже);
b. (60104) (Дорасчетный ТИ) – за предыдущий день;
c. (60105) (Дорасчетный ТИ) – с начала месяца;
d. (60106) (Дорасчетный ТИ) – за предыдущий месяц;
e. (60107) (Дорасчетный ТИ) – с начала года.
Теперь о формуле. В канале Ежедневного расхода написана формула (вызов) для подсчета и заполнения каналов, указанных выше:
CalcRate(60103,60104,60105,60106,60107,60100)
Текст формулы ниже:
double CalcRate(int cnl_today, int cnl_yesterday, int cnl_month, int cnl_prevmonth, int cnl_begyear, int cnl_src)
{
double cnl_sum;
DateTime nowDT = DateTime.Now;
if (DayBeg() == true)
{
if (MonthBeg() == true)
{
SetVal(cnl_prevmonth, Val(cnl_month));
if (nowDT.Month == 1 && nowDT.Day == 1)
{
SetVal(cnl_begyear, 0);
}
SetVal(cnl_month,0);
}
SetVal(cnl_yesterday, Val(cnl_today));
SetVal(cnl_month, (Val(cnl_month) + Val(cnl_today)));
SetVal(cnl_begyear, (Val(cnl_begyear) + Val(cnl_today)));
SetVal(cnl_today, 0);
}
cnl_sum = (Val(cnl_today) + Val(cnl_src)/60);
return cnl_sum;
}
Используются «штатные» DayBeg(), MonthBeg() и довольно топорное определение №начала года». Т.е. впри наступлении одного или нескольких сразу событий начала периода :
-Значение расхода за сегодня переписывается в канал «за вчера»;
-В значение «с начала месяца» добавляется «за сегодня»
— Канал «за сегодня» обнуляется.
Ну и также для начала месяца и года…
16.12.2024 в 18:00 #36192Mikhail
МодераторНужно выводить на экран среднее значение за сутки и месяц. Не скользящее среднее.
Вариант 1.
Считать среднее по тем значениям, которые хранятся в историческом архиве. Сейчас это умеет делать плагин Гибкий отчёт. Было бы полезно разработать модуль для Сервера, чтобы делал вычисления и записывал результат в канал для среднего.Вариант 2.
Считать среднее на основе получаемых текущих данных. Тогда потребуются промежуточные каналы, чтобы сохранять сумму и количество значений. Сбрасывать каналы периодически.Вам какой вариант подходит больше?
-
Этот ответ был изменен 2 месяца назад от
Mikhail.
-
Этот ответ был изменен 5 лет, 10 месяцев назад от
-
АвторСообщения
- Вы должны авторизироваться для ответа в этой теме.