I have two signed register values 17147 and -27394. They are in order of High-Low bits. I want to get the value float 32 big endian value using these value. I have used following code to convert to value.
My code
int intValue = 17147;
intValue <<= 16;
intValue = -27394;
byte[] bytes = BitConverter.GetBytes(intValue);
double readingValue = BitConverter.ToSingle(bytes, 0);
According to above code reading shows as 125.291. But modbus tools & other online convertions says that value should be 125.791.
Please note that some times reading is okay for some values. Actual value and converted value difference is not the same.
CodePudding user response:
You're combining the two registers together incorrectly.
- 17147 is hex
42 FB
(or00 00 42 FB
as a 4-byte value) - -27394 is hex
94 FE
as a 2-byte value, orFF FF 94 FE
as a 4-byte value - Therefore
intValue
should have the hex value42 FB 94 FE
, but your way of combining42 FB
and94 FE
gives you42 FA 94 FE
.
You're being caught out by the fact that -27394 is presented as a negative number, but that's just the way that your software has chosen to interpret those 2 bytes. You're then treating it as a signed 4-byte value rather than an unsigned 2-byte value when you come to combine it with the 17147.
When we combine 17147 and -27394, we need to make sure that we just look at the lower 2 bytes of each. That will undo any damage that was done by interpreting the values as signed 4-byte numbers.
int upper = 17147;
int lower = -27394;
int intValue = ((upper & 0xFFFF) << 16) | (lower & 0xFFFF);
Now:
byte[] bytes = BitConverter.GetBytes(intValue);
double readingValue = BitConverter.ToSingle(bytes, 0);
Console.WriteLine(readingValue);
Gives 125.79100036621094, as expected.