Я совсем запутался в приеме значений REAL с МВ110-8А, я опрашиваю модуль через библиотеку ModulsOwenLib, из него получаем значение в REAL, что требуется сделать дальше? В примере на форуме не смог до конца разобраться.
Вид для печати
Я совсем запутался в приеме значений REAL с МВ110-8А, я опрашиваю модуль через библиотеку ModulsOwenLib, из него получаем значение в REAL, что требуется сделать дальше? В примере на форуме не смог до конца разобраться.
Делите два ворда на байты и лепите из них четыре комбинации и через указатель впревращаете в реал, обычно начинают с "зеркальной" комбинации
Я не понимаю, от избытка инофрмации у меня каша в голове, у меня есть REAL, что с ним дальше делать, объясните на пальцах пож-та.
тогда считывайте в формате WORD.
Там ничего делать не нужно, только в конфигураторе укажите количество знаков после запятой.
В конфигураторе непосредственно модуля?
:) есди на пальцах разжевать, то сперва свой неправильный реал через указатель превращаете в дворд, из него с помощью shr/shl и маски получаются либо два ворда либо четыре байта, перемешав их местами собираете обратно и скармливаете указателю на реал,потом получаете нужно значение
Можете привести конткретный пример с комментариями?)
Нет,я в пути,в руках только телефон
Открываем проект- вызываем справку, операторы и функции МЭК- операторы сдвига.
VAR
A,A1: DWORD;
B,D1: REAL;
END_VAR
A:=REAL_TO_DWORD(B);
A1:=ROR(A,16);
D1:=DWORD_TO_REAL(A1);
похожий пример есть на форуме по этой ссылке
http://www.owen.ru/forum/showthread....028#post138028
обоснуй?
преобразование ничего не меняет.
Чесно говоря думал что это очевидно. Приведу пример.
x : real := 2000; последовательность байт здесь - 00,00,FA,44
эту последовательность надо сделать FA,44,00,00. Это и есть перестановка регистров.
А если сделать d : (dword) := real_to_dword(x), то мы получим d = 16#000007D0, а из этого, как не переставляй байты, никак не получится FA,44,00,00.
Допускаю что есть редкие комбинации где срастется, но это фичи на которые лучше не рассчитывать.
любое целое <-> real всегда меняет внутреннее представление.Код:преобразование ничего не меняет
real_to_dword(dword_to_real(dw)) не всегда = dw
^, %, union
Вообще-то контроллер работает с бинарным форматом, а в нем все исполняется правильно.
К примеру эта же функция с пресловутыми двумя тысячами:
Вложение 14069Я года 3 назад решал задачу получения данных с преобразователя,
где данные хранились в формате:
Мантиса в одном регистре
Экспонента в одном байте другого регистра.
Все работает, много лет.
Из данных пишется график, архив и пр...
А выглядит это так:
A1_p:=Mantisa; (*присваеваем значение регистра 108 промежуточной переменной*)
A9:=A1.15; (*Выделяем знак*)
A1_p.15:=FALSE; (*Убиваем 15 бит в промежуточной переменной*)
A3:=WORD_TO_DWORD(A1_p); (*превращаем 2 байта в 4*)
A4:=SHL(A3,8); (*Сдвигаем влево на 8 бит*)
A2_p:=WORD_TO_BYTE(Exponenta); (*выделяем младший байт с экспонентой*)
A2_2p:=BYTE_TO_DWORD(A2_p); (*превращаем 2 байта в 4*)
A2_1p:=SHL(A2_2p,23); (*Сдвигаем влево на 23 бита*)
A5:=A4+A2_1p; (*Соединяем экспоненту с мантисой*)
A5.31:=A9; (*Добавляем знак*)
pt :=ADR(A5); (*Копируем в префикс*)
A6:=pt^; (*Превращение в реал(флоат)*)
RAMP_REAL1( IN:=A6 , (*усредняем(фильтруем)*)
ASCEND:= 100,
DESCEND:=300,
TIMEBASE:=T#1s ,
RESET:= ,
OUT=>A6_1 );
A8:=REAL_TO_DWORD(A6_1); (*выделяем целую часть*)
A7:=A8/6; (*получаем расход в мин*10*)
VAR_OUT:=DWORD_TO_WORD(A7); (*Упаковываем значение в 1 регистр*)
))) Картинка ни о чем.Цитата:
К примеру эта же функция с пресловутыми двумя тысячами
Вы путаете ЗНАЧЕНИЕ и ПРЕДСТАВЛЕНИЕ. Для dword - они совпадают (исторически сложилось)
Но для ТС при получении данных с ai нужно переставить слова не ЗНАЧЕНИЯ (как на картинке), а в ПРЕДСТАВЛЕНИИ real. А оно на картинке - отсутствует.
Не сомневаюсь что это работает, но задачу ТС по перестановке регистров (слов) в ПРЕДСТАВЛЕНИИ можно решить не зная формата ПРЕДСТАВЛЕНИЯ. Достаточно знать что это 4 байта. Например:Цитата:
Все работает, много лет.
Из данных пишется график, архив и пр...
А выглядит это так:
A1_p:=Mantisa; (*присваеваем значение регистра 108 промежуточной переменной*)
..
VAR_OUT:=DWORD_TO_WORD(A7); (*Упаковываем значение в 1 регистр*)
ai:real;
p: pointer to dword; //Вы, кстати, без указателей не обошлись ))
p:=adr(ai);
p^:=rol(p^,16); //всё
Значит вариант предложенный lara197a извиняюсь не катит?
1. Это не картинка, а контроллер в режиме исполнения.
2. Указатель там не нужен -100%. Используйте косвенную адресацию и будет Вам счастье.
Много лет назад я имел по поводу указателей разговор с уважаемым И.Петровым,
ведущим специалистом КДС в России. Использовать их он крайне не рекомендовал....
3. С таким же успехом можно сделать без указателя. А:=ror(B,16)
4. Вообще перевод применен реал-дворд для наглядности,
первоначально в примере сдвинул влево и в право с заполнением нулями и сложил переменные.
Но потом решил, что и так все видно, что и Вам показал.
5. Спор ни о чем.
Пользуясь случаем, хочу передать привет компилятору кодесиса, который в ответ на rol(ai, 16) говорит удивительные вещи:Цитата:
ai:real;
p: pointer to dword; //Вы, кстати, без указателей не обошлись ))
p:=adr(ai);
p^:=rol(p^,16); //всё
REAL входит в группу ANY_NUM согласно стандарта, если что. В доках же пишут, что допускаются только BYTE, WORD и DWORD. При этом компилятор молча съедает и INT, и DINT, и UDINT. Непоследовательно как-то.Цитата:
Type mismatch in parameter 1 of 'ROL': Cannot convert 'REAL' to 'ANY_NUM".
:) жаль не могу поучаствовать в придумывании кода без машины, а как в Ваших вариантах преобразуется число 0.00000000375, вроде тоже реал
В заключении хотелось бы отметить, что для избежания ошибок перевод из REAL в DWORD крайне желателен.
при этом полностью сохраняя порядок бит и размер, мы просто избавляемся от условностей типа переменной.
DWORD- ЭТО ВСЕ ЧТО УГОДНО - 4 БАЙТА.
REAL- ЭТО 32-Х БИТНАЯ ПЕРЕМЕННАЯ. В КОТОРОЙ 31,30-24, 23-0 БИТЫ ИМЕЮТ СТРОГО ОПРЕДЕЛЕННОЕ ЗНАЧЕНИЕ.
При этом гарантированно не будет ошибок компилятора и пр.
Речь ведь зашла о неправильном получении реала по модбас,т.е число пришло очень близкое к нулю,но вещественное, dword его обязан просто округлить и получится ноль,а из нуля хоть запереворачивайся истинное значение уже неполучится
не ожидал что такая активность будет теме. Покапался сам и вот такой код будет работать?Код:FUNCTION_BLOCK POU_perenos
VAR_INPUT
input_real: REAL;
END_VAR
VAR_OUTPUT
output_real: REAL;
END_VAR
VAR
input_real_p: POINTER TO ARRAY [0..1] OF WORD;
output_real_p: POINTER TO ARRAY [0..1] OF WORD;
END_VAR
input_real_p:=ADR(input_real);
output_real_P:=ADR(output_real);
output_real_p^[0]:=input_real_p^[1];
output_real_p^[1]:=input_real_p^[0];
Обычно 1-2х знаков после запятой достаточно в 99.9% случаев удобнее получать и передавать данные в int с фиксированным положением запятой.
Модули овен это позволяют.
А конструкции такие городить нет смысла.
Указатели все равно работают только с DWORD.
И как верно замечено capzar малые значения в любом случае будут округлены.
Что по поводу кода? И каким образом модули позволяют передавать значения в int?
На чем тогда мне остановиться?
У модулей по каждому входу можно задать значение dP-смещение десятичной точки. Если к примеру задать 1, то при чтении целого значения определенного регистра модуля, вместо 25 гр.С, к примеру, получим целое же значение 256, где 6 это значение после запятой, как если бы читали вещественное 25.6
А почему мв отдают неправильный real? Что им мешает сделат его правильным?
real - правильный. Представление - другое. Как привести к нужному именно в ПЛК - обсосано до нельзя. Если и дальше что-то мешает, то есть хирурги.
Так а вот у меня температура 17.5678 - это правильное значение? Ну, наверное, правильное. Зачем тогда что-то ещё с ней делать, если она уже вот, готовенькая.
https://ru.wikipedia.org/wiki/%D0%A7...81%D1%82%D0%B8 прочтите про стандарт вещ.чисел. Первый рисунок показывает на каких разрядах, что расположено, всего их 32, По модбас ввиду особенностей программирования порядок этих разрядов меняется и число меняет свое значение, потому что на стороне мастера может не совпадать порядок расположения принятых байт
все же хочу разобраться. есть мв110. добавляем в конфигураторе real input register и присваиваем ему переменную, например, IN. далее, где-то в тексте программы это значение присваиваем другой переменной:
dummy := IN;
так вот при каких условиях в dummy будет лежать кривое число?
Если через конфигуратор,то такого гедолжно быть,если в настройках не меняли порядок
Я имею ввиду "конфигурация ПЛК" в Codesys.