5

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.

hijack
  • 263
  • 2
  • 3
  • 11

5 Answers5

4

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?)

J...
  • 30,968
  • 6
  • 66
  • 143
  • Thanks for the answer. You are correct that I don't have to use the "DWORD_TO_REAL" conversion. But I'm still getting the "1.148846e+009" value if I remove that, so its still the same. The 4bytesData is "1148846079". – hijack Apr 19 '13 at 14:24
  • @hijack it's probably doing the conversion for you automatically, then, even though you remove the explicit conversion...depends on the PLC you are using. Try declaring 4bytesData as REAL type rather than DWORD. – J... Apr 19 '13 at 14:33
  • Yeah probably it is. (I'm using Beckhoff) When I'm doing the shifting of the bytes into the 4bytesData I get an error: "Type mismatch in parameter, cannot convert 'REAL' to 'BYTE'. – hijack Apr 19 '13 at 14:52
  • ugh... I hate structured text. Just output it as a DWORD without converting and use it like a REAL in ladder, it will work. – J... Apr 19 '13 at 15:11
  • hehe, and I hate ladder :P. We don't use any ladder in our program for our machine so I need to solve this in ST only, sorry. Do you know how to write that ladder code in ST, our could you post a picture of the ladderblock, so I can try to write that in ST? – hijack Apr 19 '13 at 15:23
  • @hijack you can't do it in ST. In ladder or IL you can just move data blocks around. In ST you can't. What you could do is output the DWORD to a memory location and then bring it into a new function block typed as REAL. I use Omron but I'll post an example. – J... Apr 19 '13 at 15:39
  • 1
    @hijack I've been reading the Beckhoff manual. It seems you may have other options. Try perhaps http://infosys.beckhoff.com/content/1033/tcplccontrol/html/tcplcctrl_variables_allocated.htm?id=14211 -- declare 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?) http://infosys.beckhoff.com/english.php?content=../content/1033/tcplccontrol/html/tcplcctrl_^.htm&id=14183 – J... Apr 20 '13 at 11:46
  • The pointers did the trick, thank you so much for your help, really appreciated! Please update your answer and I will set it as a accepted answer! – hijack Apr 22 '13 at 08:29
3

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

0

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.

avra
  • 3,690
  • 19
  • 19
  • Good idea. But when I change the order I get: 4294932804(decimal) and 4.294933e+009(real). – hijack Apr 19 '13 at 11:28
  • Yeah I dont understand why I get 1148846079.. The PLC must be doing some converting that I'm not aware of. – hijack Apr 19 '13 at 11:50
  • Now I get it. You should read help for DWORD_TO_REAL(). It seams that you expect to forward to it bytes representing IEEE754 standard float format (which is wrong perception of that function), but instead it will convert for example 4 to 4.0 and 1000 to 1000.0. You need to find a function that will cast raw IEEE754 4 bytes to a real number, or write those 4 bytes in correct endianness order directly to a floating number byte by byte. – avra Apr 21 '13 at 02:04
0

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.

0

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