Converting Float Variables to Byte Arrays and Back Using .NET

We regularly create microcontroller designs that use a serial interface for testing or control.  In those designs it’s common to have a variety of variable types.  We might have 16-bit signed integers mixed with unsigned bytes and 32-bit floating point variables.

To send and receive data using a serial interface we need to convert data to a serial array so we can send a stream of bytes.  In the microcontroller this can easily be done using unions.

union LongUnion
    {
    long LW;
    unsigned long uLW;
    int W[2];
    unsigned int uW[2];
    char B[4];
    unsigned char uB[4];
    float FLT;
    };
union LongUnion
MyTemp;

MyTemp union allows you to copy a variety of variable types and easily break them into bytes.  LW (long word) shares the same memory as FLT (floating point values) and uB[4] (an array of 4 unsigned characters).

Say we want to copy a 32-bit unsigned variable to a byte array.  Place the variable in MyTemp.uLW and its byte components can be accessed via MyTemp.uB[0] (LSB), MyTemp.uB[1], MyTemp.uB[2], and MyTemp.uB[3] (MSB).

Example…

if MyTemp.uLW = 0xFF783309

Then

MyTemp.uB[0] = 0x09

MyTemp.uB[1] = 0x33

MyTemp.uB[2] = 0x78

MyTemp.uB[3] = 0xFF
Its pretty simple to break down integers this way.  You can use masks and or bit shifting to convert values.  But let’s also consider floating point variables.

In the example below we  copy a float variable, an unsigned word, a signed word, and two unsigned characters over our byte array to send to our serial port…

unsigned char TXArray[10];

float FloatValue;
unsigned int UnsignedIntValue;
int SignedIntValue;
unsigned char CharacterValue1;
unsigned char CharacterValue2;


MyTemp.FLT = FloatValue;
TXArray[0] = MyTemp.uB[0];
TXArray[1] = MyTemp.uB[1];
TXArray[2] = MyTemp.uB[2];
TXArray[3] = MyTemp.uB[3];
MyTemp.uW[0] = UnsignedIntValue;
TXArray[4] = MyTemp.uB[0];
TXArray[5] = MyTemp.uB[1];
MyTemp.W[0] = SignedIntValue;
TXArray[6] = MyTemp.uB[0];
TXArray[7] = MyTemp.uB[1];
TXArray[8] = CharacterValue1;
TXArray[9] = = CharacterValue1;

Send_Serial(TXArray);

This places our variables into an array of bytes that we can send through our serial port hardware.

NOTE:  We do a lot of Microchip designs, and use their XC8 compiler with their 8-bit chips.  In the case of XC8 floating point variables default to a 24-bit truncated version.  To interface with .NET using Visual Basic you really want your floating point variable to be in the IEEE 754 32-bit format.  In XC8 this is done by changing the compiler options.  The option is under project properties –> XC8 Linker / Memory Model options.

 

image

 

Let’s say we’ve sent the serial data in TXArray out the microcontrollers serial port, and it has been received by a computer running a Visual Studio application (in this case Visual Studio 2010 with .NET 4.0, although this technique is also available in newer versions of .NET).

The sent data is now in a variable byte array called RXArray…

Using “BitConverter” we can pull the information out of the received serial data array in the correct format.  Since our float variable is located  in RXArray locations 0-3, we just call BitConverter and tell it to convert to a “Single” variable type the data in RXArray starting at an offset of 0.  BitConverter will convert the bytes in RXArray locations 0 through 3 to a Single (32-bit floating point single precision  variable).

To convert the unsigned and signed 16-bit values in the received byte array you do the same thing but change “convert to value” and the RXArray offset.   The unsigned integer is located in RXArray bytes 4 andf 5.  The signed  integer is located in RXArray btyes 6 and 7.    Bytes 8 and 9 contain character values, which can also be converted.

 

    Private Sub ConvertSerialData(RXArray As Byte())


        Dim FloatVariable As Single
        Dim UnsignedIntVariable As UInt16
        Dim SignedIntVariable As Int16
        Dim Char1 As Char
        Dim Char2 As Char

        FloatVariable = BitConverter.ToSingle(RXArray, 0)
        UnsignedIntVariable = BitConverter.ToUInt16(RXArray, 4)
        SignedIntVariable = BitConverter.ToInt16(RXArray, 6)
        Char1 = BitConverter.ToChar(RXArray, 8)
        Char2 = BitConverter.ToChar(RXArray, 9)


    End Sub

 

Using the BitConverter class in .NET makes converting between data types pretty simple.  The only thing you really need to keep an eye on is the order of the data you’ve broken into bytes and sent via a serial link.  Sending your data LSB first works with BitConverter and the MyTemp variable as shown in this example.

Speak Your Mind

*