Question

I have a hardware that is communicating with the PLC over Profibus DP, that sends me 4 bytes of data in hex that is "44 79 FF FF" and in the PLC program I have declared a BYTE array for this input data. The problem is in the PLC the data I receive in my BYTE array is "66 121 255 255" which is the decimal value of the hexdecimal, but my goal is to convert that value to a REAL and when I do that I'm not getting the value I expected.

I have created a DWORD(4bytesData) that i insert all the BYTES into. So before I insert the 4 bytes into 4bytesData the bytes are: in1 = 68 , in2 = 121, in3 = 255 & in4 = 255

4bytesData := (SHL(SHL(SHL(BYTE_TO_DWORD(in1), 8) OR BYTE_TO_DWORD(in2), 8) OR     BYTE_TO_DWORD(in3), 8) OR in4);

realValue := DWORD_TO_REAL(4bytesData);

Where in1, in2, in3 & in4 is byte 0-3.

The value I'm getting is; 4bytesData = 1148846079 & realValue = 1.148846e+009

The value I'm expecting to get from realValue is = 9.9999993896484375E2

If i use this website ( IEEE754 Analyzer/Converter ) and converting the hex value (4479FFFF) I'm getting the value I want to, and if i insert the decimal value (1148846079) I'm getting the same value I receive in the PLC.

I hope you understand my problem, Many thanks in Advance.

Was it helpful?

Solution

You've already figured it out, it seems that you just don't realize it. The conversion DWORD_TO_REAL is taking the integer (hex) value stored in 4bytesData and converting it to IEEE754 REAL format.

This is not what you want to do. 4479FFFF is already in IEEE754 REAL format - you're taking that value, interpreting the REAL as a DWORD, and then converting the DWORD value to a REAL. The short answer is that you don't need the conversion - 4bytesData is already in the correct format.

edit

follow up on comments :

enter image description here

here FunctionBlock2 delclares rIn(REAL), rOut(REAL) and sets rOut:=rIn;. This gets around the forced typecasting of ST. Nothing is changing about the data stored in D2000 here - it's the same binary data. The top function block is storing it into memory and the bottom one is reading it from memory. The only difference is that the top rung is interpreting it as a DWORD (for display purposes) and the bottom rung is interpreting it as REAL.

edit

I've been reading the Beckhoff manual. It seems you may have other options. Try perhaps declaring a DWORD and REAL at the same memory location. If not, perhaps pointers would let you do it (not sure if type restrictions also apply to pointers with Beckhoff?)

OTHER TIPS

If someone is interested, I made this function that works on a Beckhoff PLC to convert from an array of 4 bytes to a real:

(* declaration *)

FUNCTION BYTE_TO_REAL : REAL
VAR_INPUT
abValueIn : ARRAY[0..3] OF BYTE;
END_VAR
VAR
pByteIn1, pByteIn2, pByteIn3, pByteIn4: POINTER TO BYTE;
rValueOut : REAL;
END_VAR

(* implementation *)

pByteIn1 := ADR(rValueOut);
pByteIn2 := ADR(rValueOut) + SIZEOF(BYTE);
pByteIn3 := ADR(rValueOut) + 2 * SIZEOF(BYTE);
pByteIn4 := ADR(rValueOut) + 3 * SIZEOF(BYTE);

(*watch out, small endians needed here*)
pByteIn1^ := abValueIn[3]; 
pByteIn2^ := abValueIn[2]; 
pByteIn3^ := abValueIn[1]; 
pByteIn4^ := abValueIn[0]; 

BYTE_TO_REAL := rValueOut;

As I found it out, REAL is stored on 4 bytes, strong byte at the end. I mean that, compared to IEEE-754 converter, bytes are sorted in opposite direction, so I have to invert it in code.

I don't catch the original issue with decimal- hexadecimal. In twincat IDE, value are displayed in decimal in debug, but internally, this should not make any difference

Your byte order is probably wrong and your routine is expecting opposite endianness. Try FFFF7944 instead of 4479FFFF and see if you get 9.9999993896484375E2 as expected. Also, 1148846079 is 00F4884E as IEEE754 (change byte order if needed) so you might have more then one error in your perception.

be careful nesting all the SHL. IN V2.3 you could only go about 4 deep. I have found on different controllers (compiler for the target probably) that you can get wrong evaluations by nesting. Best to keep them on their own lines. 4 lines of code put in a function FUNCTION BYTES_TO_DWROD : DWORD and you are all good to reuse your conversion over and over.

Use a pointer to move the value from the DWORD to the REAL. It seems to prevent the conversion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top