Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 11:20 01 Aug 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Converting IEEE754

Author Message
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 01:53am 27 Mar 2018
Copy link to clipboard 
Print this post

Hi All,

Can Anyone who's not as vague as me on Binary Maths tell me if I'm on the right track trying to convert this data.

My Modbus Energy Meters return a HEX value that need to be converted to a float.

It's documented here on page 14 of their manual.

Can't quite get my head around the math, but I'm attempting to treat the data as an integer then move the decimal place in binary form by dividing by 65,536 IE 2^16.

Not sure if I'm on the right track or not even though this code gives back 240.5.
I'm at this stage ignoring the sign & not sure how the exponent relates to 2^16=65536.

Thanks

Phil

  Quote  'Converting IEEE754 Floating point number from Eastron Energy Meter.
'Request Example shows Hex 43708000 returned for 240.5 Volts
'First Bit is the Sign, & the next bit is the Exponent, with an offset of 127
'The remaining 23 bits are the fractional part of the data.

Reading%=
&H43708000

Print Hex$(Reading%,8)
Print Bin$(Reading%,32)
Expo%=Reading% >>
23
Print Bin$(Expo%,8), Str$(Expo%)
Val%=Reading%
or &hff800000
Print Bin$(Val%,32)
Val%=Val% -
&hff800000
Print Bin$(Val%,24)
Val%=Val% +
&h00800000
Print Bin$(Val%,24)
'Print Bin$(Val%,32)
'Val%=Val% >> 18
Print Bin$(Val%,24)
Print Str$(Val%)
Print Str$(Val%/65536) 'or &h10000 or 2^16


Returns this....

[Code]
DOS MMBasic Ver 5.04.08
Copyright 2011-2017 Geoff Graham

43708000
01000011011100001000000000000000
10000110 134
11111111111100001000000000000000
011100001000000000000000
111100001000000000000000
111100001000000000000000
15761408
240.5
>

[/code]
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 07:28am 27 Mar 2018
Copy link to clipboard 
Print this post

Try this with a few other numbers
  Quote   DIM FLOAT a
DIM h(4)

h(
1) = &H43
h(
2) = &H70
h(
3) = &H80
h(
4) = &H00

PRINT a

FOR n = 0 TO 3
POKE VAR a, n, h(4-n)
NEXT n

PRINT a


It simply pokes the 4 bytes into a variable of type float and lets MMBasic do the conversion.
I am not sure about all the different IEEE standards but it give the right answer for the supplied bytes.

Jim
VK7JH
MMedit
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 07:51pm 27 Mar 2018
Copy link to clipboard 
Print this post

Thanks Jim,

Works with &h43708000=240.5 & &hc3708000= -240.5,
but happened to try &hc82e7570 & it returned -178646 not -178645.75.

Seems to Truncate the decimal in quite a few examples.

But then realised that my code below, which is now working fine in the DOS version, does a similar thing when I load it into an E64 that has Version 5.0302.

  Quote   'Converting IEEE754 Floating point number from Eastron Energy Meter.
'Request Example shows Hex 43708000 returned for 240.5 Volts
'First Bit is the Sign, & the next bit is the Exponent, with an offset of 127
'The remaining 23 bits are the fractional part of the data.

'Reading%=&H43708000 '=240.5V
'Reading%=&H43663334 '=230.2V

Do
CLS
Input "Hex Value: ", ReadingStr$ : ReadingStr$="&h"+ReadingStr$
Print ReadingStr$
Reading%=
Val(ReadingStr$)

Print "Hex Value Reading: ";Hex$(Reading%,8) 'Reading in Hex
Print "Binary Value: ";Bin$(Reading%,32) 'Reading in Binary
Sign%=Reading% >> 31 'Read the Sign Bit
Print "Sign Bit: ";Hex$(Sign%)
Expo%=(Reading% >>
23) - Sign%*&h100 'Extract Exponent, remove sign bit if present
Print "Exponent & -offset: ";Bin$(Expo%,8), Str$(Expo%-127)
Expo%=Expo%-
127
Val%=Reading%
or &hff800000 'Set First 9 Bits to 1
'Print Bin$(Val%,32)
Val%=Val% - &hff800000 'Remove First 9 bits
'Print Bin$(Val%,24)
Val%=Val% + &h00800000 'Add implied MSB of Mantissa before the decimal point
Print "Full Mantissa: ";Bin$(Val%,24)
'Print Bin$(Val%,32)
'Val%=Val% >> 18
'Print Bin$(Val%,24)
Print "Decimal Value: ";Str$(Val%)
Ans!=(Val%/
2^(23-Expo%)) 'Shift the point in binary. Dividing by 2^ positions to shift
Print "Binary Shift Applied: ";Ans!
Ans!=Ans!*(-
1)^Sign% 'Apply the Sign Bit
Print "Sign Bit Applied: ";Str$(Ans!)
Print

Do While Inkey$="": Loop

Loop


Output on the E64.
[Code]
print mm.ver
5.0302
> run
Hex Value: 487a7293
&h487a7293
Hex Value Reading: 487A7293
Binary Value: 01001000011110100111001010010011
Sign Bit: 0
Exponent & -offset: 10010000 17
Full Mantissa: 111110100111001010010011
Decimal Value: 16413331
Binary Shift Applied: 256458
Sign Bit Applied: 256458
[/code]

Output from DOS MMbasic.
[Code]
> print mm.ver
5.0408
> run
Hex Value: 487a7293
&h487a7293
Hex Value Reading: 487A7293
Binary Value: 01001000011110100111001010010011
Sign Bit: 0
Exponent & -offset: 10010000 17
Full Mantissa: 111110100111001010010011
Decimal Value: 16413331
Binary Shift Applied: 256458.2969
Sign Bit Applied: 256458.2969
[/code]

Edit:- original number encoded was 256458.3 & did it here...

https://www.h-schmidt.net/FloatConverter/IEEE754.html





Edited by Phil23 2018-03-29
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 08:48pm 27 Mar 2018
Copy link to clipboard 
Print this post

Floating point numbers get PRINTED with a reduced number of significant figures to give a true representartion of their precision.
  Quote   x = 256458.2969
PRINT x
PRINT STR$(x,10,10)



Change my original program to PRINT with more digits:
  Quote   DIM FLOAT a
DIM h(4)

h(
1) = &H48
h(
2) = &H7A
h(
3) = &H72
h(
4) = &H93

PRINT a

FOR n = 0 TO 3
POKE VAR a, n, h(4-n)
NEXT n

PRINT STR$(a,10,10)


You might end up with problems if/when you use a 'mite with double precision floats.

Your code might be safe.
JimEdited by TassyJim 2018-03-29
VK7JH
MMedit
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 09:18pm 27 Mar 2018
Copy link to clipboard 
Print this post

Thanks Jim,

Think I tried STR$(a,6,2) at some stage this morning, but then went on a tangent & loaded 5.04.09 Beta 16 & thought that was the answer.

Phil.
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 09:36pm 27 Mar 2018
Copy link to clipboard 
Print this post

  TassyJim said  You might end up with problems if/when you use a 'mite with double precision floats.


Yep,

Just re-flashed the Beta to try & Poking the variable makes it return a zero value.

Phil.
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 09:25pm 28 Mar 2018
Copy link to clipboard 
Print this post

Think My Binary Math understanding has improved in the past few days.

Final solution seems to work fine.
No glaring Foo-pars or incorrect practices?

  Quote   'Converting IEEE754 Floating point number from Eastron Energy Meter.
'Request Example shows Hex 43708000 returned for 240.5 Volts
'First Bit is the Sign, & the next 8 bits are the Exponent, with an offset of 127
'The remaining 23 bits are the fractional part of the data. An implied 24th bit is added as 1.

'&H43708000 = 240.5V
'&HC3663334 = -230.2V
'&H45280939 = 2688.5764
'&H40AC49BA = 5.384

Do

Input "Hex Value: ", ReadingStr$ : ReadingStr$="&h"+ReadingStr$

Reading%=
Val(ReadingStr$)
Sign%=Reading% >>
31 'Read the Sign Bit
Expo%=((Reading% >> 23) And &hff) - 127 'Extract Exponent, Remove sign, Subtract Offset
Ans!=((Reading% Or &h800000) And &hffffff)/2^(23-Expo%)*(-1)^Sign% 'Extract Mantissa & Add implied 24th bit, Shift Point in Binary & apply sign

Print "Text Input String: ";ReadingStr$
Print "Hex Value Reading: ";Hex$(Reading%,8) 'Reading in Hex
Print "Binary Value: ";Bin$(Reading%,32) 'Reading in Binary
Print "Sign Bit: ";Hex$(Sign%)
Print "Exponent & -offset: ";Bin$(Expo%+127,8), Str$(Expo%)
Print "Mantissa Value: ";Bin$((Reading% Or &h800000) And &hffffff,32)
Print
Print "Returned Value: ";Str$(Ans!,10,4)
Print

Do While Inkey$="": Loop

Loop


Phil.
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6283
Posted: 10:24pm 28 Mar 2018
Copy link to clipboard 
Print this post

You have ended up with a nice useful function. It will be handy as double precision becomes more prevalent.

Jim
VK7JH
MMedit
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2170
Posted: 08:17am 29 Mar 2018
Copy link to clipboard 
Print this post

Hello Phil. Hope you are well.

I would like to see your very useful IEEE to MMBasic FP conversion Function in the new MMBasic library at http://www.fruitoftheshed.com/ this ensures it is preserved and is find-able for anyone in a similar situation.

Are you ok with this?

You can create the wiki page yourself to document the Function or I can if you prefer (you'll get the credit and there will be a pointer to this discussion)

Let me know how you are with this.

Thanks

Andrew
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025