3

I have a raspberry Pi and my environment is C#. Basically I am sending GPS (GPRMC) data across a wireless device. The Rx wireless device reads the data and strips out unnecessary info. The Tx side is sending a GPRMC message (I am using bray terminal)

$24GPRMC,123123.00,A,2753.13285,N,08232.29411,W,0.021,,011113,,,D*6D

When I use CuteCom on the RPi I get this:

\0xaa\0x02G\0xf0y\0x7fE,\0x12 \0xc6\0x00\0xa1-\0xcfU

regular (hex output box unchecked)

or this in hex (when the hex output box IS checked):

aa 02 47 f0 79 7f 45 2c   12 20 c6 00 a1 2d cf 55 

The hex is the expected message, as it has all the relevant data I need (start, id, date, lat, long, lrc, end).

I have set up my C# code to read the serial data, but cannot seem to get it to display data in that fashion.

This is what I have so far in C#:

        public static void Main ()
    {
        SerialPort serial = new SerialPort ("/dev/ttyUSB0", 115200);
        serial.Open ();


        while (true) 
        {
            string data = ReadData(serial);

            if(!string.IsNullOrEmpty(data))
            {
                Console.WriteLine(data);

            }
        }
    }

    public static string ReadData (SerialPort serial)
    {
        string rxString = "";

        rxString += serial.ReadExisting();

        return rxString;
    }

for the output I get:

?G?yE, ??-?U

I have also tried stream reader, but that doesn't work:

    public static string ReadData2 (System.IO.Stream s)
    {

        StreamReader sr = new StreamReader (s);
        DataString = sr.ReadLine ();

        return DataString;
    }

and I have also tried using Bit Converter I found in another post.

    private static string ReadData3 (SerialPort serial)
    {
        GPSrxString += serial.ReadExisting();
        string GPSrxStringhex = BitConverter.ToString(Encoding.ASCII.GetBytes(GPSrxString));

        return GPSrxString;
    }

So after all of that, I'm stuck. Where have I gone wrong. What do I need to do to get that proper/desired hex output?

EDIT: I used strings here, but I ended up finding out that strings aren't the way to go, it's unnecessary. Use an array to hold all the values and go from there. You can calculate needed numbers like UTC in the answers below.

Jonathan Nath
  • 71
  • 1
  • 12

3 Answers3

4

Looks like the data is binary, but your ReadData implementation treats it as an ASCII string (hence the weird characters). Try reading in the binary data, then converting that into a string representation of the values in hex:

public static string ReadData(SerialPort serial)
{
    byte[] buffer = new byte[serial.BytesToRead];
    serial.Read(buffer, 0, buffer.Length);

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < buffer.Length; i++)
        sb.AppendFormat("{0:X2} ", buffer[i]);

    return sb.ToString();
}
Chris Ballard
  • 3,771
  • 4
  • 28
  • 40
  • @JonathanNath what do you actually need to do with the values? They are byte values, so value is correct, the choice of decimal/hex is just a way to present it in human readable form. Can you give an example of the next step? – Chris Ballard Mar 13 '14 at 13:16
  • So as it turns out, I dont need it as a string. I do need to read the hex values. I see the buffer has the correct values, but how do I obtain the hex values into a float variable. for instance buffer[0]=170,buffer[1]=2,buffer[2]=71...in hex they would be 0xAA,0x02,and 0x47 respectively. also these values once concatenated need to be in float. 0x47f0797f = 123122.99 – Jonathan Nath Mar 13 '14 at 13:17
  • so element 0 is the head of the message 0xAA, element 1 is the device ID 0x02 in this case. elements 2 to 5 represent time. in this case they are 0x47 0xf0 0x79 0x7f. The url below converts the hex to float, the result is 123122.99, that is the expected output. http://gregstoll.dyndns.org/~gregstoll/floattohex/ – Jonathan Nath Mar 13 '14 at 13:21
  • added a new answer, as this is a new part of the question. In case this is of interest to other people - you may want to edit the question itself and add the comments above to it. – Chris Ballard Mar 13 '14 at 13:54
1

To answer the second part of your question, as per comments on my first answer:

Assuming you have this data:

byte[] data = new byte[] {0xAA, 0x02, 0x47, 0xF0, 0x79, 0x7F};

We need to skip the first two bytes, then take the remaining four bytes. We also need to reverse the order of bytes before we can convert to floating point:

byte[] data2 = data.Skip(2).Take(4).Reverse().ToArray();

Now we can convert:

float val = System.BitConverter.ToSingle(data2, 0);
Chris Ballard
  • 3,771
  • 4
  • 28
  • 40
0

I've always used this type of code:

public static string ReadData (SerialPort s)
{
    string DataString = "";
    int nByte = s.BytesToRead;
    for (i=0;i<nByte;i++)
    {
        int byteTemp = s.ReadByte();
        DataString += (char)(byteTemp);
    }
    return DataString;
}

This is a direct translation from VB.Net, I'm not sure if the sintax is 100% correct.

AlexF
  • 487
  • 1
  • 5
  • 16