А действительно, почему их должны волновать проблемы ПР (индейцев), если это оборудование не предназначено для подобного.
Смотреть нет ни времени, ни желания.
Прочитать 4 регистра как Инты, выбрать целую часть, на остальное положить.
А действительно, почему их должны волновать проблемы ПР (индейцев), если это оборудование не предназначено для подобного.
Смотреть нет ни времени, ни желания.
Прочитать 4 регистра как Инты, выбрать целую часть, на остальное положить.
100 тоже нет, там нет LReal.
Поддерживают scada в полном объеме, на что вероятно и был расчет. Прибор как средство измерения, а не управления все таки.
Я что-то нить упустил, нафига в пр данные от расходомера? Принять какое-то решение и включить реле?
Поставить шлюзом scada туда же в котельную. Будет и средство мониторинга и выполнит необходимую задачу, будет распределять нагрузку на котлы.
Выйдет дешевле, чем напрягать мозги. Насколько ронимаю, в ST для ПР формат double не завезли, и завезут ли?
Последний раз редактировалось melky; 21.09.2025 в 23:51.
Добрый день.
DOUBLE (LREAL) в ПР и в ПЛК1хх не поддерживается.
Если прочитать из устройства число DOUBLE как два отдельных DWORD, то в ПР можно на языке ST написать функцию конвертации в REAL. Понятно, что точность будет потеряна.
Пример для числа Пи:
в DOUBLE = 3.141592653589793
в HEX = 0x400921fb54442d18
старший DWORD в десятичном виде = 1074340347
младший DWORD в десятичном виде = 1413754136
результат в REAL = 3,1415927
f10.PNG
В real (float) вроде даже целая часть меньше чем у Инта, это только если расход попадает в диапазон, тогда наверное можно кастрировать.
Приложил.
Для тестов удобно использовать конвертер https://gregstoll.com/~gregstoll/floattohex/
FUNCTION DOUBLE_TO_REAL : REAL;
VAR_INPUT
dwHigh: UDINT;
dwLow: UDINT;
END_VAR
VAR
rSign, rExponent, rMantissa: REAL;
udiExp: UDINT;
udiMantissa: UDINT;
END_VAR
//Знак (бит 63)
rSign := 1.0;
IF dwHigh >= 2147483648 THEN
rSign := -1.0;
END_IF;
//Экспонента (биты 62-52)
// / 1048576 - сдвигаем на 20 бит вправо (1048576 = 2^20)
// MOD 2048 - берём младшие 11 бит экспоненты (2048 = 2^11)
udiExp := (dwHigh / 1048576) MOD 2048;
//Мантисса
// MOD 1048576 - берём старшие 20 бит мантиссы (1048576 = 2^20)
udiMantissa := dwHigh MOD 1048576;
// Cтаршие 20 бит мантиссы: биты 51-32
rMantissa := 1.0 + UDINT_TO_REAL(udiMantissa) / 1048576.0; // Делим на 2^20
// Младшие 32 бита: биты 31-0
rMantissa := rMantissa + UDINT_TO_REAL(dwLow) / 4503599627370496.0; // Делим на 2^52
rExponent := POW(2.0, UDINT_TO_REAL(udiExp) - 1023.0);
DOUBLE_TO_REAL := rSign * rExponent * rMantissa;
END_FUNCTION
Последний раз редактировалось kondor3000; 23.09.2025 в 17:55.
Может что-то типа такого?
Только мне толком проверить не на чем, поскольку у меня REAL - это double. Но, по сравнению с 52-битной мантиссой разница в 6-ом разряде после запятой начинается.Код:REAL FUNCTION get_dred_var(INT w1, INT w2, INT w3, INT w4) REAL rval; INT eval; INT SignBit; eval=(w4 BITAND 32752)/16; SignBit = w4 BITAND Pow(2,15); rval = (1 + ((w4 BITAND 15)*(Pow(2,28)) + w3*(Pow(2,12)) + w2)/Pow(2,32))* Pow(2, eval-1023); IF SignBit = 0 THEN RETURN rval; ELSE RETURN -rval; END; END
Так, пожалуй, правильнее. До 8-го знака совпадение.Код:rval = (1 + ((w4 BITAND 15)*(Pow(2,28)) + w3*(Pow(2,12)) + w2/16)/Pow(2,32))* Pow(2, eval-1023);