Code Won't Register that GPS is Sending Signals

Hello, thank you for taking the time to read my post.

I am trying to build a GPS guided robot based upon this(https://www.instructables.com/id/How-to-Build-a-GPS-Guided-Robot/) instructable.

I have had to heavily modify the code because I am using a newer magnetometer and a different gps module. The GPS I am using is Goouuu Tech GT-U7, their website lists this datasheet.

https://translate.googleusercontent.com/translate_c?depth=1&hl=en&prev=search&rurl=translate.google.com&sl=cs&sp=nmt4&u=https://drive.google.com/file/d/1VG6fHMfjlsQuf91JFCPol-2hnCXNHOh2/view%3Fusp%3Ddrive_open&xid=17259,15700021,15700186,15700190,15700256,15700259,15700262,15700265&usg=ALkJrhjnurrZXzDMIDSkgOrKGyYJnSMJLQ

I am using the tinyGPSPlus library, and it worked perfectly until a week ago. The code would register and print how many satellites I was connected to on Monday. On Wednesday(when the part I needed came in) despite no changes being made to the code, it stopped working. I figured maybe someone else changed it, so I reverted to a backup I had and it still didn't work. I tried a new GPS module, it still didn't work. However, the deviceExample from tinyGPS does display how many satellites are connected. I am not sure why, but I'm guessing it has to do with either the arduino I'm using, or the Encode function. I am unsure of how to implement the encode function into the larger project, and I hope I don't have to seeing as I didn't need it before.

I am using a mega2560 and have bluetooth, a motorshield, an ultrasound sensor, and a magentometer connected to it. I have had issues with memory before, but thought I had it resolved, so I don't expect it to be that.

I really appreciate any help, if you need me to upload the tinyGPSPlus library(or anything else) I can.

Sorry about the 9 attachments, 8 of them are one program, it is split up into multiple files, they're all one program except for device example, which is the one which will actually read the GPS. If you don't want to deal with the whole program you really only need GPS_Guided_RoboEVERYTHINGWORKSDONOTEDIT.ino and Startup.ino.

Bluetooth.ino (4.34 KB)

Collision_Avoid.ino (1.22 KB)

Go_Waypoint.ino (3.68 KB)

GPS_Compass.ino (7.41 KB)

GPS_Guided_RoboEVERYTHINGWORKSDONOTEDIT.ino (9.85 KB)

Startup.ino (1.37 KB)

Steering.ino (14.6 KB)

Sweep.ino (1.05 KB)

DeviceExample.ino (6.86 KB)

I have had issues with memory before, but thought I had it resolved, so I don't expect it to be that.

No, you haven't resolved it, never use the String class on AVR Arduinos:

String str;                                                        // raw string received from android to arduino

During the time you wait for 4 satellites to become visible (it this realistic in your location?), you should print out debugging information to have an idea if there is any satellite visible or none at all. Did you check the hardware, the antenna, etc.?

The code no longer crashes the way it did when I had memory issues, so I don't think it is a problem, but what should I use instead of string?

4 is feasible, I am usually getting 6 or 7- while inside next to a window. I am certain satellites are visible, because the deviceExample.ino I attached shows them. The hardware all works, at least for the device example.

Instructables are usually pretty awful, written by people who have little to no idea what they are doing. In general, we recommend to avoid them.

Make sure to get the GPS module functioning with the example code provided by TinyGPS before trying to build it into your robot code. Of course, you must be outside, with a clear view of the sky, for it to work.

Instead of Strings, use C-strings, or zero terminated character arrays. There is an entire library of short functions (string.h) that allow you to manipulate C-strings and if used correctly, they work without causing memory problems.

One of many on line references: C Library -

One of many on line tutorials: C - Strings

Sawyer7887:
4 is feasible, I am usually getting 6 or 7- while inside next to a window. I am certain satellites are visible, because the deviceExample.ino I attached shows them. The hardware all works, at least for the device example.

Do not assume that just because x number of satellites are 'visable' that you will have a fix.

The GPS might see x number of satellites but the signals can be so weak that they cannot be used to establish a fix.

Pretty sure I have a fix. And it actually doesn't matter if I have a fix because the code is based upon how many are visible, the problem isn't with the GPS, it works with the device example.

And it actually doesn't matter if I have a fix

Actually, it matters a great deal.

See it matters eventually, but for right now I just want to deal with the problem of the code not registering that the GPS has visible satellites. It having a fix doesn't matter if the code can't see that it does.
And even if it does matter, I have a fix, so we don't need to worry about it.

jremington:
Actually, it matters a great deal.

Indeed it does.

Ok so I think I found the issue, but I'm not sure how to implement it. I wrote a really simple program that just prints the # of satellites, it doesn't do anything else. It prints 0, so I started commenting things out on the DeviceExample until it printed 0 too.

It started printing 0s when I commented out

//while (Serial3.available() > 0){

So now the code looks like

TinyGPSPlus gps;

void setup()
{
  Serial.begin(115200);
  Serial3.begin(9600);
}

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  //while (Serial3.available() > 0){
    if (gps.encode(Serial3.read()));
 Serial.println(gps.satellites.value());
   
   //displayInfo();

}

Any advice for implementing a while(Serial3.available) into the real program?

This seems stupid as hell, and unsurprisingly it still reads 0.

while (Serial3.available() > 0){
    while (Number_of_SATS <= 4)                         // Wait until x number of satellites are acquired before starting main loop
   //while (GPSpoof < 0);
  {                                  
    getGPS();                                         // Update gps data
    Number_of_SATS = (int)(gps.satellites.value());   // Query Tiny GPS for the number of Satellites Acquired       
    bluetooth();                                      // Check to see if there are any bluetooth commands being received     
  }    
  setWaypoint();                                      // set intial waypoint to current location
  wpCount = 0;                                        // zero waypoint counter
  ac = 0;                                             // zero array counter
  
  Serial1.print(Number_of_SATS);
  Serial1.print(" Satellites Acquired");    
}    
}

The extremely simple code works if I add in the encode snippet as well, but adding those into the larger program doesn't solve the issue.

Any advice for implementing a while(Serial3.available) into the real program?

You already do that but in your code (see below) you use Serial2 to access the GPS. It's definitely to for you to provide a complete wiring diagram of your setup!

void getGPS()                                                 // Get Latest GPS coordinates
{
    while (Serial2.available() > 0)
    gps.encode(Serial2.read());

}

Pretty sure I have a fix.

There is no need to be uncertain about it.

The GPS unit very clearly announces whether it has a valid fix. If it doesn't have a valid fix, there is no point in attempting to use the GPS output for navigating.

It is mildly interesting, but rarely useful, to know how many satellites the unit has detected.

jremington:
There is no need to be uncertain about it.

The GPS unit very clearly announces whether it has a valid fix. If it doesn't have a valid fix, there is no point in attempting to use the GPS output for navigating.

It is mildly interesting, but rarely useful, to know how many satellites the unit has detected.

Indeed, just checking my logs and I can see an ocaision when the GPS had detected 12 satellites, but still had no fix and there are good reasons for that.

And even though there were 12 satellites in view, TinyGPSplus would report 0 satellities since the GPS did not have a fix.

Sawyer7887:
I just want to deal with the problem of the code not registering that the GPS has visible satellites.

I think you are confused between satellites that are visible and satellites that are being used for navigation. TinyGPSplus reports the later (by default) and only does so once the GPS has a fix.

You can get at the number of visible satellites, there is an example in the TinyGPSplus on how to do it, but knowing the number is of little consequence.

Thanks for pointing out that I had accidentally left Serial2 in there, I must've missed that one when I switched to Serial3. After fixing this, the error remains, I did double check that I hadn't missed any others. If you would still like me to make a wiring diagram I will.

I am certain I have a fix, as I am getting location data from the GPS and the light is blinking. I assume that I am grabbing the number of satellites being used to navigate, I am using Serial.println(gps.satellites.value())

I realized one of the few differences between the sketch that works and the one that doesn't: the one that doesn't uses Number_of_SATS instead of directly calling the data. So I tried replacing all of those with direct calls for the data, and commenting out where Number_of_SATS was defined. It didn't fix it. I wondered if I missed some, so I decided to write a simple sketch that uses the variable to see if it would work.

#include <TinyGPS++.h>
TinyGPSPlus gps;
int satNumber = gps.satellites.value();

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
Serial3.begin(9600);

}

void loop() {
 
Serial.println(satNumber);
delay(30);
Serial.println(gps.satellites.value());
}

This printed 0 for both values.

Then I figured maybe it isn't the variable, but something that I didn't include from the working sketch. So I wrote a version of this without the variable.

#include <TinyGPS++.h>
TinyGPSPlus gps;

void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);
Serial3.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
Serial.println(gps.satellites.value());
}

This didn't work either.

I saw another post in the forum where Jremington said that calls like this pull from previously received data, so is the problem that I am not reading the GPS before this? If it is, I am not sure why the main sketch doesn't work, as it reads the GPS before the call. Am I missing something obvious? Thank you to everybody who has helped so far.

How is thisint satNumber = gps.satellites.value(); supposed to be properly populated when this information is unknown at the time of info request?

Here is the code I use that works great and lasts a long time:

#include <TinyGPS++.h>
TinyGPSPlus GPS;
void setup()
{
GPSSerial.begin ( GPS_DataBits, SERIAL_8N1, 2, 15 ); // begin GPS hardware serial
xTaskCreatePinnedToCore( fGPS_Parse, "fGPS_Parse", TaskStack10K3, NULL, Priority5, NULL, TaskCore0 ); // assigned to core 0
  sema_GPS_Gate = xSemaphoreCreateMutex();
  xSemaphoreGive( sema_GPS_Gate );

}
void fGPS_Parse(  void *pvParameters )
{
  int iBit = 1;
  for (;;)
  {
    xEventGroupWaitBits (eg, evtGPS_Parse, pdTRUE, pdTRUE, portMAX_DELAY) ;
    if ( xSemaphoreTake( sema_GPS_Gate, xTicksToWait0 ) == pdTRUE )
    {
      //query GPS: has a new complete chunk of data been received?
      if ( GPSSerial.available() > 1 )
      {
        if ( GPS.encode(GPSSerial.read()) )
        {
          if (  GPS.location.isValid())
          {
            if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
            {
              xPosit.Lat = GPS.location.lat();// store data into structure
              xPosit.Lon = GPS.location.lng();
              xSemaphoreGive( sema_Posit );
            }
          } // if (  GPS.location.isValid())
          if (GPS.speed.isValid())
          {
            if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
            {
              xPosit.MPH = GPS.speed.mph();
              xPosit.KPH = GPS.speed.kmph();
              xSemaphoreGive( sema_Posit );
            }
          } //  if (GPS.speed.isValid())
          if (GPS.time.isValid())
          {
            if ( xSemaphoreTake( sema_Time, xSemaphoreTicksToWait ) == pdTRUE )
            {
              xTime.iSeconds = GPS.time.second();
              xTime.iMinutes = GPS.time.minute();
              xTime.iHours = GPS.time.hour();
              xSemaphoreGive( sema_Time );
            }
          } // if (GPS.time.isValid())
          if (GPS.date.isValid())
          {
            if ( xSemaphoreTake( sema_Date, xSemaphoreTicksToWait ) == pdTRUE )
            {
              xDate.iMonth = GPS.date. month();
              xDate.iDay = GPS.date.day();
              xDate.iYear = GPS.date.year();
              xSemaphoreGive( sema_Date );
            }
          } // if (GPS.date.isValid())
          if (  GPS.altitude.isValid() )
          {
            if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
            {
              xPosit.Alti = GPS.altitude.meters();
              xSemaphoreGive( sema_Posit );
            }
          } //  if (  GPS.altitude.isValid() )
          if ( GPS.course.isUpdated() )
          {
            if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
            {
              xPosit.Hdg = GPS.course.deg();
              xSemaphoreGive( sema_Posit );
            }
          } // if ( GPS.course.isUpdated() )
          if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
          {
            xQueueOverwrite( xQ_Posit, (void *) &xPosit );
            xSemaphoreGive( sema_Posit );
          }
        } // if ( GPS.encode(GPSSerial.read()))
      } // if ( GPSSerial.available() > 0 )
      xSemaphoreGive( sema_GPS_Gate );
    }
  } // for (;;)
  vTaskDelete( NULL );
} // void fGPS_Parse(  void *pvParameters )

fGPS_Parse() is triggered to run once every mS.

That's a great point, thank's for showing me. I really appreciate you uploading this code as well, though I am having trouble implementing it.
here's my new setup:

void setup() 
{  
  Serial.begin(115200);
  Serial1.begin(9600);

  myservo.attach(9);
  //Serial3.begin(9600);
  // Ping Sensor
  pinMode(trigPin, OUTPUT);                                        // Ping Sensor
  pinMode(echoPin, INPUT);                                         // Ping Sensor                                                    // Join I2C bus used for the HMC5883L compass
  compass.begin();  
  compass.setOffset(550,-260); //untested

GPSSerial.begin ( GPS_DataBits, Serial3, 14, 15); // begin GPS hardware serial
xTaskCreatePinnedToCore( fGPS_Parse, "fGPS_Parse", TaskStack10K3, NULL, Priority5, NULL, TaskCore0 ); // assigned to core 0
  sema_GPS_Gate = xSemaphoreCreateMutex();
  xSemaphoreGive( sema_GPS_Gate );
  
  
  
  // Pre-fill the sample buffer
  for (unsigned i = 0; i < SampleCount; i++)
  {
    AddSample();
    delayMicroseconds(SampleIntervalMicroseconds);  // Crude, but close enough for the first second.
  }
  LastSampleTime = micros();
  // Do this line for each value:
  SampleAverage = SampleTotal / SampleCount;
  fGPS_Parse();
  Startup();                                                       // Run the Startup procedure on power-up one time
}

and I trimmed fGPS_parse to just what I needed, so I'll include that as well, as I may have screwed that up.

void fGPS_Parse(  void *pvParameters )
{
  int iBit = 1;
  for (;;)
  {
    xEventGroupWaitBits (eg, evtGPS_Parse, pdTRUE, pdTRUE, portMAX_DELAY) ;
    if ( xSemaphoreTake( sema_GPS_Gate, xTicksToWait0 ) == pdTRUE )
    {
      //query GPS: has a new complete chunk of data been received?
      if ( GPSSerial.available() > 1 )
      {
        if ( GPS.encode(GPSSerial.read()) )
        {
          if (  GPS.location.isValid())
          {
            if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
            {
              xPosit.Lat = GPS.location.lat();// store data into structure
              xPosit.Lon = GPS.location.lng();
              xSemaphoreGive( sema_Posit );
            }
          } // if (  GPS.location.isValid())
          
          if ( GPS.course.isUpdated() )
          {
            if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
            {
              xPosit.Hdg = GPS.course.deg();
              xSemaphoreGive( sema_Posit );
            }
          } // if ( GPS.course.isUpdated() )
          if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
          {
            xQueueOverwrite( xQ_Posit, (void *) &xPosit );
            xSemaphoreGive( sema_Posit );
          }
        } // if ( GPS.encode(GPSSerial.read()))
      } // if ( GPSSerial.available() > 0 )
      xSemaphoreGive( sema_GPS_Gate );
    }
  } // for (;;)
  vTaskDelete( NULL );
} // void fGPS_Parse(  void *pvParameters )

When I attempt to compile this fGPS gives me an error on the if GPSSerial.available line, claiming that GPSSerial wasn't declared. Also, I notice GPSSerial doesn't define baudrate, do I need to do that before declaring GPSSerial? Should I uncomment the Serial3.begin?

Thanks so much for your help.

The code posted was written for a ESP32, you'll have to figure out the differences required for your board.

Such as your board may not have freeRTOS or multiple cores or initialize serial ports the same way.