> 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é
> 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é
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é
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
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.