PDA

Просмотр полной версии : LREAL (double float) и ПЛК100



vitiali
30.03.2011, 19:21
Как получить по Modbus и обработать данные с расходомера KROHNE на ПЛК 100?
Есть расходомер KROHNE с Modbus передает данные с накопительных счетчиков в double float.
Работал раньше с расходомером Siemens с Modbus, так он имеет альтернативу, хочешь забирай данные в double float, а хочешь в float.
Что касается ПЛК100, планирую забирать данные с помощу string input, там есть возможность выставить функцию 03 и запросить количество байт, в моем случае 8. Потом со стринг сбросить данные по указателю в LREAL. Но тут загвоздка, ПЛК100 не хочет работать с этим типом данных, ну и с функцией преобразования LREAL_TO_REAL.

Николаев Андрей
31.03.2011, 20:41
Что значит не хочет работать?

vitiali
31.03.2011, 23:00
При компилировании выдает сообщения о не поддержке LReal и ф-ии LREAL_TO_REAL. прошивка последняя официальная v.2.12.7 таргет 2.10. Может в настрйках где-нибудь галочку надо поставить

vitiali
01.04.2011, 20:11
Уточняю, при компиляции пишет Ошибка (3610) Lreal не поддерживается
И в перечне при выборе типа переменной нет LREAL. При ручном вводе XXX:LREAL; Синтаксис воспренимается нормально.

vitiali
01.04.2011, 22:03
CoDeSys_v23922 . Скачивал с сайта Овен. Настройки не менял.
Если можете, вставте в свой проект LREAL и посмотрите, что напишет.

vitiali
01.04.2011, 23:47
Я попробую. Правда немного непонял фрразу из документации ' V Treat LREAL as REAL: заставляет компилятор использовать тип REAL для LREAL объявлений'. Т.Е. заставляет компилятор использовать 32-х битный тип с плавющей запятой для 64-х битных обявленний с плавающей запятой.
Какой в ней заложен смысл?
Сколько под этот LREAL при установке галочки выделится памяти, 4байта или 8?

vitiali
02.04.2011, 10:16
IFC 300. У него на счетчиках Counter 1, Counter 2 и Counter 3 только double. Это расходомер и объем подсчитаного может быть огромный, да и сумироватся не за один месяц. И добавте точность 0.25%. Для моих задач достаточно и float, но его там нет.

При переписке с KROHNE, решал вопрос по докуметации и спросил, за одно, почему нет float. Ответили, а какие проблемы могут быть при работе с double на контроллере. Правда какой конторллер им не писал.

vitiali
02.04.2011, 11:31
http://www.krohne-downloadcenter.com/dlc/AD_IFC300_Modbus_en_100709_4000410703_R03.pdf Страница 12

vitiali
02.04.2011, 11:58
Не пробовал. Субота. Все на работе. Но чуствую будут проблемы во-первых с галочкой о которой Вы писали. Во-вторых c перестановкой слов, а затем и пар слов местами чтобы получить значение светящееся на индекаторе IFC300.

Спасибо что помогаете, но хотелось в дополнение, услышать кого-то из овен по поводу работы с LREAL

vitiali
02.04.2011, 12:14
Возьму сначала из расходомера какой нибудь флоат, стрингом. Посмотрю порядок передачи, благо флоат поддерживается. Затем буду переставлять два двойных слова если LREAL поддерживается.

vitiali
02.04.2011, 12:19
О какой точности количства продукта можно говорить если брать мгновенный расход и умножать на время.

vitiali
02.04.2011, 12:20
Чтобы знать порядок передачи слов

vitiali
02.04.2011, 12:28
для этого надо его вычислить

capzap
02.04.2011, 13:10
http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D1%80%D1%8F%D0%B4%D0%BE%D0%BA_%D0%B1% D0%B0%D0%B9%D1%82%D0%BE%D0%B2

vitiali
02.04.2011, 14:35
Мне жаль, но пока меня это волнует меньше всего.
Основной проблемой остается сама возможность работы с LREAL.
Обидно будет если разработчик скажет что в таргете надо было ремарку убрать с типа данных, а я функцию преобразования в рил напишу или изменю имеющуюся. Работать с числами LREAL имея возможность делать над ними математические операции все же приятней и происходит без потери точности. А перед отправкой на панель оператора можно и преобразовать в рил

Николаев Андрей
03.04.2011, 10:25
Господа, у кого под рукой есть прибор - ну попробуйте пожалуйста:
var
a : lreal;
end_var


a:=a+0.1;

Надо просто понять - запишется в контроллер код, и будет ли исполняться.

vitiali
03.04.2011, 15:47
Я уже писал при подобном коде
var
a : lreal;
end_var
a:=a+0.1;
при компиляции пишет Ошибка (3610) Lreal не поддерживается
И в перечне при выборе типа переменной нет LREAL. При ручном вводе
a : lreal; Синтаксис воспренимается нормально.


capzap Я сожалею о том, что нельзя работать с LREAL пока ВОБЩЕ.
Если галочка обрежет до 32 бит мои переменные которые я завел в програме то это не проблема.
Проблема в том, что я получаю с другого контроллера double float и не могу с ним работаь, а точнее обработать или привести к этим же 32 битам

vitiali
03.04.2011, 16:39
Сами по себе мне эти байты не нужны. Меня интересует то значение расхода которое они несут. А если нет возможности обработать LREAL или преобразовать LREAL TO REAL то зачем мне эти байты на ПЛК 100.

vitiali
03.04.2011, 16:41
Завтра попробую установить галочку и посмотреть сколько памяти скушает этот галочный LREAL. и какие значения там появятся. Сравню с этим http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html

vitiali
03.04.2011, 16:46
У кого есть функция преобразования double TO float c помощу сдвигов или иначе киньте пожалуйста.

swerder
04.04.2011, 10:16
cds 2.3.9.22, галочка в опциях проекта. при превышении верхней границы 3,4*e+38 переменная принимает значение = 1.#INF
без галочки компилятор выдает ошибку 3610 : LREAL не поддерживается.
так что либо как предложил capzap считывать побитно регистры приходящего lreal, либо обходиться без этого lreal

vitiali
04.04.2011, 20:28
Если бы vitiali выложил значение счетчика и значения четырех регистров, я бы попытался написать биб-ку для преобразования

По ссылкам можно получить значения регистров 32 и 64 флоат в шеснадцатиричном коде.
http://www.binaryconvert.com/convert_double.html?decimal=048
http://babbage.cs.qc.cuny.edu/IEEE-754/Decimal.html

Проверил с галочкой количество байт занимаемых LREAL. Получилось 4байта или 32 бита. Содержимое свпадает с НЕХ в выше приведенных ссылках для 32 битного флоат.

ПЛК100 НЕ РАБОТАЕТ С LREAL(IEEE754 Double precision 64-bit) или разработчики думают иначе?

vitiali
05.04.2011, 19:32
Пока поддержка овен молчит, я написал кое-какой код для перевода строки содержащей LREAL байты в REAL.
Если кто знает как вкинуть побитно DWORD в переменую REAL напишите. не в язике СИ, а в ST (Codesys).
DWORD у меня сформатирован как REAL (со знаком экспонентой и мантисой).

FUNCTION_BLOCK STR_d_real
VAR_INPUT
str_d:STRING;
swap:BOOL;
END_VAR
VAR_OUTPUT
d_to_f : REAL; (*преобразование дабл флоат в флоат на ПЛК100 принятых через порт *)
nnn:REAL; (*для альтернативного способа*)
END_VAR
VAR
str:POINTER TO BYTE;
b: ARRAY[1..8]OF BYTE;
mant:DWORD; (*Мантиса числа REAL *)
help1:DWORD;(*Вспомогательная переменнаяч*)
i:BYTE;(*счет для цикла*)
expon:DWORD;
FL:POINTER TO REAL;
DW:POINTER TO DWORD;
eexxpp:DWORD; (*для альтернативного способа*)
END_VAR

str:=ADR(str_d);
(*swap устанавливается в 1 или снимается в зависимости от порядка передачи другого контроллера*)
IF swap=1 THEN (*Формируем масив с определенной последовательностью байт*)
i:=8;
WHILE i<>0 DO (*если требуется начинать с большего и по убыванию *)
b[i]:=str^;
str:=str+1;
i:=i-1;
END_WHILE
ELSE (*если требуется только перестановка местами слов*)
FOR i:=2 TO 8 BY 2 DO
b[i]:=str^;
str:=str+1;
b[i-1]:=str^;
str:=str+1;
END_FOR
END_IF
mant:=0;
expon:=0;
help1:=(b[7] AND 16#0F) ; (*Определяем мантису*)
help1:=SHL(help1,19);
mant:= mant OR help1;
help1:=b[6];
help1:=SHL(help1,11);
mant:= mant OR help1;
help1:=b[5];
help1:=SHL(help1,3);
mant:= mant OR help1;
help1:=(b[4] AND 16#F0);
help1:=SHR(help1,5);
mant:= mant OR help1; (*Определили мантису*)

help1:=(b[7] AND 16#F0); (*определяем экспоненту *)
help1:=SHR(help1,4);
expon:=expon OR help1;
help1:=(b[8] AND 16#7F);
help1:=SHL(help1,4);
expon:=expon OR help1;
expon:=expon-1023;
eexxpp:=expon; (*для альтернативного способа*)
expon:=expon+127;
expon:=SHL(expon,23); (*определили экспоненту *)

help1:=(b[8] AND 16#80); (*определяем знак*)
help1:=SHL(help1,24); (*определяем знак*)

help1:= help1 OR expon OR mant ; (*Собрали все вместе. здесь находится 32 битное число. Если его побитно запихнуть в REAL то получем преобразование LREAL TO REAL*)

DW:=ADR(help1); (*здесь не могу все правильно собраные биты запихнуть в REAL *)
d_to_f :=DW^; (*здесь не могу все правильно собраные биты запихнуть в REAL *)

nnn:=(EXPT(2, eexxpp))*(mant/8388607.0+1.0); (*Альтернативный способ*)

vitiali
06.04.2011, 20:35
Законченый и провереный вариант кода для преобразования байт содержащих LREAL и полученых через порт от расходомера в REAL. Исходя из особенностей ПЛК100, 8-мь байт собираются в строку при приеме через порт. Разработчикам которые работают с расходомерами или теплосчетчиками, с большими расходами советовал бы оценить достаточно ли им разрешающей способности REAL и если нет взять другой контроллер работающий с LREAL. Сapzap спасибо за подсказки.

FUNCTION StDR_to_R : REAL (*преобразование дабл флоат в флоат на ПЛК100 принятых через порт *)
VAR_INPUT
str_d:STRING;
swap:BOOL;
END_VAR
VAR
str:POINTER TO BYTE;
b: ARRAY[1..8]OF BYTE;
mant:DWORD; (*Мантиса числа REAL *)
help1:DWORD;(*Вспомогательная переменнаяч*)
i:BYTE;(*счет для цикла*)
expon:DWORD;
FL:POINTER TO REAL; (*для копирования DWORD в REAL *)
END_VAR
str:=ADR(str_d);
(*swap устанавливается в 1 или снимается в зависимости от порядка передачи другого контроллера*)
IF swap=1 THEN (*Формируем масив с определенной последовательностью байт*)
i:=8;
WHILE i<>0 DO (*если требуется начинать с большего и по убыванию *)
b[i]:=str^;
str:=str+1;
i:=i-1;
END_WHILE
ELSE (*если требуется только перестановка местами слов*)
FOR i:=2 TO 8 BY 2 DO
b[i]:=str^;
str:=str+1;
b[i-1]:=str^;
str:=str+1;
END_FOR
END_IF
mant:=0;
expon:=0;
help1:=0;
help1:=(b[7] AND 16#0F) ; (*Определили мантису*)
help1:=SHL(help1,19);
mant:= mant OR help1;
help1:=b[6];
help1:=SHL(help1,11);
mant:= mant OR help1;
help1:=b[5];
help1:=SHL(help1,3);
mant:= mant OR help1;
help1:=(b[4] AND 16#F0);
help1:=SHR(help1,5);
mant:= mant OR help1; (*Определили мантису*)

help1:=(b[7] AND 16#F0); (*определяем экспоненту*)
help1:=SHR(help1,4);
expon:=expon OR help1;
help1:=(b[8] AND 16#7F);
help1:=SHL(help1,4);
expon:=expon OR help1;
IF mant>0 THEN (*чтобы при нулевой мантисе не вылизло какое-нибудь число*)
expon:=expon-1023;
expon:=expon+127; (*если мантиса больше 0 экспон. приймет значения *)
END_IF
expon:=SHL(expon,23); (*определяем экспоненту*)

help1:=(b[8] AND 16#80); (*определяем знак*)
help1:=SHL(help1,24); (*определяем знак*)

help1:= help1 OR expon OR mant ; (*Собрали все вместе. здесь находится 32 битное число. Если его побитно запихнуть в REAL то получем преобразование LREAL TO REAL*)

FL:=ADR(help1);
StDR_to_R :=FL^; (*здесь копирую побитно в REAL *)

GoodLuck
12.07.2017, 09:31
Подскажите, пожалуйста. Что-то я туплю...

Есть 8 байт, которые необходимо преобразовать в LREAL.
Вот так все работает замечательно:

p1:=ADR(otvet[18]); p:=ADR(L); p^:=p1^;
p1:=ADR(otvet[17]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[16]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[15]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[14]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[13]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[12]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[11]); p:=p+1; p^:=p1^;


Но мне надо сначала из 8 байт сформировать 2 DWORD'а, которые потом преобразовывать в LREAL.
Делаю так:
p1:=ADR(otvet[14]); p:=ADR(dw1); p^:=p1^;
p1:=ADR(otvet[13]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[12]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[11]); p:=p+1; p^:=p1^;

p1:=ADR(otvet[18]); p:=ADR(dw2); p^:=p1^;
p1:=ADR(otvet[17]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[16]); p:=p+1; p^:=p1^;
p1:=ADR(otvet[15]); p:=p+1; p^:=p1^;

Далее, собираю LREAL.
L3:=TwoDWord_TO_LREAL(IN_Data1:= dw1 , IN_Data2:= dw2);

В результате, необходимое число не получается.