modbus_get_float()

841 views
Skip to first unread message

Rene Maurer

unread,
Apr 4, 2012, 12:16:49 PM4/4/12
to libm...@googlegroups.com
Hello

I have compiled libmodbus for the ARM architecture.

Reading registers over TCP works fine so far. I have troubles with registers representing floats. I cannot convert them correctly with  modbus_get_float().

Also a simple example (taken from the man page) does not work as expected:

float u;

uint16_t xx[2] = {0x4465, 0x229a};
u = modbus_get_float(xx);
printf("%1.1f\n",  u);  // ---> u WRONG VALUE 0.0

uint16_t xxx[2] = {0x229a, 0x4465};
u = modbus_get_float(xxx);
printf("%1.1f\n",  u);  //    ---> u CORRECT VALUE 916.5

I seams that I have to change the two 16 bit values before the conversion...

Help would be much appreciated.

Best regards, Rene M.

Rene Maurer

unread,
Apr 4, 2012, 3:16:52 PM4/4/12
to libm...@googlegroups.com
On 04/04/2012 at 21:04 Rene Maurer <rene...@gmail.com> wrote:

> Reading registers over TCP works fine so far. I have troubles with
> registers representing floats. I cannot convert them correctly with
> modbus_get_float().
>

> I seams that I have to change the two 16 bit values before the
> conversion...

Answering myself.

My ARM system has a "big endian float order" while the libmodbus
implementation is made for "little endian float order".

The float word order can easy be detected at compile time with the
following statement: "#if __FLOAT_WORD_ORDER == BIG_ENDIAN".

Should I fix this inside my code or is there a chance that it will be
fixed in libmodbus?

René

Stéphane Raimbault

unread,
Apr 6, 2012, 8:34:30 AM4/6/12
to libm...@googlegroups.com
I've a patch to fix this issue on my computer for ages (based on hton macros), I just need some testers.
I'll try to find the time to send you this patch if you're willing to test.

Stéphane

2012/4/4 Rene Maurer <rene...@gmail.com>

Stéphane Raimbault

unread,
Apr 9, 2012, 5:39:32 PM4/9/12
to libm...@googlegroups.com
Hi Rene,

Could try the float branch please?
https://github.com/stephane/libmodbus/tree/float

I've many doubts about the way to handle this.

Stéphane

Rene Maurer

unread,
Apr 9, 2012, 6:55:51 PM4/9/12
to libm...@googlegroups.com
On 04/09/2012 at 23:04 Stéphane Raimbault
<stephane....@gmail.com> wrote:

> Could try the float branch please?
> https://github.com/stephane/libmodbus/tree/float

Thank you very much for answering.
I will try the branch today or tomorrow.

Regards René

Rene Maurer

unread,
Apr 10, 2012, 10:04:46 AM4/10/12
to libm...@googlegroups.com
On 04/09/2012 at 23:39 Stéphane Raimbault
<stephane....@gmail.com> wrote:

I have now done some more tests with two independent machines:

1. PC (an Ubuntu GNU/Linux x86 box)
2. ARM (GNU/Linux uclib based embedded ARM system)

On both system I have used the latest libmodbus (3.0.2) without
modifications.

I have a small test program which reads 6 registers (16 Bit each
register). This registers represents 3 float values.

This means, after

retval = modbus_read_registers(mb, 0, 6, tab_reg);

tab_reg[0] and tab_reg[1] contain the first float value
tab_reg[2] and tab_reg[3] contain the second float value
tab_reg[4] and tab_reg[5] contain the third float value

(that at least is my understanding)

When I use

f1 = modbus_get_float(&tab_reg[0]);
f2 = modbus_get_float(&tab_reg[2]);
f3 = modbus_get_float(&tab_reg[4]);

to convert the register values to floats, the result is wrong ON BOTH
SYSTEMS.... (the ARM system has BIG ENDIAN FLOATS while the PC has
LITTLE ENDIAN FLOATS).

If I change the order before doing the conversion in the following way:

tmp1 = tab_reg[0];
tmp2 = tab_reg[1];
tab_reg[0] = tmp2;
tab_reg[1] = tmp1;
f = modbus_get_float(&tab_reg[0]);

...the result on BOTH SYSTEMS is ok [...]

Example output PC:

$ ./ModBusClientPC 192.168.252.42 502
Detect endianess: LITTLE ENDIAN FLOATS
Read: 0x4368 0x38b4 0x4368 0x19e1 0x4368 0x30ff
0) Register: 0x4368 0x38b4 -> 0.00 (WRONG)
0) Register: 0x38b4 0x4368 -> 232.22 (OK)
1) Register: 0x4368 0x19e1 -> 0.00 (WRONG)
1) Register: 0x19e1 0x4368 -> 232.10 (OK)
2) Register: 0x4368 0x30ff -> 0.00 (WRONG)
2) Register: 0x30ff 0x4368 -> 232.19 (OK)


Example output embedded/ARM:

# ./ModbusClient 192.168.252.42 502
Detect endianess: BIG ENDIAN FLOATS
Read: 0x4367 0x5189 0x4367 0x4220 0x4367 0x68a7
0) Register: 0x4367 0x5189 -> 73692667904.00 (WRONG)
0) Register: 0x5189 0x4367 -> 231.32 (OK)
1) Register: 0x4367 0x4220 -> 40.07 (WRONG)
1) Register: 0x4220 0x4367 -> 231.26 (OK)
2) Register: 0x4367 0x68a7 -> 6319028451394841600000000.00 (WRONG)
2) Register: 0x68a7 0x4367 -> 231.41 (OK)

Is there somewhat wrong with my MODBUS device? Does it deliver the
result words/registers in the wrong order? Or am I completely wrong
with my interpretation?

Sorry for not being clear enough in my first postings.

Regards, René

Stéphane Raimbault

unread,
Apr 10, 2012, 5:38:08 PM4/10/12
to libm...@googlegroups.com
Your feedback is very useful, no difference between ARM and PC and your device expect CDAB order (instead of current ABCD).

I'm pretty sure that the byte ordering is not always the same between the various Modbus devices (the Modbus standard isn't very clear on the subject).
So could someone give me information about the way the Modicon TSX automation devices store float numbers on the Modbus trame?
I'm intend to use Modicon device as the reference device.

With this information I will know how to encode the float (ARM and PC) and then I'll provide a macro to swap floats on non-compliant devices.

Rene (and others :), could you test with this float value?

const float UT_REAL = 916.540649;

This value is currently used in the unit tests of libmodbus so it will be convenient to compare ordering.

Have you tried the float branch?

Stéphane

2012/4/10 Rene Maurer <rene...@gmail.com>

Is there somewhat wrong with my MODBUS device? Does it deliver the
result words/registers in the wrong order? Or am I completely wrong
with my interpretation?


I'm pretty sure that the byte ordering is not always the same between the various Modbus devices (the Modbus standard isn't very clear on the subject).
So could someone give me information about the way the Modicon TSX automation devices store float numbers on the Modbus trame?
With this information I will know how to encode the float (ARM and PC) and then I'll provide a macro to swap floats on non-compliant devices.

Rene Maurer

unread,
Apr 11, 2012, 5:55:27 AM4/11/12
to libm...@googlegroups.com
On 04/10/2012 at 23:38 Stéphane Raimbault
<stephane....@gmail.com> wrote:

> I'm pretty sure that the byte ordering is not always the same between
> the various Modbus devices

I have read several articles confirming this.

> So could someone give me information about the way the Modicon TSX
> automation devices store float numbers on the Modbus trame?
> I'm intend to use Modicon device as the reference device.

Sorry I am using other devices (Janitza), where the float value
"227.977" is stored in the frame as follows:
tab_reg[0] -> 0x4363
tab_reg[1] -> 0xfa36

> I'll provide a macro to swap floats on non-compliant devices.

This is what i use for now:

float swap_float(float f)
{
uint32_t *fp = (uint32_t*)&f;
*fp = ((*fp << 16) & 0xffff0000) | ((*fp >> 16) & 0x0000ffff);
return f;
}

> Have you tried the float branch?
> https://github.com/stephane/libmodbus/zipball/float

I have had problems with cross compiling the branch (autogen.sh vs
configure). Finally i have taken only the .c and .h files from the src
directory. As far as i can see it does work (when i use the float_swap
method described above).

R.

Stephane Raimbault

unread,
Jun 11, 2012, 6:54:40 PM6/11/12
to libm...@googlegroups.com


Le mercredi 11 avril 2012 11:55:27 UTC+2, Rene Maurer a écrit :
So we can merge this branch in master and provide a function to swap float.

Just need to find time to do that...

Stéphane 

Brandon Fowler

unread,
Jan 9, 2013, 11:17:15 AM1/9/13
to libm...@googlegroups.com
Any chance we'll see an arm build in the future?  I'd like to run this on a beaglbone/beaglebone to communicate with some of our PLC machines.  Either that or a little help with cross compiling for arm. 

Stéphane Raimbault

unread,
Jan 14, 2013, 12:29:36 PM1/14/13
to libm...@googlegroups.com
I don't intend to provide ARM builds. Many contributors provides packages for many distributions and architectures (may be ARM).
libmodbus has already been compiled for ARM with success (not by me).

It's all I know about this...

2013/1/9 Brandon Fowler <brand...@gmail.com>
Reply all
Reply to author
Forward
0 new messages