- Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
- Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
- Не писать свой вопрос в первую попавшуюся тему - вместо этого создать новую тему.
- За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения.
- Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
- Перед тем как что-то написать - читать здесь и здесь, а студентам - обязательно здесь.
- Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.
расчет усредненного значения влажности за час, сутки, месяц
-
- здесь недавно
- Сообщения: 16
- Зарегистрирован: 12 окт 2018, 08:31
- Имя: Александр
- Страна: Россия
- город/регион: Магадан
расчет усредненного значения влажности за час, сутки, месяц
Здравствуйте уважаемые форумчане, нужна помощь. На предприятии используем датчик влажности, который посылает мгновенное значение влажности, руководство озадачило выводом усредненного значения влажности за последний час, за неделю и за месяц. Работаю в TiaPortal V14 , еще не совсем освоил работу с программой. Буду благодарен за помощь, может есть у кого пример программы, желательно STL.
Спасибо.
Спасибо.
-
- здесь недавно
- Сообщения: 40
- Зарегистрирован: 05 ноя 2017, 01:12
- Имя: Александр
- Страна: Россия
- город/регион: Хабаровск
- Благодарил (а): 3 раза
- Поблагодарили: 3 раза
расчет усредненного значения влажности за час, сутки, месяц
Данные которые получает контроллер куда выводятся? Допустим если используется WinCC то в TagLogging есть возможность усреднения значений при логировании, либо это позволяет сделать небольшой скрипт если требуются прямо точные временные рамки.
-
- здесь недавно
- Сообщения: 16
- Зарегистрирован: 12 окт 2018, 08:31
- Имя: Александр
- Страна: Россия
- город/регион: Магадан
расчет усредненного значения влажности за час, сутки, месяц
Данные с контроллера выводятся на панель TP700, просто не могу сообразить как сделать накопительное значение влажности в контроллере, либо на панеле, за определенное время. Соответственно потом можно вывести среднее значение. Может полелитесь примером скрипта или кодом программы, который реализует такие функции. Спасибо:)
-
- осмотрелся
- Сообщения: 166
- Зарегистрирован: 24 янв 2018, 11:18
- Имя: Антон
- Страна: Россия
- город/регион: Калининград
- Благодарил (а): 26 раз
- Поблагодарили: 27 раз
расчет усредненного значения влажности за час, сутки, месяц
Klerik88, ну если в общем, то алгоритм такой:
1. Создайте хранилище массива значений: это может быть обычный Global DB нужной длины.
2. Создайте функцию, которая делает приблизительно следующее:
- запись текущего значения в элемент массива
- подсчет среднего арифметического всех элементов массива
- переход к следующему элементу массива
Для написания кода (или адаптации готового кода) вам потребуется хотя бы базовое понимание следующих тем:
- косвенная адресация
- указатели
- циклы LOOP
ИМХО в PLC имеет смысл вести расчет средних значений за период +/- несколько часов максимум.
Расчет статистики за день/неделю/месяц это задача систем верхнего уровня, сервера производственных архивов, например.
1. Создайте хранилище массива значений: это может быть обычный Global DB нужной длины.
2. Создайте функцию, которая делает приблизительно следующее:
- запись текущего значения в элемент массива
- подсчет среднего арифметического всех элементов массива
- переход к следующему элементу массива
Для написания кода (или адаптации готового кода) вам потребуется хотя бы базовое понимание следующих тем:
- косвенная адресация
- указатели
- циклы LOOP
ИМХО в PLC имеет смысл вести расчет средних значений за период +/- несколько часов максимум.
Расчет статистики за день/неделю/месяц это задача систем верхнего уровня, сервера производственных архивов, например.
-
- здесь недавно
- Сообщения: 16
- Зарегистрирован: 12 окт 2018, 08:31
- Имя: Александр
- Страна: Россия
- город/регион: Магадан
-
- эксперт
- Сообщения: 1626
- Зарегистрирован: 06 янв 2016, 19:45
- Имя: Петров В.Л.
- Страна: Россия
- город/регион: Красноярск
- Благодарил (а): 70 раз
- Поблагодарили: 191 раз
расчет усредненного значения влажности за час, сутки, месяц
Можно и без массива, если использовать рекуррентную формулу для среднего
Sn = Sn-1 X (N-1)/N + Xn/N
Sn = Sn-1 X (N-1)/N + Xn/N
-
- здесь недавно
- Сообщения: 16
- Зарегистрирован: 12 окт 2018, 08:31
- Имя: Александр
- Страна: Россия
- город/регион: Магадан
расчет усредненного значения влажности за час, сутки, месяц
Спасибо, Вы не могли бы привести пример кода как использовать данную функцию, я что то не могу сообразить. Я совсем недавно столкнулся с tiaportal.
-
- эксперт
- Сообщения: 1626
- Зарегистрирован: 06 янв 2016, 19:45
- Имя: Петров В.Л.
- Страна: Россия
- город/регион: Красноярск
- Благодарил (а): 70 раз
- Поблагодарили: 191 раз
расчет усредненного значения влажности за час, сутки, месяц
Как вариант так.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
-
- здесь недавно
- Сообщения: 16
- Зарегистрирован: 12 окт 2018, 08:31
- Имя: Александр
- Страна: Россия
- город/регион: Магадан
-
- освоился
- Сообщения: 282
- Зарегистрирован: 14 фев 2014, 11:55
- Имя: Николай
- Страна: Россия
- Благодарил (а): 9 раз
- Поблагодарили: 64 раза
расчет усредненного значения влажности за час, сутки, месяц
Дарю свой функциональный блок. Считает среднее квадратическое (для большинства случаев показывает лучший результат, чем среднее арифметическое). Учитывает знак, т.е. отрицательные числа тоже считает корректно.
FUNCTION_BLOCK "SQRT_Averaging"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
new_item : Real;
Front : bool; // фронт 1 раз в 100 мс
END_VAR
VAR
curr_count : Int; // текущее кол-во элементов
"time" : Int := 1; // период добавления нового элемента [дс]
"counter" : Int; // счётчик времени
value : Real;
summ : Real;
index : Int;
items : Array[0..9] of Real;
isUseAverage : Bool; // включает/отключает фильтрацию
END_VAR
VAR_TEMP
i : Int;
koef : Real;
END_VAR
BEGIN
IF(#new_item = 999.0 OR #isUseAverage = false) THEN // условно считается, что 999.0 - неправильное показание при обрыве датчика
#curr_count := 0;
#counter := 0;
#value := #new_item;
#summ := 0.0;
#index := 0;
FOR #i := 0 TO 9 BY 1 DO
#items[#i] := 0.0;
END_FOR;
RETURN;
END_IF;
//----------------------------------------------
IF(#new_item >= 0.0) THEN #koef := 1.0;
ELSE #koef := -1.0;
END_IF;
//----------------------------------------------
IF(#Front) THEN
#counter := #counter + 1;
ELSE
RETURN;
END_IF;
IF(#counter >= #time) THEN // если счётчик досчитал
#counter := 0; // сбросить счётчик
IF(#curr_count < 10) THEN // если тек. кол-во элементов еще не достигло заданного
IF(#curr_count <> 0) THEN
#index := #index + 1;
END_IF;
#curr_count := #curr_count + 1; // увеличить тек. кол-во элементов
ELSE // если тек. кол-во элементов равно 10
IF(#index = 9) THEN
#index := 0;
ELSE
#index := #index + 1;
END_IF;
END_IF;
#items[#index] := SQR(IN := #new_item) * #koef; // заменить текущий элемент ^ 2 на новый ^ 2 (с сохранением знака)
FOR #i := 0 TO 9 BY 1 DO
IF(#i = 0) THEN
#summ := 0;
END_IF;
#summ := #summ + #items[#i]; // перерасчёт суммы
END_FOR;
IF(#curr_count >= 2) THEN
IF(#summ >= 0.0) THEN #koef := 1.0;
ELSE #koef := -1.0;
END_IF;
#value := SQRT(IN := ABS(#summ / #curr_count)) * #koef; // расчёт нового выходного значения (с сохранением знака)
ELSE #value := #new_item;
END_IF;
END_IF;
END_FUNCTION_BLOCK
Моя функция рассчитана лишь на 10 значений, поскольку для моих задач надо усреднять значение максимум за 2 - 3 секунды. Функция требует внешней переменной #Front, которая = 1 один раз в 100 мс. Суть в том, что вы сами решаете (переменная #time), как часто будут добавляться новые значения в массив. На основании этого можете рассчитать, за какой период времени будете получать среднее значение. Например, если надо получить среднее за две секунды, то #time должно быть равно 2, т.е. будет происходить добавление нового значения в массив каждые 2x100 = 200 мс.
Если надо усреднять часы и дни, то можно период фронта (#Front) использовать не 100 мс, а бóльший, поскольку очевидно, что точность до 0.1 сек в таком случае не нужна. Касательно массива, то можно его раздуть, сделав не 10, а бóльшее количество значений. Хотя я бы не стал сильно увлекаться таким нерациональным использованием памяти ПЛК, я бы лучше сделал расчет рекурсивным. Т.е. можно создать экземплярный DB, который будет считать среднее за 1 минуту, а уже его значения отправлять в другой DB, который будет считать среднее за 1 час, далее его значения отправлять в DB, где считается среднее за неделю, а уже его показания - в DB, который будет считать за месяц. Как-то так.
FUNCTION_BLOCK "SQRT_Averaging"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
new_item : Real;
Front : bool; // фронт 1 раз в 100 мс
END_VAR
VAR
curr_count : Int; // текущее кол-во элементов
"time" : Int := 1; // период добавления нового элемента [дс]
"counter" : Int; // счётчик времени
value : Real;
summ : Real;
index : Int;
items : Array[0..9] of Real;
isUseAverage : Bool; // включает/отключает фильтрацию
END_VAR
VAR_TEMP
i : Int;
koef : Real;
END_VAR
BEGIN
IF(#new_item = 999.0 OR #isUseAverage = false) THEN // условно считается, что 999.0 - неправильное показание при обрыве датчика
#curr_count := 0;
#counter := 0;
#value := #new_item;
#summ := 0.0;
#index := 0;
FOR #i := 0 TO 9 BY 1 DO
#items[#i] := 0.0;
END_FOR;
RETURN;
END_IF;
//----------------------------------------------
IF(#new_item >= 0.0) THEN #koef := 1.0;
ELSE #koef := -1.0;
END_IF;
//----------------------------------------------
IF(#Front) THEN
#counter := #counter + 1;
ELSE
RETURN;
END_IF;
IF(#counter >= #time) THEN // если счётчик досчитал
#counter := 0; // сбросить счётчик
IF(#curr_count < 10) THEN // если тек. кол-во элементов еще не достигло заданного
IF(#curr_count <> 0) THEN
#index := #index + 1;
END_IF;
#curr_count := #curr_count + 1; // увеличить тек. кол-во элементов
ELSE // если тек. кол-во элементов равно 10
IF(#index = 9) THEN
#index := 0;
ELSE
#index := #index + 1;
END_IF;
END_IF;
#items[#index] := SQR(IN := #new_item) * #koef; // заменить текущий элемент ^ 2 на новый ^ 2 (с сохранением знака)
FOR #i := 0 TO 9 BY 1 DO
IF(#i = 0) THEN
#summ := 0;
END_IF;
#summ := #summ + #items[#i]; // перерасчёт суммы
END_FOR;
IF(#curr_count >= 2) THEN
IF(#summ >= 0.0) THEN #koef := 1.0;
ELSE #koef := -1.0;
END_IF;
#value := SQRT(IN := ABS(#summ / #curr_count)) * #koef; // расчёт нового выходного значения (с сохранением знака)
ELSE #value := #new_item;
END_IF;
END_IF;
END_FUNCTION_BLOCK
Моя функция рассчитана лишь на 10 значений, поскольку для моих задач надо усреднять значение максимум за 2 - 3 секунды. Функция требует внешней переменной #Front, которая = 1 один раз в 100 мс. Суть в том, что вы сами решаете (переменная #time), как часто будут добавляться новые значения в массив. На основании этого можете рассчитать, за какой период времени будете получать среднее значение. Например, если надо получить среднее за две секунды, то #time должно быть равно 2, т.е. будет происходить добавление нового значения в массив каждые 2x100 = 200 мс.
Если надо усреднять часы и дни, то можно период фронта (#Front) использовать не 100 мс, а бóльший, поскольку очевидно, что точность до 0.1 сек в таком случае не нужна. Касательно массива, то можно его раздуть, сделав не 10, а бóльшее количество значений. Хотя я бы не стал сильно увлекаться таким нерациональным использованием памяти ПЛК, я бы лучше сделал расчет рекурсивным. Т.е. можно создать экземплярный DB, который будет считать среднее за 1 минуту, а уже его значения отправлять в другой DB, который будет считать среднее за 1 час, далее его значения отправлять в DB, где считается среднее за неделю, а уже его показания - в DB, который будет считать за месяц. Как-то так.
-
- здесь недавно
- Сообщения: 16
- Зарегистрирован: 12 окт 2018, 08:31
- Имя: Александр
- Страна: Россия
- город/регион: Магадан