Read serial data into string and work with it.

Hello guys,

i usually only read this forum, but now i got stuck on a task and apparently cant find a solution myself.
Obviously i’m quite new in Arduino programming, but did a few small projects with copy and paste snippets and some own code derived from that.

Hardware: Arduino Pro Mini ATMega328P
GUI: 1.8.5

I have a Ublox7 GPS Module on a software serial port (12,11)
From this device, i get the following data with “Serial.write(mySerial.read())”:

?????????????????????????????????????????????????????????????<- those are backwards
$GPRMC,141320.00,A,4734.90390,N,01037.56812,E,0.027,,180120,,,A*70
$GPVTG,,T,,M,0.027,N,0.050,K,A*23
$GPGGA,141320.00,4734.90390,N,01037.56812,E,1,07,1.30,807.1,M,47.0,M,,*5B
$GPGSA,A,3,17,19,24,12,13,15,20,,,,,,2.54,1.30,2.18*07
$GPGSV,3,1,10,01,01,034,,12,25,223,40,13,45,150,46,15,64,203,46*7E
$GPGSV,3,2,10,17,39,089,34,19,34,119,44,20,20,285,41,24,51,289,47*7D
$GPGSV,3,3,10,28,31,051,26,30,02,093,*7B
$GPGLL,4734.90390,N,01037.56812,E,141320.00,A,A*66

In between the data, which is coming seamless, i get a lot of reversed question marks.
I only need the data from the last line.

My idea was to check for the “GPGLL” expression and the record the data in a string to work with.
Unfortunately i’m not able to do that.
Could you provide my an example which i could adapt to make it work?
A good example (or a link) for how to use the correct function would already be enough.

my last try was with “mySerial.readString()” but i dont know how to make it stop reading.
In the Arduino description it says only by timeout…

Thank you and best regards
Tobi

Unfortunately i'm not able to do that.

Why not? Show us what you tried.

It's pretty simple, actually. There is a start marker - $. There is an end marker - the carriage return. Start storing the data when the start marker arrives. Stop storing, and use the data, when the end marker arrives.

See Robin2's Serial Input Basics - Updated post.

Serial input basics.

I think there is an Arduino library for parsing GPS data.

…R

GPS parsers.
TinyGPS.
[NeoGPS/url.

Check if the following two sketches (tested using UN0-sender and NANO-receiver) are helpful for you. If yes, then parse the received ASCII formatted data string to retrieve the individual 'data item' like 4734.90390, 01037.56812, and 141320.00.

UNO Sketch: (sender which simulated data string)

#include<SoftwareSerial.h>
SoftwareSerial SUART(12, 11);  //SRX = 12, STX = 11

char myData[] = "$GPGLL,4734.90390,N,01037.56812,E,141320.00,A,A*66";  //data string 

void setup() 
{
  Serial.begin(9600);
  SUART.begin(9600);
}

void loop() 
{
  SUART.write(myData, sizeof(myData)); 
  Serial.println(myData);
  SUART.write('\n');  //Newlie as END Mark
  delay(2000); //test interval
}

NANO Sketch: (receiver)

#include<SoftwareSerial.h>  //neede to create SUART Port
SoftwareSerial SUART (12, 11); //SRX = 12, STX = 11
char myData[100];  //to hold data
char msgHeader[10]; //to  hold $GPGLL, (the header)
bool flag = false;
int i = 0;
char myData1[10]; //to hold DataItem1 in ASCII fromat

void setup()
{
  Serial.begin(9600);
  SUART.begin(9600);
}
void loop()
{
  byte n = SUART.available();//check if a charcater has arrived and stored in FIFO BUFFer
  if (flag == false)  //$GPGLL, (the header) not yet found
  {
    if (n == 7)  //7-charcater header (the:$GPGLL,)
    {
      for (i = 0; i < 7; i++)
      {
        msgHeader[i] = SUART.read(); //copy header from FIFO BUFFer to local array
      }
      msgHeader[++i] = '\0';  //null character as last elemnt in string array
      if (strcmp(msgHeader, "$GPGLL,") == 0)//comparing two strings
      {
        flag = true;  //the: $GPGLL, is found
        Serial.println("Header Found.");
      }
    }
  }
  else
  {
    byte m = SUART.readBytesUntil('\n', myData, 100);//receive and save data
    myData[m] = '\n';  //insert null charcater
    Serial.println(myData); //pront the data received in ASCII format
    //-- add codes to parse data string to retrive individual data items
    int j = 0;
    do
    {
      myData1[j] = myData[j];
      //Serial.println(myData[j]); //shows: 4 7 3 4 . 9 0 3 9 0
      j++;
    }
    while (myData1[j-1] != ',');
    myData1[j-1] = '\0'; //null character
    float dataItem1 = atof(myData1);  //convert ASCII coded value to flot value
    Serial.println(dataItem1, 5); //shows: 4734.90380; why not: 4734.90390?
    flag = false;
  }
}

Receiver Serial Monitor
smD1.png

smD1.png

My idea was to check for the “GPGLL” expression and the record the data in a string to work with.

This example code uses the serial input basics example #2 to read GPS sentences and keep only the GPGLL sentence, in a string, for further processing. The strstr() function.

// Robin2's Example 2 - Receive with an end-marker modified to work with software serial
// retrieve $GPGLL sentance from GPS string.
// by groundfungus aka c. goulding

#include <SoftwareSerial.h>

SoftwareSerial ssPort(4, -1);  // Uno pin 4 to GPS TX pin.  GPS RX not connected

const byte numChars = 64;
char receivedChars[numChars];   // an array to store the received data
char gglLine[64];
boolean newData = false;

void setup()
{
   Serial.begin(115200);
   ssPort.begin(9600);
   Serial.println("<Arduino is ready>");
}

void loop()
{
   recvWithEndMarker();
   getGLLdata();
   //showNewData();
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (ssPort.available() > 0 && newData == false)
   {
      rc = ssPort.read();

      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

void getGLLdata()
{
   if (newData == true)
   {

      if (strstr(receivedChars, "$GPGLL") )
      {
         strcpy(gglLine, receivedChars);
         Serial.print("This just in ... ");
         Serial.println(gglLine);
      }
      newData = false;
   }
}

See example 5 of the tutorial for an example using strtok() to break the sentence down further.

Note that if you want to check the correct reception of the message you have to recalculate the checksum.
In this case must consider the message without the '$' and without the "*xx" (where xx is the "transmitted" checksum).

You can find a C code example at wiki.