0

I want to send some serial values to my PC.

Arduino with sensors (master) >> via Bluetooth >> Arduino (slave) >> via serial com port >> PC with C# app

Serial transmission works well from master to slave, but how can I receive and convert the values received to floats on the PC side using C#?

Slave code is:

Struct definition

 typedef struct {
  char bt1;
  float bt2; 
  float bt3; 
  float bt4;
  float bt5;
  float bt6;
  float bt7;  
  char bt8;
  } PayloadBT;
  PayloadBT payloadBT;  

Struct sent to pc

BT_writeAnything(0, payloadBT);


template <class T> long int BT_writeAnything(int ee, T& valuebt)
{
  Serial.write('/');
  Serial.write((char *) &valuebt, sizeof(valuebt));
}

On PC app:

using System;
using System.IO.Ports;
using System.Threading;

 public struct PayloadSerial
{
    public char bt1;
    public float bt2;
    public float bt3;
    public float bt4;
    public float bt5;
    public float bt6;
    public float bt7;
    public char bt8;
  }

namespace ConsoleApp1
{
    class Program
    {
    static SerialPort _serialPort;
    static char rc;


        public static  void Main()
        {
            _serialPort = new SerialPort();
            _serialPort.PortName = "COM7";//Set your board COM
            _serialPort.BaudRate = 9600;
            _serialPort.Open();
            PayloadSerial payloadSerial;

            while (true)
            {
                someText = (byte)_serialPort.ReadChar();
                rc = someText;
                if (rc == '/')
                {
                    byte* p = (byte*)&payloadSerial;
                    int i;
                    for (i = 0; i < 26; i++)
                    {
                        *p++ = (byte)_serialPort.ReadChar();
                    }

                    if (payloadSerial.bt1 == '<' && payloadSerial.bt8 == '>') {

                    Console.WriteLine(payloadSerial.bt2);
                    Console.WriteLine(payloadSerial.bt3);
                    Console.WriteLine(payloadSerial.bt4);
                    Console.WriteLine(payloadSerial.bt1);
                    Console.WriteLine(payloadSerial.bt8);
                    Console.WriteLine(payloadSerial.bt5);
                    Console.WriteLine(payloadSerial.bt6);
                    Console.WriteLine(payloadSerial.bt7);
                        Thread.Sleep(10);   
                    }
                }
            }
        }
    }
}

What I receive is : Error CS0214 Pointers and fixed size buffers may only be used in an unsafe context. If I declare as unsafe I receive strange values ended with E-39

4.408201E-39
5.785725E-39
7.255092E-39
# this char value is correct
W this char value is correct 
5.785725E-39
5.785725E-39
7.347765E-40

I am using Visual Studio as my IDE.

Euro Micelli
  • 33,285
  • 8
  • 51
  • 70
hunt333r
  • 3
  • 3
  • After you read "/" char read into an byte array and then use [this](https://stackoverflow.com/questions/2871/reading-a-c-c-data-structure-in-c-sharp-from-a-byte-array) method to create your struct from byte array. And if you want to continue use your current implementation you need to used [fixed](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/fixed-statement) statement – Eldar Nov 27 '19 at 19:01
  • can you please give me a more exact response ? i try to use the examples provided but i get only errors – hunt333r Nov 28 '19 at 19:22

1 Answers1

0

The problem probably stems from the fact that you use default SerialPort.Encoding. And it is

An Encoding object. The default is ASCIIEncoding.

That means that each byte will get its highest bit set to 0, as explained in SerialPort encoding - how do I get 8 bit ASCII?

The solution proposed there is to use

_serialPort.Encoding = System.Text.Encoding.GetEncoding(1252);

It would probably work, but I'd rather recommend you to use the ReadByte method instead as it does exactly what it says

someText = _serialPort.ReadByte();
rc = someText;
if (rc == '/')
{
    byte* p = (byte*)&payloadSerial;
    int i;
    for (i = 0; i < 26; i++)
    {
        *p++ = _serialPort.ReadByte();

There may also be (additionally)

  1. an issue with endianness (though both x86 and arduino seem to be little-endian).
  2. or an issue with incompatible struct layout/padding (probably not, but still a possibility)

P.S. Also, as it has been already pointed in the comment it may be better to read all bytes into an array and create the structure from it with Reading a C/C++ data structure in C# from a byte array

Eugene Podskal
  • 10,270
  • 5
  • 31
  • 53