View previous topic :: View next topic |
Author |
Message |
[email protected]
Joined: 28 Jul 2014 Posts: 38
|
modbus rtu data calculation |
Posted: Wed Dec 30, 2020 5:56 am |
|
|
Dear friends,
I am new to modbus rtu. I am getting the following data. How to compute the same ?
01 03 04 (86 9F 00 01) 22 95 = 99999
(86 9F 00 01) this is the data. How can i compute to get 99999 ?
01 03 04 (79 61 FF FE )72 C1 = -99999
(79 61 FF FE ) this is the data. How can i compute to get -99999 ?
01 03 04 (40 00 44 0D) 1D 36 = 7894.567
(40 00 44 0D) this is the data. How can i compute to get 7894.567 ?
kindly help me. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Wed Dec 30, 2020 8:09 am |
|
|
The first two are easy. They are just integer values. So all you would need
to do is write the bytes in the right order into a CCS signed int32 value,
and it'll contain the result:
Code: |
union {
unsigned int8 bytes[4];
signed int32 word;
} combiner;
//combiner.bytes[0] = second byte from value
//combiner.bytes[1] = first byte from value
//combiner.bytes[2] = fourth byte from value
//combiner.bytes[3] = third byte from value
//so
combiner.bytes[0] = 0x9F;
combiner.bytes[1] = 0x86;
combiner.bytes[2] = 0x1;
combiner.bytes[3] = 0x00;
//Then
combiner.word //Will be 99999
|
The third is problematic. Modbus _does not define any way to send float
values_. Float transmission is 'customer specific'. You need to know
how this value has been encoded. The normal way to do it would be
IEE 754. However the value you post is not in this format. Likely alternatives
are that in fact the value is being sent as perhaps an integer in some small
fraction. However I can't see an obvious multiple to give this.
You need data from whoever is generating this value as to the format
they are using. Otherwise it is going to be a difficult task (and you would
need a lot more values), to work out how they are coded. |
|
|
[email protected]
Joined: 28 Jul 2014 Posts: 38
|
|
Posted: Wed Dec 30, 2020 10:31 pm |
|
|
Thanks for your code it is working.
For floating point value i got some more values:
Rx:000001-01 03 04 (4F 80 47 C3) 9E AE = 99999.000
Rx:000003-01 03 04 (44 9C C2 6A) FF A2 = -58.567
Rx:000005-01 03 04 (33 33 41 43 )74 D9 = 12.200
Rx:000007-01 03 04 (E6 B6 46 40 )1F 0D = 12345.678
Can you guess what type of encoding they are using ?
I am using Weintek HMI. From that only i am getting the data. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 31, 2020 2:01 am |
|
|
It's IEEE-754 32-bit single precision floating point format. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Thu Dec 31, 2020 2:15 am |
|
|
OK. Well those are in standard IEEE format. So it suggests that the other
value may have been wrong. The bytes you gave decode to 565.0 using
standard IEEE encoding....
Question. What PIC are you on?. The answer changes if you are on a
PIC24/30/33.
For a PIC16/18:
Code: |
include "IEEEfloat.c"
union {
unsigned int8 bytes[4];
signed int32 word;
unsigned int32 uword;
} combiner;
float floatval;
//combiner.bytes[0] = second byte from value
//combiner.bytes[1] = first byte from value
//combiner.bytes[2] = fourth byte from value
//combiner.bytes[3] = third byte from value
//so
combiner.bytes[0] = 0x80;
combiner.bytes[1] = 0x4F;
combiner.bytes[2] = 0xC3;
combiner.bytes[3] = 0x47;
//for your first 99999.00 number
//Then
floatval=f_IEEEtoPIC(combiner.uword);
//will give the float value
|
On the PIC24/30/33, the float format is already IEEE, so all that is needed
is a fourth 'float' value in the combiner, and this will contain the float result. |
|
|
[email protected]
Joined: 28 Jul 2014 Posts: 38
|
|
Posted: Thu Dec 31, 2020 4:38 am |
|
|
I am using dspic 33ep512mu810.
Float format is IEEE-754.
Quote: |
union {
unsigned int8 bytes[4];
signed int32 word;
unsigned int32 uword;
} combiner;
float floatval;
//combiner.bytes[0] = second byte from value
//combiner.bytes[1] = first byte from value
//combiner.bytes[2] = fourth byte from value
//combiner.bytes[3] = third byte from value
so
while(true)
{
combiner.bytes[0] = 0x80;
combiner.bytes[1] = 0x4F;
combiner.bytes[2] = 0xC3;
combiner.bytes[3] = 0x47;
//for your first 99999.00 number
//Then
floatval=f_IEEEtoPIC(combiner.uword);
lcd_gotoxy(1, 1);
printf(lcd_putc1, "%f",floatval);
//will give the float value
} |
The result I am getting in lcd is = 2676363008.00.
This value is wrong! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Thu Dec 31, 2020 4:44 am |
|
|
It would be. Read what I said for the PIC24/33.
All you need for this is:
Code: |
//include "IEEEfloat.c" Not needed for this on DsPIC
union {
unsigned int8 bytes[4];
signed int32 word;
unsigned int32 uword;
float32 floatval;
} combiner;
//combiner.bytes[0] = second byte from value
//combiner.bytes[1] = first byte from value
//combiner.bytes[2] = fourth byte from value
//combiner.bytes[3] = third byte from value
//so
combiner.bytes[0] = 0x80;
combiner.bytes[1] = 0x4F;
combiner.bytes[2] = 0xC3;
combiner.bytes[3] = 0x47;
//for your first 99999.00 number
//Then
combiner.floatval //is then the result.
//will give the float value
|
You are taking an already IEEE value and converting it to the CCS/
Microchip format, when your chip uses IEEE.... |
|
|
[email protected]
Joined: 28 Jul 2014 Posts: 38
|
|
Posted: Thu Dec 31, 2020 6:18 am |
|
|
Sorry for the confusion bro.
Now it is working correctly.
Thank you. |
|
|
|