TinyGPS running in loop - SOLVED

I have some Tiny GPS code I want to run either in the loop of a main program (where I have other subroutines running) or as its own subroutine.

If i just have the GPS code in its own sketch it runs fine but if I add it to my larger program the While loop doesnt seem to run (no print statements occur). The working sketch is;

#include <TinyGPS.h>

TinyGPS gps;

int year;

byte month, day, hour, minute, second, hundredths;
unsigned long chars;
unsigned short sentences, failed_checksum;

void setup()
{

    Serial.begin(9600);
    Serial3.begin(9600);
    Serial.println("");
    Serial.println("GPS Shield QuickStart Example Sketch v12");
    Serial.println(" ...waiting for lock... ");
    Serial.println("");
}

void loop()
{
    while(Serial3.available())
    {
        int c = Serial3.read();
        if(gps.encode(c))
        {
            float latitude, longitude;
            gps.f_get_position(&latitude, &longitude);
            Serial.print("Lat/Long: ");
            Serial.print(latitude,5);
            Serial.print(", ");
            Serial.println(longitude,5);
            gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
            Serial.print("Date: ");
            Serial.print(month, DEC);
            Serial.print("/");
            Serial.print(day, DEC);
            Serial.print("/");
            Serial.print(year);
            Serial.print(" Time: ");
            Serial.print(hour, DEC);
            Serial.print(":");
            Serial.print(minute, DEC);
            Serial.print(":");
            Serial.print(second, DEC);
            Serial.print(".");
            Serial.println(hundredths, DEC);
            Serial.print("Altitude (meters): ");
            Serial.println(gps.f_altitude());
            Serial.print("Course (degrees): ");
            Serial.println(gps.f_course());
            Serial.print("Speed(kmph): ");
            Serial.println(gps.f_speed_kmph());
            Serial.print("Satellites: ");
            Serial.println(gps.satellites());
            Serial.println();
           
             
            // adding cardinal course
            Serial.print("Cardinal Compass course  ");
            Serial.println(gps.cardinal(gps.f_course()));
            

            gps.stats(&chars, &sentences, &failed_checksum);
        }
    }
}

Is it a timing issue? -

Search for topics like "Do several things at the sam time", maybe "Do many…", written by @Robin2.

In that spirit I suggest:

while(Serial3.available())
    {
        int c = Serial3.read();
        if(gps.encode(c))
        {
            float latitude, longitude;
            gps.f_get_position(&latitude, &longitude);
            Serial.print("Lat/Long: ");
            Serial.print(latitude,5);
            Serial.print(", ");
            Serial.println(longitude,5);
            gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
            Serial.print("Date: ");
            Serial.print(month, DEC);
            Serial.print("/");
            Serial.print(day, DEC);
            Serial.print("/");
            Serial.print(year);
            Serial.print(" Time: ");
            Serial.print(hour, DEC);
            Serial.print(":");
            Serial.print(minute, DEC);
            Serial.print(":");
            Serial.print(second, DEC);
            Serial.print(".");
            Serial.println(hundredths, DEC);
            Serial.print("Altitude (meters): ");
            Serial.println(gps.f_altitude());
            Serial.print("Course (degrees): ");
            Serial.println(gps.f_course());
            Serial.print("Speed(kmph): ");
            Serial.println(gps.f_speed_kmph());
            Serial.print("Satellites: ");
            Serial.println(gps.satellites());
            Serial.println();
           
             
            // adding cardinal course
            Serial.print("Cardinal Compass course  ");
            Serial.println(gps.cardinal(gps.f_course()));
            

            gps.stats(&chars, &sentences, &failed_checksum);
        }
    }

To be:

if(Serial3.available())// Change suggested by Railroader
    {
        int c = Serial3.read();
        if(gps.encode(c))
        {
            float latitude, longitude;
            gps.f_get_position(&latitude, &longitude);
            Serial.print("Lat/Long: ");
            Serial.print(latitude,5);
            Serial.print(", ");
            Serial.println(longitude,5);
            gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
            Serial.print("Date: ");
            Serial.print(month, DEC);
            Serial.print("/");
            Serial.print(day, DEC);
            Serial.print("/");
            Serial.print(year);
            Serial.print(" Time: ");
            Serial.print(hour, DEC);
            Serial.print(":");
            Serial.print(minute, DEC);
            Serial.print(":");
            Serial.print(second, DEC);
            Serial.print(".");
            Serial.println(hundredths, DEC);
            Serial.print("Altitude (meters): ");
            Serial.println(gps.f_altitude());
            Serial.print("Course (degrees): ");
            Serial.println(gps.f_course());
            Serial.print("Speed(kmph): ");
            Serial.println(gps.f_speed_kmph());
            Serial.print("Satellites: ");
            Serial.println(gps.satellites());
            Serial.println();
           
             
            // adding cardinal course
            Serial.print("Cardinal Compass course  ");
            Serial.println(gps.cardinal(gps.f_course()));
            

            gps.stats(&chars, &sentences, &failed_checksum);
        }
    }

Look at the change, an if instead of while in the beginning.
What du You think?
Note that all other code belove must be none hanging, none waiting.
No task should be finished in one step. Do a little bit at the time.

Thankyou.

I did look at that myself and tried an IF instead of the WHILE but that didn't seem to help. I will check again today and look at Robins examples.

Like you I would have thought the IF would have helped a lot but it didnt seem to when I first tried it.

Its almost like serial 3 isnt staying open?

Will let you know how it goes. :slight_smile:

When You start up the GPS it takes some time to find enough number of satellites. That can be minutes.
Try to print out that data, the number of sattelites, as early as it is available.

In the test sketch (not in my loop), it gets the fix very quickly (seconds) as it has a good backup battery system.

Will keep trying....

I've stated stepping through it and the sketch halts after.....

void GPS() {
  if(Serial3.available())
    {Serial.print("Lat/Long: ");
        int c = Serial3.read();
        
        if(gps.encode(c))
        {......//rest of code

If i put a print test (int c) after if(gps.encode(c)). It doesnt print, so the encode function isnt running?

I add it to my larger program

Which you did not post. How do you expect us to help with that?

You need to be collecting characters from the GPS as soon as they are ready, otherwise you won't get complete GPS sentences, and TinyGPS won't ever report an update.

All other functions must have lower priority than getting characters from the GPS. Execute slow functions, like printing, only when you have an update available.

This is the code I use for my NEO-6M.

void loop()
{
  int tmp, tmpa;
  float ftmp;

  while (mySerial.available())
    gps.encode(mySerial.read());

You should define the variable c as char, not int, I think.

And... keep the while…...

Sorry to reiterate but the sketch below works fine on its own with a WHILE or an IF and gets data very quickly, even with the Serial.prints running.

Its only when I add it as a sub to my bigger loop it doesnt return ‘c’.

#include <TinyGPS.h>

TinyGPS gps;

int year;

byte month, day, hour, minute, second, hundredths;
unsigned long chars;
unsigned short sentences, failed_checksum;
unsigned long speed;
void setup()
{

    Serial.begin(9600);
    Serial3.begin(9600);
    Serial.println("");
    Serial.println("GPS Shield QuickStart Example Sketch v12");
    Serial.println(" ...waiting for lock... ");
    Serial.println("");
}

void loop()
{
    if(Serial3.available())
    {
        int c = Serial3.read();
        if(gps.encode(c))
        {
            float latitude, longitude;
            gps.f_get_position(&latitude, &longitude);
            Serial.print("Lat/Long: ");
            Serial.print(latitude,5);
            Serial.print(", ");
            Serial.println(longitude,5);
            gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths);
            Serial.print("Date: ");
            Serial.print(month, DEC);
            Serial.print("/");
            Serial.print(day, DEC);
            Serial.print("/");
            Serial.print(year);
            Serial.print(" Time: ");
            Serial.print(hour, DEC);
            Serial.print(":");
            Serial.print(minute, DEC);
            Serial.print(":");
            Serial.print(second, DEC);
            Serial.print(".");
            Serial.println(hundredths, DEC);
            Serial.print("Altitude (meters): ");
            Serial.println(gps.f_altitude());
            Serial.print("Course (degrees): ");
            Serial.println(gps.f_course());
            Serial.print("Speed(kmph): ");
            Serial.println(gps.f_speed_kmph());
Serial.print("Speed(mph): ");
            Serial.println(gps.f_speed_mph());
            
            Serial.print("Satellites: ");
            Serial.println(gps.satellites());
            Serial.println();
            speed = gps.speed();
           Serial.print("Speed: ");
           Serial.println(gps.speed());
           
            Serial.println();
             
            // adding cardinal course
            Serial.print("Cardinal Compass course  ");
            Serial.println(gps.cardinal(gps.f_course()));
            

            gps.stats(&chars, &sentences, &failed_checksum);
        }
    }
}

Sorry i havent put all other code but its huge (vehicle control system) and i’m not sure it is relevant to int c not returning…

i'm not sure it is relevant to int c not returning.

Of course it is, and until you figure that out, you won't get anywhere.

Sorry, i'm not trying to be annoying and should have probably phrased the question better .....

so what might stop if(gps.encode(c)) returning if the sketch is a sub in a larger loop?

Nothing stops it from "returning". It always returns.

Please reread reply #6, as that explains what is most likely the problem.

I tried cutting out all the serial prints and now just have.....

[codevoid GPS() {
  if (Serial3.available())
  { 
    int c = Serial3.read();

    if (gps.encode(c))
      Serial.println("Lat/Long222: ");
    {
      gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
      Serial.print(" Time: ");
      Serial.print(hour, DEC);
      Serial.print(":");
      Serial.print(minute, DEC);
      Serial.print(":");
      Serial.print(second, DEC);
      Serial.print(".");
    
      gps.stats(&chars, &sentences, &failed_checksum);
    }
  }

}]

but time isnt being updated.

I hope my understanding of post 6 is correct

Take another look at that code.

You have broken the entire "if" statement by adding the print before the curly brace.

sorry quick edit on the forum and accidental delete.

This sketch doesnt display at all and stops at the gps.encode line. I cant see how i can make it much simpler...

and i have double checked baud rate etc. and know the wiring and hardware are good.

void GPS() {
  if (Serial3.available())
  {
    int c = Serial3.read();

    if (gps.encode(c))
    {
      gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
     
      Serial.print(" Time: ");
      Serial.print(hour, DEC);
      Serial.print(":");
      Serial.print(minute, DEC);
      Serial.print(":");
      Serial.print(second, DEC);
      Serial.print(".");
      gps.stats(&chars, &sentences, &failed_checksum);
    }
  }

}

287 posts and you STILL don't understand that you need to post ALL the code?

Bye.

Sorry the full code is huge so to help I have shortened it to show the problem with just an OLED section running.

With the oled code in setup the GPS runs fine.

With the OLED code it the loop the GPS stalls.

#include <TinyGPS.h>
TinyGPS gps;
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long chars;
unsigned short sentences, failed_checksum;
float latitude, longitude;

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include "RTClib.h"

#define dc   A2
#define cs   53
#define rst  4
#define mosi A7//currently i/o sp2
#define sclk A8//currently i/o sp2

#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define WHITE           0xFFFF

Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, mosi, sclk, rst); //no sclk,mosi on hw spi oled

void setup(void) {
  
}
void loop()
{
  Serial.begin(9600);
  Serial3.begin(9600);
  tft.begin();
  tft.setRotation(2);
  tft.fillRect(0, 0, 128, 128, BLACK);
  tft.setCursor(30, 5);
  tft.setTextColor(WHITE);
  tft.setTextSize(2);
  tft.println("Suzuki");
  tft.setTextSize(4);
  tft.println(" 101 ");
  delay (1000);

  GPS();
}


void GPS() {
  if (Serial3.available())
  {
    //Serial.println("Lat/Long: ");
    int c = Serial3.read();

    if (gps.encode(c))
    {
      
      gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
      
      Serial.print(" Time: ");
      Serial.print(hour, DEC);
      Serial.print(":");
      Serial.print(minute, DEC);
      Serial.print(":");
      Serial.print(second, DEC);
      Serial.print(".");
      gps.stats(&chars, &sentences, &failed_checksum);
    }
  }

}

Make a construction using millis that makes the OLED code run once per second and GPS every loop turn, and drop that delay. It's a possible troublemaker.

unsigned long time_for_OLED = millis();

setup()
{
.
.
}

loop()
{
   if( miliis() > time_for_OLED )
   {
      OLED();// OLED code…...
      time_for_OLED += 1000;
   }
   GPS();
}

Thanks Railroader.

I did try dropping the delay assuming it was an issue and it didnt make a difference.

I will look at the constructor idea but I have about 10 subroutines to do that with!!!

It still seems like there is some fundamental issue if only simple OLED code wont run in the loop with the GPS?

Cheers

Functions that need a high frequency of service should be called every time in loop. Less urgent functions can be called at their needed intervalls. You likely have a large project and You surely need to have control of how the controller capacity is used.
Take a look at the principals for "doing several things at the same time" (something like that) written by @Robin2. They are really good! Using that strategy I once made experienced space, satellite programmers look like newbies, telling my mission was imposible.