News:

Let's find out together what makes a PIC Tick!

Main Menu

Hex array to float conversion

Started by shantanu@india, May 13, 2022, 02:54 AM

Previous topic - Next topic

shantanu@india

Hi,
Successfully communicating a PIC with a Schneider EM6400NG multifunction meter over RS485 Modbus to get regular data.
Problem is how to convert the hex array [43,6C,B3,33] into the corresponding float value 236.7?
I tried myFloat. Byte3  = 43, myFloat. Byte2 = 6C etc. but that didn't work.
Any pointers?
Regards
Shantanu

trastikata

Quote from: shantanu@india on May 13, 2022, 02:54 AMAny pointers?

Positron is using MC FP representation while, you are looking in your hex array at the standard IEE754 FP format. Just convert it from the IEE754 FP using standard math sign bit * (exponent - 127 as offset) * matissa

Gabi

Try this:

Dim yrInitialFloat As Float
Dim expectedFloat As Float

Main:    
    yrInitialFloat.Byte0 = $43   '// this should be the order
    yrInitialFloat.Byte1 = $6c   '// when loading your bytes
    yrInitialFloat.Byte2 = $b3   '// from array
    yrInitialFloat.Byte3 = $33   '//
   
    While 1 = 1
        DelayMS 1000
        expectedFloat = toMchip(yrInitialFloat)
        HRSOutLn "Result = ", Dec3 expectedFloat
    Wend

Proc toMchip(IEEE754 As Float), Float
    Dim fTemp As Float  '// work with a copy
    fTemp = IEEE754     '// if you want to keep the passing float param intact
    Rol fTemp.Byte1            
    Rol fTemp.Byte0             
    Ror fTemp.Byte1 
    Result = fTemp    
EndProc
GL & 73
YO4WM

top204

Also, see page 26 of the compiler's manual.

It has the conversion code for Microchip to IEEE-754 and IEEE-754 to Microchip.

shantanu@india

Regards
Shantanu

John Drew

@shantanu@india I noticed that you had byte2 = 6c.
Without the $ sign to indicate hex.
Otherwise you could have used byte2=108 but I suspect it was a typo. :)
John

Yasin

$define IEEE754_MChip(pVar) '
'
'
'
'
Rol pVar.Byte1
Rol pVar.Byte0
Ror pVar.Byte1
'-------------------------------------------------------------------------------
' Convert the Microchip variable passed, to an IEEE-754 format
' Input     : pVar holds the Microchip format floating point variable
' Output    : pVar will be converted to IEEE-754 format
' Notes     : pVar must be a Float type variable and not a constant value
'
$define MChip_IEEE754(pVar) '
'---------------------------------------------------------------------------------
' Demo to convert Microchip and IEEE-754 floating point formats
'
Main:
MChip_IEEE754(MyFloat)       ' Convert MyFloat to IEEE-754 format
IEEE754_MChip(MyFloat)       ' Convert MyFloat back to Microchip format
Rol pVar.Byte1
Ror pVar.Byte0
Ror pVar.Byte1

Dear Les, I tried to explain before. But I was not successful. This example is very nice, but there is an overlooked error. I noticed it while reading data from energy analyzer in a modbus application. My mcu was generally reading correctly. Sometimes it was misreading. It's been a while, I don't remember the exact value. It was making more mistakes at values below 1.30 Volts. So I realized. When using ROL and ROR, the bit lost when returning was 0, and it was returned as 1. This causes the value to deteriorate. There is no problem when the returned bit is 1. Solution proposal; First, the bit in the direction of rotation must be stored in a flag. The flag stored with the rotation needs to be loaded into the new entry. You will understand better what I mean in the example I gave.

Device=18F25K20
Declare Xtal=8
Dim i As Byte
Dim bTemp1 As Byte
Dim BTemp2 As Word
DelayMS 100
Input PORTB
bTemp1 = PORTB
Main:
    DelayMS 1000
    HSerOut [Bin8 BTemp2,13,10]
    If bTemp1 <> PORTB Then
        bTemp1 = PORTB
        BTemp2 = bTemp1
    EndIf
'    ROL bTemP2 ' This is wrong
    Rol BTemp2,BTemp2.7 'That's right
GoTo Main

tumbleweed

#7
I don't see anything wrong with those two macros (except for the cut-and-paste errors in the example code you posted).

Perhaps there was something else going on?

'-------------------------------------------------------------------------------
' Convert the IEEE-754 variable passed, to a Microchip format
' Input : pVar holds the IEEE-754 format floating point variable
' Output : pVar will be converted to Microchip format
' Notes : pVar must be a Float type variable and not a constant value
'
$define IEEE754_MChip(pVar) '
Rol pVar.Byte1  '
Rol pVar.Byte0  '
Ror pVar.Byte1

'-------------------------------------------------------------------------------
' Convert the Microchip variable passed, to an IEEE-754 format
' Input : pVar holds the Microchip format floating point variable
' Output : pVar will be converted to IEEE-754 format
' Notes : pVar must be a Float type variable and not a constant value
'
$define MChip_IEEE754(pVar) '
Rol pVar.Byte1  '
Ror pVar.Byte0  '
Ror pVar.Byte1


Yasin

ROR and ROL are just scrolling. There is a problem if flag is not used. In other words, when the byte is rotated in one direction, the overflowing bit must be moved to the bit in the other direction. For this reason, the flag should be used. It will be clearer if you simulate the example I gave above with ISIS.

If you use this when compiling, overflow bits that are one low will come up high on the other.
Rol bTemP2 ' This is wrong
It will work correctly if you use this when compiling.
Rol BTemp2,BTemp2.7 'That's right

Yasin

#9

tumbleweed

ROL and ROR instructions on the PIC go through the CARRY flag, and if you follow the three instruction sequences in those macros you'll see that it works correctly.

Yasin

I guess I couldn't explain it. There is no problem with ROL and ROR. It works as expected. The problem is in the example on page 26 of the positron manual. In this example there is a partial error while converting to Float. I mean this needs to be fixed.

tumbleweed

The example shown on pg 26 of the manual is correct.

MODBUS doesn't define a floating-point format, but there's a good chance that if your device sends floats it's in IEEE format. If it "mostly worked" then you know at least you have the byte order correct.

After receiving the four bytes, convert it to mchip format using IEEE754_MChip() and then use that value in your code.

To send data back to the device, first convert it back to IEEE using MChip_IEEE754() and then send it.


Yasin

IEEE-754 to Microchip. I used it, noticed the error and fixed it. The part you don't understand;
For example:
pVar.Byte1 with all bits zero (0x00000000). Returned once with the ROL is pVar.Byte1 (0x00000001). This is the cause of the error. If the 7th bit shifting to the left is 1, there is no problem because the new bit coming from the right is 1, but if the 7th bit shifting to the left is 0, the bit from the right is 1. So bit 0 becomes 1.

Yasin

#14
I thought a little. I went through my old archives. I encountered the error I mentioned in 2021. Or older. There is a slightly different example in the manual in older versions. Old manuel page 25.

Format        Exponent    Mantissa 0  Mantissa 1  Mantissa 2
IEEE-754      sxxx xxxx   yxxx xxxx   xxxx xxxx   xxxx xxxx
Microchip     xxxx xxxy   sxxx xxxx   xxxx xxxx   xxxx xxxx

IEEE-754 to Microchip
  Rlf Mantissa0
  Rlf Exponent
  Rrf Mantissa0

Microchip to IEEE-754
  Rlf Mantissa0
  Rrf Exponent
  Rrf Mantissa0


Some devices can change the byte order. Because of that. I used the following way to sort when necessary.

Proc FloatToMicrochip(pExponent As Byte,pMantissa0 As Byte,pMantissa1 As Byte,pMantissa2 As Byte),Float
    GB1 = pMantissa0.7
    GB2 = pExponent.7
    Rol pExponent, GB1
    pMantissa0.7 = GB2
    Result.Byte0 = pExponent
    Result.Byte1 = pMantissa0
    Result.Byte2 = pMantissa1
    Result.Byte3 = pMantissa2
EndProc

Here are those links. Maybe it'll be of use to someone perhaps.

https://www.scadacore.com/tools/programming-calculators/online-hex-converter/

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

tumbleweed

#15
QuoteIEEE-754 to Microchip. I used it, noticed the error and fixed it. The part you don't understand;
For example:
pVar.Byte1 with all bits zero (0x00000000). Returned once with the ROL is pVar.Byte1 (0x00000001). This is the cause of the error.
I understand it quite well.

The examples from the two different manuals are exactly the same. There is no error in either one. ROL=RLF=RLCF and ROR=RRF=RRCF.

The bit value "rotated" in or out depends on the state of the CARRY flag.
As I said, if you follow the sequence of instructions through ALL THREE STEPS, you find out that what gets shifted into pVar.Byte1 in the first step (ROL pVar.Byte1) gets shifted back out in the third step (ROR pVar.Byte1).

Here's how it works, step by step:
Rol pVar.Byte1  ' get Mantissa0 y into Carry (shifts don't care bit into lsb)
Rol pVar.Byte0  ' shifts Carry (mantissa0 y) into lsb of Exponent, shifts Exponent s into Carry
Ror pVar.Byte1  ' shift Carry (Exponent s) into msb of Mantissa0, don't care bit from step 1 drops off