LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Modbus Type Conversion Issues - Floating Point Number Handling

Solved!
Go to solution

I setup communication with a Modbus Master (PLC) in LabVIEW using an I/O Server.  I would like to be able to read 64bit Floating Point numbers directly using one Modbus variable but for some reason I can get it to work correctly. 

 

In the attached image you can see Modbus address locations 29 through 32 (each being U16) being read and after doing some word swapping I get the correct value in "VariableAA".

 

Below that I tried various different ways that I found in examples to read the same 64bit floating point number starting at Modbus address 29.  None of the shown methods result in the correct value "VariableAA".  I understand I need to do a similar word swap, but even when I do, I seem to still get an answer that is very wrong.

 

Is there something that I am missing?  Am I going to be stuck passing all my 64bit floating point numbers as 4 different U16 variables?  Any advice would be greatly appreciated.

 

I didn't include the LabVIEW code since it would need my Modbus communications to function but I can if that would help.  I am running LV2020.

0 Kudos
Message 1 of 9
(4,255 Views)

Hi JTClarke,

 


@JTCLARKE wrote:

In the attached image you can see Modbus address locations 29 through 32 (each being U16) being read and after doing some word swapping I get the correct value in "VariableAA".

 

Is there something that I am missing?  Am I going to be stuck passing all my 64bit floating point numbers as 4 different U16 variables?  Any advice would be greatly appreciated.


Using Join and TypeCast is one way of converting 4 U16 values into one DBL (64bit) value.

You may also build an array of your U16 values and TypeCast the array.

And yes, Modbus can only handle integer data, AFAIK only 8, 16 and 32 bit entities values. You need to convert from those entities to DBL anyway…

 


@JTCLARKE wrote:

Below that I tried various different ways that I found in examples to read the same 64bit floating point number starting at Modbus address 29.  None of the shown methods result in the correct value "VariableAA".  I understand I need to do a similar word swap, but even when I do, I seem to still get an answer that is very wrong.


What value do you read in the "VariableA" shared variable?

And why do you think swapping bytes would be a good idea when typecasting a DBL value into another DBL value?

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 2 of 9
(4,227 Views)
Solution
Accepted by topic author JTCLARKE

I started to answer this question, then realized it was a bit confusing as to what was going on, and that some details were missing.  Like Gerd point out what is in Variable A, but must obviously be the value in Variable AB

 

Although the OP does a lot of manipulations with the data in LabVIEW, I reread the message and realized the issue was in the setup of the Modbus I/O library and the I/O variable in it that is designated to be double.  It would have been great if the OP had posted at least a screen shot of the setup of the library and variable.

 

I think the issue is that the I/O variable doesn't have a way to designate word or byte order in it like other Modbus scanning programs do.  If this was a single precision float (2 registers, which is far more common in Modbus) rather than double precision float (4 registers), programs would designate them as ABCD  or DCBA  or BADC or CDAB or,  maybe there are more combinations.  I'm not going to even attempt an 8 byte 4 register set of combinations, but ABCDEFGH and various permutations are how it would look.

 

Are the 4 individual U16 registers supposed to be the exact same value(s) as the set of 4 registers you designated as double?  We see what the values are in the probes from the middle, but we don't see what any of the conversions to U16's look like at the bottom.

 

I suggest trying to set up a U64 first in grabbing the 4 registers.  That way you can show them in hex code and have a better understanding of how the words and bytes are arranged.

 

And please attach a project and library file so we see how you've configured things.

 

 

0 Kudos
Message 3 of 9
(4,218 Views)

VariableA should be 0.945.


@GerdW wrote:

Hi JTClarke,

 


@JTCLARKE wrote:

In the attached image you can see Modbus address locations 29 through 32 (each being U16) being read and after doing some word swapping I get the correct value in "VariableAA".

 

Is there something that I am missing?  Am I going to be stuck passing all my 64bit floating point numbers as 4 different U16 variables?  Any advice would be greatly appreciated.


Using Join and TypeCast is one way of converting 4 U16 values into one DBL (64bit) value.

You may also build an array of your U16 values and TypeCast the array.

And yes, Modbus can only handle integer data, AFAIK only 8, 16 and 32 bit entities values. You need to convert from those entities to DBL anyway…

 


@JTCLARKE wrote:

Below that I tried various different ways that I found in examples to read the same 64bit floating point number starting at Modbus address 29.  None of the shown methods result in the correct value "VariableAA".  I understand I need to do a similar word swap, but even when I do, I seem to still get an answer that is very wrong.


What value do you read in the "VariableA" shared variable?

And why do you think swapping bytes would be a good idea when typecasting a DBL value into another DBL value?



 The goal is to convert the single 64bit shared “VariableA”(DBL) to the correct value without having to read 4 different shared variables as U16.

 

The byte swapping was only to try to recreate the same functionality as reading 4 - U16 registers, swapping the words and then typecasting as shown in example VariableAA.


I had hoped using the I/O server modbus function would simplify conversions and require less manipulation and typecasting that I had done using read/write holding register slave functions.  

0 Kudos
Message 4 of 9
(4,209 Views)

I would follow RavensFan's advice: typecast your DBL value to a string or U8 byte array, then compare it to the content of the four U16 integers, displaying all values in hex format.

I'm surprised though about that DBL value: that precision is rarely needed. In most cases it would be a waste of memory and bandwidth (although tiny).

Paolo
-------------------
LV 7.1, 2011, 2017, 2019, 2021
0 Kudos
Message 5 of 9
(4,201 Views)

Thank you RavensFan.  After playing around a bit with your suggestions I have solved the problem! 

 

I used your advice and read in the 4 registers using the Array of UInt16 I/O Server Modbus function and looked at each of the 4 registers first to make sure they matched the registers that I read separately.  I then did the word swapping required and typecast it back to DBL.  Everything matches up now and it matches the host system.

 

I really was trying to avoid having to do any typecasting, which is why I had hoped I would be able to read the 4 registers and convert directly to DBL using the I/O Server functions rather that having to read in as (4) U16 and then typecasting.

 

This solution works though!  Thank you everyone for your help and support on this.

 

I attached some images of the final solution as well as my I/O server config and project.

0 Kudos
Message 6 of 9
(4,169 Views)

Excellent.

 

A couple tips for you based on your last picture.

 

1.  Index Array is expandable!  Delete of those leaving just one.  Drag the bottom border downwards.  Get rid of the index constants.  You can get 4 outputs and they'll automatically be indices 0, 1, 2, 3 by default without wiring up constants.  You'll go from 8 nodes and all the extra wires and wire branches down to a single node!

 

2.  Don't bother with the extra functions to format a numeric into a string to case into a string indicator.  Make a numeric indicator.  Right click and make the radix visible.  Click on it to set it for hex format.  Right click on the indicator and adjust the display settings so that it will show leading zeroes, that way the display will always show 4 hex characters.  8 more functions, 8 more constants and respective wires are now eliminated from your VI.

0 Kudos
Message 7 of 9
(4,166 Views)

Thank you again!  Those are great tips too!

 Sometimes you just don’t realize these little things can really simplify your code.

 

Should I mark your reply as the solution or mine? 

0 Kudos
Message 8 of 9
(4,163 Views)

You should mark my message.  I provided that solution to you and it gives me credit for doing that.

0 Kudos
Message 9 of 9
(4,154 Views)