Бетар СХВ-15д
Вид для печати
Подобная задача в ОЛ решается элементарно:
http://www.owen.ru/forum/showthread.php?t=22608&page=4
Вложение 21688
http://www.owen.ru/forum/showthread.php?t=22511
CFC на сколько знаю, мало отличается от ОЛ, но если решите это сделать на ПР, буду рад помочь, вернее всё уже придумано, просто останется выбрать, что Вам больше понравится!
И что считает эта схема? Без каких-то личных претензий, но как применить ваш пример для "среднего расхода за последние сутки" как-то неясно.
Если я правильно прочитал вашу схему, то вы считаете "общее количество импульсов/общее время". Верно?
Такой подход будет работать только при постоянной скорости. Если же расход меняется со временем, то ваш алгоритм будет показывать погоду.
Если что, то я выше экспоненциальное сглаживание для ПЛК выложил. Оно адаптируется к изменяющимся скоростям.
И кода там 15 строк. Открываем статью в Wikipedia, сверяем алгоритм. На всякий пожарный проверяем в симуляции.
Наверное, это можно переделать в CFC или даже ПР, но, на мой взгляд, на ST нагляднее (да и сравнить с оригиналом в wikipedia проще).
Код:PROGRAM averages
(* https://en.wikipedia.org/wiki/Exponential_smoothing#Basic_exponential_smoothing *)
VAR CONSTANT
sampling_interval: REAL := 10; (* seconds, should be equal to interval in task configuration *)
END_VAR
VAR_OUTPUT
last1m: REAL;
last1h: REAL;
last1d: REAL;
END_VAR
VAR
a1m: REAL;
a1h: REAL;
a1d: REAL;
prevCnt: INT;
delta: REAL;
END_VAR
delta := (PLC_PRG.CV - prevCnt)/sampling_interval; (* current flow ITEMS PER SECOND *)
prevCnt := PLC_PRG.CV; (* <-- интересно, тут может возникнуть ошибка из-за того, что мы 2 раза читаем переменную PLC_PRG.CV ? *)
a1m := 1-EXP(-sampling_interval/60); (* можно вычислить заранее и прямо константой забить *)
a1h := 1-EXP(-sampling_interval/3600);
a1d := 1-EXP(-sampling_interval/86400);
last1m := a1m*delta + (1-a1m)*last1m;
last1h := a1h*delta + (1-a1h)*last1h;
last1d := a1d*delta + (1-a1d)*last1d;
Код:PROGRAM PLC_PRG
VAR_INPUT
inp: BOOL;
END_VAR
VAR_OUTPUT
CV: INT;
END_VAR
VAR
cntr: CTU;
END_VAR
cntr(CU := inp); (* тут просто считаем импульсы *)
CV := cntr.CV;
Если сглаженное значение нужно довольно часто (например, раз в секунду-две-три), то можно сделать без "отдельных программ для усреднения".
Нужно всего несколько строк и одна переменная, в которой будет хранится усреднённое значение -- avg_period:
Вот пример, как оно может выглядеть: https://docs.google.com/spreadsheets...it?usp=sharingКод:period := new-old; (* т.е. время, прошедшее с прошлого раза, в миллисекундах *)
a := 1.0 - EXP(-period / 200.0); (* тут 200.0 мс это как раз период усреднения -- его можно менять *)
avg_period := a*Period + (1.0-a)*avg_period; (* тут накапливается усреднение *)
rate := 1000/avg_period; (* Результат, "оборотов в секунду". Что выводить в случае "деления на ноль" предлагаю рассмотреть отдельно *)
Видно, что при увеличении константы результат сглаживания меняется более плавно, но медленнее.
Если характерная частота -- 5-20Гц, то, судя по графику, значение 200 должно неплохо работать. За секунду-полторы оно "выходит на режим", и потом несильно колбасится.
Сбрасываешь по каждому импульсу со счётчика - текущий расход, раз в час - часовой, раз в сутки - суточный, при этом до сброса показывает расход за преведущий интервал времени, разумеется потребуется три экземпляра, чтобы это одновременно отображать! И расход будет средний за период с соответствующим периодом обновления!
С этого и начинали.
Сразу после сброса цифры будут плавать.
Вот пример где "ругаются" на то, что "первое время после сброса цифры плавают": http://www.owen.ru/forum/showthread.php?t=18573
И неужели добавленные сбросы упростят программу?
Или, может, упростят поддержку?
Или, может, ещё что-то?
Ну троллить-то зачем?
Взрослые люди же.
last1m -- "мгновенный расход"
last1h -- "усреднённое за час"
last1d -- "усреднённое за сутки"
В начале темы говорилось, что на конкретном объекте счётчик выдаёт 1 импульс в 10 секунд.
Я из этого и решил, что "мгновенным показателем" в данном конкретном случае будет "усреднение за минуту".
Ваши предложения? :)
В конце концов, поменять период усреднения тут проще простого, и сделать "среднее за 5 секунд" тут раз плюнуть.
Надеюсь, не нужно рассказывать, что способа вычислить "частоту" импульсов без усреднений вообще не бывает?
Ах, да, есть способ, когда частота просто "дана свыше" и мы просто выводим на экран заложенное заранее значение. Но
Цитата:
взрослые люди же.