Switch to desktop version  
Modbus Float value - Printable Version

+- Ewon Technical Forum (https://techforum.ewon.biz)
+-- Forum: Development (https://techforum.ewon.biz/forum-50.html)
+--- Forum: BASIC Script (https://techforum.ewon.biz/forum-52.html)
+--- Thread: Modbus Float value (/thread-1903.html)



Modbus Float value - spessi - 24-12-2021

Dear All,
I'm following a customer that is reading a float value thorugh Modbus Tcp IO server, but the modifier F and H embedded aren't able to read the correct value.
Checking the two registers with wireshark the raw value is:

3a b4 b8 41 >>> format ABCD

The correct reading must be 23.08 that it seems the format Little-Endian (DCBA) >>> I checked with Modbus Poll (see picture in attach) and with an online HEX converter ( https://www.scadacore.com/tools/programming-calculators/online-hex-converter/ ).
Ewon seems to be able to read float ABCD sequence ( 0.00137878221 ) or CDAB sequence ( -0.0000460694573 ).

Reading separately the two registers (called for example WL and WH), I'm able with a simple basic script to unpack each byte:

BA%=WL@
DC%=WH@
A%=(BA% / 256) MOD 255
B%=(BA% - (A%*256)) MOD 255
C%=(DC% / 256) MOD 255
D%=(DC% - (C%*256)) MOD 255
PRINT A% 
PRINT B%
PRINT C%
PRINT D%

A >>> 58    >>> hex 3A
B >>> 180  >>> hex B4
C >>> 184  >>> hex B8
D >>> 65   >>> hex 41

At this stage I'm not able to rebuild the right value 23.08 with the format DCBA.
I didn't find any way with the command embededd into the basic scripting.

Do someone have any suggestion to do that?

Thank you
Marco


RE: Modbus Float value - spessi - 28-12-2021

Here below a FUNCTION to convert two register (Low and Hgh) into a type FLOAT, passing the Modbus tags (WL@,WH@):

example of function call >>> floatDCBA@ = @DINT_TO_FLOAT(WL@,WH@)

////////////////////////////////////////////////////////////////
FUNCTION DINT_TO_FLOAT($regL,$regH)
CLS
// SINGLE BYTE ABCD
$BA%=$regL
$DC%=$regH
$A%=($BA% / 256) MOD 255
$B%=($BA% - ($A%*256)) MOD 255
$C%=($DC% / 256) MOD 255
$D%=($DC% - ($C%*256)) MOD 255
// DINT VALUE DCBA
$DCBA% = $D%*16777216 + $C%*65536 + $B%*256 + $A%
// CONVERSION DINT_TO_FLOAT
// EXPONENT
$espx% = (($DCBA% AND 2139095040) MOD 8388607) - 127
Print $espx%
// MANTISSA
$bitMantx% = $DCBA% AND 8388607
$mantx = ($bitMantx%#22)*(2^-1) + ($bitMantx%#21)*(2^-2) + ($bitMantx%#21)*(2^-3) + ($bitMantx%#19)*(2^-4) + ($bitMantx%#18)*(2^-5) + ($bitMantx%#17)*(2^-6) + ($bitMantx%#16)*(2^-7) + ($bitMantx%#15)*(2^-8)
$mantx = $mantx + ($bitMantx%#14)*(2^-9) + ($bitMantx%#13)*(2^-10) + ($bitMantx%#12)*(2^-11) + ($bitMantx%#11)*(2^-12) + ($bitMantx%#10)*(2^-13) + ($bitMantx%#9)*(2^-14) + ($bitMantx%#8)*(2^-15) + ($bitMantx%#7)*(2^-16)
$mantx = $mantx + ($bitMantx%#6)*(2^-17) + ($bitMantx%#5)*(2^-18) + ($bitMantx%#4)*(2^-19) + ($bitMantx%#3)*(2^-20) + ($bitMantx%#2)*(2^-21) + ($bitMantx%#1)*(2^-22) + ($bitMantx%#0)*(2^-23)
$mantx = 1.0 + $mantx
// SIGN AND FLAOT VALUE
PRINT $bitMantx%#31
$signBit%=$bitMantx%#31
IF $signBit% = 0 THEN
$DINT_TO_FLOAT = $mantx*2^$espx%
ELSE
$DINT_TO_FLOAT = -($mantx*2^$espx%)
ENDIF
ENDFN
////////////////////////////////////////////////////////////////

Ciao
Marco


RE: Modbus Float value - simon - 29-12-2021

Hello Marco,

Sorry for the late reply and thank you for your feedback :-)

I think the function FCNV could have been used as well :
ieee = 0.0
a$ = "1234"
a$(1) = Chr$(140)
a$(2) = Chr$(186)
a$(3) = Chr$(9)
a$(4) = Chr$(194)
ieee = FCNV a$,2
PRINT ieee // This will print -34.432176

Just in case your hand made function does not work in all cases...

Simon