Код:
FUNCTION_BLOCK flow
(*
Для обычных импульсных счетчиков с частотой < 50..100Гц.
Для вменяемых пользователей с рабочим циклом 0..3мс (Гражданин помни : эмуляция - десятки мс)
(C) Валенок, апрель 2014
Люблю печенки
*)
VAR_INPUT
impulse : BOOL;
tmax : TIME; (*для обрыва асимптоты. Больше время - выше чуйствительность, но хуже ловля закрытия кранчиков*)
k : REAL; (*л/имп*)
END_VAR
VAR_OUTPUT
q : REAL; (*м3/ч*)
END_VAR
VAR_IN_OUT
liters : DWORD; (*наработка целых литров, из внешнего ретайна*)
END_VAR
VAR
fix : R_TRIG; (*ловим кокой-нить фронт импульса*)
period, (*последний законченный межимпульсный интервал*)
peri, (*текущий незаконч..*)
t : TIME; (*временная отметка*)
c : BYTE; (*на подумать самому*)
rem : REAL; (*k - real, liters - dword, нам пох*)
END_VAR
(*порядок выполнения выделенных групп особого значения не имеет*)
peri := TIME() - t;
c := SEL(peri > tmax, c, 0); (*самореинициализация, если чо*)
fix(clk := impulse);
IF fix.q THEN
period := peri;
t := TIME();
c := MIN(2,c + 1);
rem := rem + k;
liters := liters + REAL_TO_DWORD(rem); (*расчет редкий, промежуточное сохранение не нужно*)
rem := rem - REAL_TO_DWORD(rem);
END_IF
IF c = 2 THEN
IF peri >= period THEN
q := k * 3600 / TIME_TO_DWORD(peri); (*расчет делается только по необходимости - импульс и асимптота*)
END_IF
ELSE
q := 0;
END_IF