По просьбе наших посетителей, данный материал перенесен с сайта plc4good.org.ua, в связи с полной его потерей. Всё возражения принимаются через форму обратной связи.
plc4good.org.ua/view_post.php?id=222
Работая в контроллере с числами в формате REAL, выход обрабатываемых данных за допустимый диапазон – это не единственная неприятность которая может произойти.
Хорошая традиция проверять данные перед использованием, особенно если они получены от соседних систем.
Update: после правки совпали контрольные суммы у базового варианта.
Добавлен вариант проверки из комментария.
Имея жестко описанную (стандарт IEEE 754) структуру, в вычислениях могут использоваться только нормализованные числа.
Рассмотренная функция позволяет определить вид проверяемого числа:
– нормализованное (нет ошибки)
– бесконечность
– денормализованное
– не число (NaN)
Вспомним как устроены числа типа REAL.
Структура числа
Диапазоны
Функция входит в библиотеку BASIS LIBRARY V8.0 пакета PCS 7
Описание блока в Function Manual
Name: FC260
Symbolic Name: ChkREAL
Symbol Comment: Check infinite values
Family: @SYSTEM
Version: 5.0
Author: DRIVER80
Last modified: 02/08/2011
{
Scl_ResetOptions ,
Scl_OverwriteBlocks:= ‘y’ ,
Scl_GenerateReferenceData := ‘y’ ,
Scl_S7ServerActive:= ‘n’ ,
Scl_CreateObjectCode:= ‘y’ ,
Scl_OptimizeObjectCode:= ‘y’ ,
Scl_MonitorArrayLimits:= ‘n’ ,
Scl_CreateDebugInfo := ‘n’ ,
Scl_SetOKFlag:= ‘n’ ,
Scl_SetMaximumStringLength:= ‘254’
}
FUNCTION FC1260 : REAL
TITLE =‘Check infinite values’
AUTHOR : DRIVER80
FAMILY : ‘@SYSTEM’
NAME : ChkREAL
VERSION : ‘5.0’
//reversedVAR_INPUT
In : REAL, //The real value to be checked
END_VAR
VAR_OUTPUT
ErrNum : INT, //error number: 0=no error/1=infinity/2=denormal/3=NaN
END_VAR
VAR_TEMP
theREAL : REAL,
theREAL_dw AT theREAL : DWORD,
exponent : DWORD, //Bit 23 – 30,
fraction_1 : DWORD, //Bit 22, most significant bit
fraction_2 : DWORD, //Bit 0 – 21
END_VAR
BEGINErrNum:=0,
theREAL:=In,
exponent:=theREAL_dw AND DW#16#7F800000,
fraction_1:=theREAL_dw AND DW#16#400000,
fraction_2:=theREAL_dw AND DW#16#3FFFFF,
FC1260:=theREAL,IF exponent = DW#16#7F800000
THEN
IF (fraction_1<,>,DW#16#0) OR ((fraction_1 = DW#16#0) AND (fraction_2 <,>, DW#16#0))
THEN
ErrNum:=3, //3=NaN
OK:=false,
ELSIF (fraction_1 = DW#16#0) AND (fraction_2 = DW#16#0)
THEN
ErrNum:=1, //1=infinity
IF theREAL >, 0.000000e+000 THEN FC1260:=3.402822e+038, ELSE FC1260:=-3.402822e+038, END_IF,
END_IF,
ELSIF (exponent = DW#16#0) AND ((fraction_1 <,>, DW#16#0) OR (fraction_2 <,>, DW#16#0))
THEN
ErrNum:=2, //2=denormal
FC1260:=0.000000e+000,
END_IF,END_FUNCTION
Block checksum оригинального и восстановленного блока совпадает.
Пример использования:
Ti:=ChkREAL(In :=Ti,ErrNum :=nTiErr), // check if time is good number
IF nTiErr = 1 OR nTiErr = 3 THEN ErrorNum:=33, ELSE ErrorNum:=0, END_IF,
Альтернативный вариант от Василия:
FUNCTION_BLOCK FB32 //Фильтр NaN и Inf для чисел REAL.
TITLE = ‘Фильтр NaN Inf’,VAR_INPUT //Входные переменные, сохраняемые.
X:REAL:=0.0, //Вход.
END_VARVAR_OUTPUT //Выходные переменные, сохраняемые.
Y:REAL:=0.0, //Выход.
END_VAR//Алгоритм.
//Если Y=(NaN или Inf или -Inf) то Y=0 иначе Y=X.
//DW#16#7F800000=DW#2#01111111_10000000_00000000_00000000
//Стандарт IEEE 754.
IF ((REAL_TO_DWORD(X) AND DW#16#7F800000) = DW#16#7F800000) THEN
Y:=0.0,
ELSE
Y:=X,
END_IF,END_FUNCTION_BLOCK
И еще два ‘бюджетных’ варианта, выведенных из предложенного в комментариях,
для тех кто не любит лишних блоков в проекте.
Комментарии к материалу
Добавлен: Василий Дата: 2016-06-29
Предлагаю альтернативный вариант. Менее функциональный но более удобный и тестированный.
Эффективно борется с NaN и Inf.
FUNCTION_BLOCK FB32 //Фильтр NaN и Inf для чисел REAL.
TITLE = ‘Фильтр NaN Inf’,
VAR_INPUT //Входные переменные, сохраняемые.
X:REAL:=0.0, //Вход.
END_VAR
VAR_OUTPUT //Выходные переменные, сохраняемые.
Y:REAL:=0.0, //Выход.
END_VAR
//Алгоритм.
//Если Y=(NaN или Inf или -Inf) то Y=0 иначе Y=X.
//DW#16#7F800000=DW#2#01111111_10000000_00000000_00000000
//Стандарт IEEE 754.
IF ((REAL_TO_DWORD(X) AND DW#16#7F800000) = DW#16#7F800000)
THEN
Y:=0.0,
ELSE
Y:=X,
END_IF,
END_FUNCTION_BLOCK
Добавлен: komatic Дата: 2016-06-30
Спасибо за вариант. Добавил его в материал.
Оцените статью!