0

This is my first post so please let me know what to do better next time.

I am trying to send data as byte arrays over serial. I have checked several posts but none seemed to work for me. I started to make a quick console app for testing the conversions.

This is the struct I want to receive over serial port:

public struct DataStructSend
{
    public UInt32 int1;
    public UInt32 int2;
    public UInt32 int3;
    public float float1;
    public float float2;
    public float float3;
}

First I start with generating a dummy string that contains the byte[] of my struct for the received data.

Here is the code for generating said string:

//Just generating dummy serial data to "read"
List<byte> data = new List<byte>();

DataStructSend dataStruct = new DataStructSend();

UInt32 int1 = 1;
UInt32 int2 = 2;
UInt32 int3 = 3;
float float1 = 16524.0000003F;
float float2 = 13524.0000002F;
float float3 = 25524.0000001F;



byte[] byteLine = BitConverter.GetBytes(int1);
data.AddRange(GetByteList(byteLine));
byteLine = BitConverter.GetBytes(int2);
data.AddRange(GetByteList(byteLine));
byteLine = BitConverter.GetBytes(int3);
data.AddRange(GetByteList(byteLine));

byteLine = BitConverter.GetBytes(float1);
data.AddRange(GetByteList(byteLine));
byteLine = BitConverter.GetBytes(float2);
data.AddRange(GetByteList(byteLine));
byteLine = BitConverter.GetBytes(float3);
data.AddRange(GetByteList(byteLine));

byte[] dataBytes = data.ToArray();

data.Add(0x0A);
Debug.WriteLine(data.Count());


for (int i = dataBytes.Count()-1; i >=0; i--)
{
    Debug.Write(dataBytes[i] + " ");
}
Debug.WriteLine("");

string line = System.Text.Encoding.Default.GetString(dataBytes);



//Here we have the Serial "received data"
            
Debug.Write("The data is -->");
Debug.Write(line);
Debug.WriteLine("<--");

I already checked and understood the struct alignement and padding. This is my I am using uint32 for all variables (except float, but they are 4 bytes too).

Until there everything seems fine. My application returns:

Started...
1 0 0 0 
2 0 0 0 
3 0 0 0 
0 24 129 70 
0 80 83 70 
0 104 199 70 
25
70 199 104 0 70 83 80 0 70 129 24 0 0 0 0 3 0 0 0 2 0 0 0 1 
The data is -->*unknown characters*<--

After this I convert it back to my struct:

//Remove the newline (is there when port.Readline())
line = line.Trim();




byte[] recevedBytes = Encoding.ASCII.GetBytes(line);

Debug.Write("Sent Bytes (" + dataBytes.Count() + ")\t\t\t--> ");
for (int i = dataBytes.Count() - 1; i >= 0; i--)
{
    Debug.Write(dataBytes[i] + " ");
}
Debug.WriteLine("");

//Issue is here

//Printing the converted byte array, the uint32 values are the same, but not the float. they are somehow random. float2 seems to be correct
Debug.Write("Received Bytes (" + recevedBytes.Count() + ")\t\t--> ");
for (int i = recevedBytes.Count() - 1; i >= 0; i--)
{
    Debug.Write(recevedBytes[i] + " ");
}
Debug.WriteLine("");



//Checking the struct is empty and has same size as received data
byte[] dataStructBytes = GetBytes(dataStruct);



dataStruct = FromBytes(recevedBytes);


//Printing the new struct
foreach (var field in typeof(DataStructSend).GetFields(BindingFlags.Instance |
                                        BindingFlags.NonPublic |
                                        BindingFlags.Public))
{
    Debug.WriteLine("{0} = {1}", field.Name, field.GetValue(dataStruct));
}

The result shows that only the uint32 variables were identically matching:

Sent Bytes (24)         --> 70 199 104 0 70 83 80 0 70 129 24 0 0 0 0 3 0 0 0 2 0 0 0 1 
Received Bytes (24)     --> 70 63 104 0 70 83 80 0 70 63 24 0 0 0 0 3 0 0 0 2 0 0 0 1 
int1 = 1
int2 = 2
int3 = 3
float1 = 12230
float2 = 13524
float3 = 12250

What could cause the problem for this? Or does anyone has a more efficient solution of transfering a struct based data packet from an 8bit microcontroller to a 64bit word application?

Here is the full code:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ConverstionTest
{
    class Program
    {
        public static List<byte> GetByteList(byte[] array)
        {
            List<byte> returnList = new List<byte>();
            for (int i = 0; i < array.Count(); i++)
            {
                Debug.Write(array[i] + " ");
                returnList.Add(array[i]);
            }
            Debug.WriteLine("");
            return returnList;
        }

        public struct DataStructSend
        {
            public UInt32 int1;
            public UInt32 int2;
            public UInt32 int3;
            public float float1;
            public float float2;
            public float float3;
        }

        public static byte[] GetBytes(DataStructSend str)
        {
            int size = Marshal.SizeOf(str);
            byte[] arr = new byte[size];

            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(str, ptr, true);
            Marshal.Copy(ptr, arr, 0, size);
            Marshal.FreeHGlobal(ptr);
            return arr;
        }

        public static DataStructSend FromBytes(byte[] arr)
        {
            DataStructSend str = new DataStructSend();

            int size = Marshal.SizeOf(str);
            IntPtr ptr = Marshal.AllocHGlobal(size);

            Marshal.Copy(arr, 0, ptr, size);

            str = (DataStructSend)Marshal.PtrToStructure(ptr, str.GetType());
            Marshal.FreeHGlobal(ptr);

            return str;
        }

        static void Main(string[] args)
        {
            Debug.WriteLine("Started...");


            //Just generating dummy serial data to "read"
            List<byte> data = new List<byte>();

            DataStructSend dataStruct = new DataStructSend();

            UInt32 int1 = 1;
            UInt32 int2 = 2;
            UInt32 int3 = 3;
            float float1 = 16524.0000003F;
            float float2 = 13524.0000002F;
            float float3 = 25524.0000001F;



            byte[] byteLine = BitConverter.GetBytes(int1);
            data.AddRange(GetByteList(byteLine));
            byteLine = BitConverter.GetBytes(int2);
            data.AddRange(GetByteList(byteLine));
            byteLine = BitConverter.GetBytes(int3);
            data.AddRange(GetByteList(byteLine));

            byteLine = BitConverter.GetBytes(float1);
            data.AddRange(GetByteList(byteLine));
            byteLine = BitConverter.GetBytes(float2);
            data.AddRange(GetByteList(byteLine));
            byteLine = BitConverter.GetBytes(float3);
            data.AddRange(GetByteList(byteLine));

            byte[] dataBytes = data.ToArray();

            data.Add(0x0A);
            Debug.WriteLine(data.Count());


            for (int i = dataBytes.Count()-1; i >=0; i--)
            {
                Debug.Write(dataBytes[i] + " ");
            }
            Debug.WriteLine("");

            string line = System.Text.Encoding.Default.GetString(dataBytes);



            //Here we have the Serial "received data"
            
            Debug.Write("The data is -->");
            Debug.Write(line);
            Debug.WriteLine("<--");




            //Remove the newline (is there when port.Readline())
            line = line.Trim();




            byte[] recevedBytes = Encoding.ASCII.GetBytes(line);

            Debug.Write("Sent Bytes (" + dataBytes.Count() + ")\t\t\t--> ");
            for (int i = dataBytes.Count() - 1; i >= 0; i--)
            {
                Debug.Write(dataBytes[i] + " ");
            }
            Debug.WriteLine("");

            //Issue is here

            //Printing the converted byte array, the uint32 values are the same, but not the float. they are somehow random. float2 seems to be correct
            Debug.Write("Received Bytes (" + recevedBytes.Count() + ")\t\t--> ");
            for (int i = recevedBytes.Count() - 1; i >= 0; i--)
            {
                Debug.Write(recevedBytes[i] + " ");
            }
            Debug.WriteLine("");



            //Checking the struct is empty and has same size as received data
            byte[] dataStructBytes = GetBytes(dataStruct);



            dataStruct = FromBytes(recevedBytes);


            //Printing the new struct
            foreach (var field in typeof(DataStructSend).GetFields(BindingFlags.Instance |
                                                 BindingFlags.NonPublic |
                                                 BindingFlags.Public))
            {
                Debug.WriteLine("{0} = {1}", field.Name, field.GetValue(dataStruct));
            }



        }
    }
}

2
  • System.Text.Encoding.Default and System.Text.Encoding.ASCII are an unusual way to encode and decode a byte[] to a string. Any reason you're not using Convert.ToBase64String and Convert.FromBase64String? Commented Nov 13, 2020 at 21:03
  • Hello! I am receiving a struct as a byte array from an 8 bit microcontroller. Can I change the base anyway? I think the base from the sent data is 8bit not 64bit right? Commented Nov 14, 2020 at 11:47

1 Answer 1

1

You encode String using Encoding.Default, and decode using Encoding.ASCII. Default is not ASCII.

Sign up to request clarification or add additional context in comments.

2 Comments

Hi! Thanks for the very quick answer. I don´t get the same result when I convert from ACII to ASCII. But I do get the correct result when I convert from Default to Default. What is the "Port.ReadLine" encoding?
I suppose you mean SerialPort. It has property named Encoding, which controls it - by default it is ASCII

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.