Unexpected Behaviour

Good Day,

I am having some weird issues with a GPS based project. I am using an Adafruit Ultimate GPS breakout and an UNO. My code was made using tutorials I found online. It is supposed to read the GPS GPRMC sentence and then print it onto the serial monitor. It actually works, but I am getting extra spaces in the data. On top of that every time it prints the data to the serial monitor it also reprints what it is supposed to print only once from the setup loop. Am I missing something obvious?

Code:

#include <Adafruit_GPS.h>     //include library
#include <SoftwareSerial.h>   //include library

SoftwareSerial mySerial(3, 2);  //for GPS module (leave serial port for use

Adafruit_GPS GPS(&mySerial);    //GPS connection


byte byteGPS = 0;
int i = 0;
int h = 0;

char inBuffer[300] = "";
char GPS_RMC[100] = "";


void setup()
{
  Serial.begin(9600);
  GPS.begin(9600);

  Serial.println("GPS Sentence Test");
  Serial.flush();

  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
}

void loop()               
{
  byteGPS = 0;
  byteGPS = GPS.read();
  while(byteGPS != 'R')
  {
    byteGPS = GPS.read();
  }
  GPS_RMC[0]='

Any help would be greatly appreciated!

Cheers,
Berg;
  GPS_RMC[1]='G';
  GPS_RMC[2]='P';
  GPS_RMC[3]='R';

i = 4;
  while(byteGPS != '*')
  {
    byteGPS = GPS.read();
    inBuffer[i]=byteGPS;
    GPS_RMC[i]=byteGPS;
    i++;   
  }

Serial.print("RMC sentence: ");
  h = 0;
  while(GPS_RMC[h] != 42)
  {
    Serial.write(GPS_RMC[h]);
    h++;
  }
  Serial.println();
  delay(1000);
}


Any help would be greatly appreciated!

Cheers,
Berg

Here is the output from the monitor:

  i = 4;
  while(byteGPS != '*')
  {
    byteGPS = GPS.read();
    inBuffer[i]=byteGPS;
    GPS_RMC[i]=byteGPS;
    i++;   
  }

Normally, one would check that there was room in the array before writing to the array. These two arrays are different sizes.

    Serial.write(GPS_RMC[h]);

To send ASCII data? Why? That's what the print() method is for.

As to why setup() is being run again, I suspect that you are writing beyond the end of an array, and crapping on something you shouldn't be.

Thank you for the reply. The Serial.write was put in during troubleshooting, it was print before and it is print again. It does not change what I am seeing.

I think you are on to the problem with the arrays. I obviously don't understand how to handle them as well as I should. For instance I don't know how to check the size of an array (off to google that next).

Doing a complete power reset makes it come good again (no extra spaces, no repeated text from the setup loop) for a while, but then an extra space is added at the end of a sentence and the thing goes back to the image I posted.

Cheers,
Berg

For instance I don't know how to check the size of an array (off to google that next).

You don't need to check it. You defined it at the top of the file. What you need to do is check that the index variable is less than the size of the array before writing.

    if(i < 300) inBuffer[i]=byteGPS;
    if(i < 100) GPS_RMC[i]=byteGPS;

Of course, you could use the sizeof() function to check the actual size, or use:

const int inBufferSize = 300;
char inBuffer[inBufferSize);

.
.
.

   if(i < inBufferSize) inBuffer[i] = byteGPS;

Thank you very much! That has solved the repeatedly printing the statement from the setup loop, almost. I must have screwed up something pretty good.

I do have some other weirdness now though (see attached picture).

Updated code:

#include <Adafruit_GPS.h>     //include library
#include <SoftwareSerial.h>   //include library

SoftwareSerial mySerial(3, 2);  //for GPS module (leave serial port for use

Adafruit_GPS GPS(&mySerial);    //GPS connection


byte byteGPS = 0;
int i = 0;
int h = 0;

char inBuffer[300] = "";
char GPS_RMC[100] = "";

void setup()
{
  Serial.begin(9600);
  GPS.begin(9600);

  Serial.println("GPS Sentence Test");
  Serial.flush();

  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
}

void loop()               
{
  byteGPS = 0;
  byteGPS = GPS.read();
  while(byteGPS != 'R')
  {
    byteGPS = GPS.read();
  }
  GPS_RMC[0]='

Thanks again for the help, I really appreciate it.

Cheers,
Berg

;
  GPS_RMC[1]='G';
  GPS_RMC[2]='P';
  GPS_RMC[3]='R';

i = 4;
  while(byteGPS != '*')
  {
    byteGPS = GPS.read();
   
    if (i < 300) inBuffer[i]=byteGPS;
    if (i < 100) GPS_RMC[i]=byteGPS;
    i++;   
  }

Serial.print("RMC sentence: ");
  h = 0;
  while(GPS_RMC[h] != 42)
  {
    Serial.print(GPS_RMC[h]);
    h++;
  }
  Serial.println();
  delay(1000);
}


Thanks again for the help, I really appreciate it.

Cheers,
Berg

![GPSout2.jpg|1783x905](upload://k8HfqvwL3APtdpFWvkT6vZr6W8K.jpeg)

I really don't see the point in posting a picture of text. Just post the text. At least then I'd have a hope in hell of reading it.

Sorry, I tried to copy and paste from the serial monitor but it doesn't seem to work (just puts the first few things and that's it). I can't even get it to copy into any text editors.

I know it isn't what you want, but I've attached another screen grab (this one is legible, I failed to check before, my bad).

Trying to describe it: First line is the one from the setup loop as expected. Second line looks as it did before with the extra spaces. Then it seems to settle down, but it prints everything twice, and doesn't seem to make it to the end of the expected data (missing the first part of the GPS checksum. The second printing also doesn't have the "$GPR".

Sorry for the bad attachments.

Cheers,
Berg

What are you using inBuffer for? It seems to me as though you are wasting a lot of SRAM unnecessarily.

What is the Adafruit_GPS library contributing? Again, it appears that you are wasting SRAM creating an instance of this library that does nothing more than wrap the SoftwareSerial instance.

You are assuming that all the serial data from the GPS arrives at once. It does not. Therefore, you are reading faster than data can arrive, and stuffing a lot of -1's in your array(s).

Try this:

  while(byteGPS != '*')
  {
    int crap = GPS.read();
    if(crap > 0)
    {
        if (i < 300) inBuffer[i] = crap;
        if (i < 100) GPS_RMC[i] = crap;
        i++;
    }
    byteGPS = crap;
  }

The inBuffer was part of the example I was using to get started. I didn't think it was doing anything and removed it and the sketch stopped working (nothing was written to serial monitor).

The GPS library lets me send the command to tell the GPS unit what information I would like sent back, just the RMC for now.

I tried the code you gave me and it prints out (all on one line):

"RMC sentence: $GPRMC,140722.000,A,5104.8571,N,11407.7391,W,0.02,295.86,29$GPRMC,140723.000,A,5104.8572,N,11407.739 MC,140722.000,A,5104.8571,N,11407.7391,W,0.02,295.86,29$GPRMC,140723.000,A,5104.8572,N,11407.7393,W,0.03,342.07,290316,,,D* (LOTS OF BLANK SPACE) �~

The last few characters appear different on the monitor than here (square, accented e, etc).

It is definitely an improvement as I am now getting all the information in the part after the third $GPRMC. I admit I do have some confusion as to why it is either reading or writing the information multiple times for one reading.

As I understand it the GPS works like a serial device and sends one character at a time.

Thanks again for your help. I realize I'm not up to speed on this stuff.

Cheers,
Berg

I tried to copy and paste from the serial monitor but it doesn't seem to work (just puts the first few things and that's it).

Have you tried Ctrl/A to select and Ctrl/C to copy the text, assuming that you are using Windows.

berg9987:
... and removed it and the sketch stopped working (nothing was written to serial monitor).

Which indicates that you more than likely have a memory issue (e.g. buffer overflow). Have you tried to remove it after PaulS' comments?

UKHeliBob:
Have you tried Ctrl/A to select and Ctrl/C to copy the text, assuming that you are using Windows.

I did, no dice.

sterretje:
Which indicates that you more than likely have a memory issue (e.g. buffer overflow). Have you tried to remove it after PaulS' comments?

I just did, and it is working!

Now the output looks like this (extra long space is gone):

GPS Sentence Test
RMC sentence: $GPRMC,143323.000,A,5104.8575,N,11407.7474,W,0.02,247.53,290316,,,D
RMC sentence: $GPRMC,143324.000,A,5104.8575,N,11407.7475,W,0.01,213.45,29$GPRMC,143325.000,A,5104.8574,N,11407.747d

Every time I restart the unit the first output seems good (so long as the GPS has a lock). The sentences after that sentences after that are repeated and missing some information at the end. Every so often a good one appears again though.

Cheers,
Berg

I think I have it SOLVED!

As Paul said the data isn't coming in all at once, and I had no function in my sketch to really ensure that the data being read started at the beginning every time. I added a clearGPS loop from another example and called it once during the setup loop and at the end of the main loop. In the ten minutes it has been running it has given me reliable correct information. I will be running it for a few hours just to be sure.

Thank you everyone for your help, especially PaulS. I truly appreciate your advice and patience.

Cheers,
Berg

My now working code:

#include <Adafruit_GPS.h>     //include library
#include <SoftwareSerial.h>   //include library

SoftwareSerial mySerial(3, 2);  //for GPS module (leave serial port for use

Adafruit_GPS GPS(&mySerial);    //GPS connection


byte byteGPS = 0;
char c;
int i = 0;
int h = 0;

char GPS_RMC[100] = "";

void setup()
{
  Serial.begin(9600);
  GPS.begin(9600);

  Serial.println("GPS Sentence Test");
  Serial.flush();
  clearGPS();

  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
}

void loop()               
{
  byteGPS = 0;
  byteGPS = GPS.read();
  while(byteGPS != 'R')
  {
    byteGPS = GPS.read();
  }
  GPS_RMC[0]='

;
 GPS_RMC[1]='G';
 GPS_RMC[2]='P';
 GPS_RMC[3]='R';

i = 4;

while(byteGPS != '*')
 {
   int crap = GPS.read();
   if(crap > 0)
   {
       if (i < 100) GPS_RMC[i] = crap;
       i++;
       
   }
   byteGPS = crap;
 }

Serial.print("RMC sentence: ");
 h = 0;
 while(GPS_RMC[h] != 42)
 {
   Serial.print(GPS_RMC[h]);
   h++;
 }
 Serial.println();
 delay(1000);
 clearGPS();
}

void clearGPS() {  
while(!GPS.newNMEAreceived()) {
 c=GPS.read();
 }
GPS.parse(GPS.lastNMEA());
while(!GPS.newNMEAreceived()) {
 byteGPS=GPS.read();
 }
GPS.parse(GPS.lastNMEA());

}