GPS sketch reduces loop speed by 50%

As part of an investigation into loop speed I have discovered that a GPS function (based on OP SMET’s work) when commented out speeds up the loop considerably.

The declarations/library are;

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

The loop runs the following to supply the Wait time.

gpsWaitFix (1);
bool gpsWaitFix(uint16_t waitSecs)
{
  //waits a specified number of seconds for a fix, returns true for good fix
  uint32_t endwaitmS;
  uint8_t GPSchar;
  uint32_t endFixmS;
 
  endwaitmS = millis() + (waitSecs * 1000);

  while (millis() < endwaitmS)
  {
    if (Serial3.available() > 0)
    {
      GPSchar = Serial3.read();
      gps.encode(GPSchar);
    }
    if (gps.location.isUpdated() && gps.course.isUpdated() && gps.satellites.isUpdated() && gps.date.isUpdated() && gps.speed.isUpdated())
    {
      endFixmS = millis();

      courseDeg = (gps.course.deg());
      return true;
    }
  }
  return false;
}

Is there anyway to speed this up or call it in some other way? I do need to see constant GPS readings.

Why the wait?
If there’s nothing to read from the GPS, return false.

I (probably incorrectly) thought that Wait was a minimum time needed for a fix to be encoded and received?

I must be misunderstanding what Wait does.

I don't know what your particular GPS receiver does but the one I used sent the current location plus a load of other data as a stream of serial data called a 'sentence' every second. From this I extracted the data I wanted. Writing your own code to do this might seem daunting but you will learn loads and feel very satisfied when you finish.

If it's serial start with Robin2's serial input basics tutorial.

Thanks Perry

I believe the library encode function is pretty good at getting specific data from the NMEA sentence and as in the sketch I have extracted exactly what I need.

I tried removing the Wait element all together but the GPS doesnt return anything then so I need to understand exactly what that is doing first I think.

All I know right now is not running GPS doubles the speed of my loop!

Obviously at startup, your program needs to wait for a satellite fix. After that, usually not, but it is wise to check, because if the fix is temporarily lost, the current location will not be updated.

That is what function calls like this are for:

gps.location.isUpdated()

You do need something like this in loop():

 if (Serial3.available() > 0)
    {
      GPSchar = Serial3.read();
      gps.encode(GPSchar);
    }

kpg:
I must be misunderstanding what Wait does.

You are.

gpsWaitFix() just sets a limit on how long to wait for an updated fix, there are many reasons why you may want to do this.

If the GPS is running and has satellite reception then typically an updated fix appears in less than a second or so and the routine exits as true. If the GPS has failed or otherwise does not have a fix then you get to choose the timeout.

If you want to read the GPS on a continuous basis then do so, but you will still only get an updated fix about once a second.

For the applications that use gpsWaitFix() loop speed is not an issue and you cannot get new information out of the GPS faster that it can provide it.

smet

Thankyou for the explanation. So it is just an optional timeout setting, good.

So as the GPS reads out whenever it can, why does commenting it out double my loop speed? I still dont really understand that....

Because every time you call that function, you waste a second.

Ok, so it is a timeout and the effect is also its adds the wait time to the loop when called.

So ignoring the need for timeouts I tried to just run....

in loop

 gpsWaitFix ();

and in function

bool gpsWaitFix()
{
  
  uint8_t GPSchar;
     if (Serial3.available() > 0)
    {
      GPSchar = Serial3.read();
      gps.encode(GPSchar);
    }
    if (gps.location.isUpdated() && gps.course.isUpdated() && gps.satellites.isUpdated() && gps.date.isUpdated() && gps.speed.isUpdated())
    {
      courseDeg = (gps.course.deg());
      return true;
    }
   return false;
}

But it doesnt seem to be able to decode the output

kpg:
So as the GPS reads out whenever it can, why does commenting it out double my loop speed? I still dont really understand that....

No idea, it depends on what your 'loop' is doing.

Dont take a routine that works well in its application out of context and assume its a general purpose routine for all possible situations.

The gpsWaitFix() routine is specifically from a tracker application and in general for a tracker you do this;

Start loop()
Wait for the GPS to update the location fix
Save the latitude, longitude etc
Display the new location
Transmit the new location
Maybe stop reading the GPS and power down for x seconds
..... and repeat

The active part of the loop() will typically take less than a second, maybe longer if the GPS has to wake up from powerdown. Improving the so called loop speed makes no practical difference here since there will only be new GPS fix information to display or transmit once a second.

smet

Apologies if I am mis-understanding but from your last post I believe what you are saying is;

Assuming the GPS is powered up and able to get a fix, then it will report around once a second, irrespective of the setting in gpsWaitFix() and therefore if I am not using the wait timeout function the GPS will read out whenever it can anyway?,

So if I dont apply a timeout and I just let it stream when it can as in my last code post (#9), why does it not show a fix. I can see it is finding satelites but it wont show Lat and Long.

I am guessing this is a function of my remaining loop speed?

gpsWaitFix ();

If you just call gpsWaitFix(); without checking the return value how do you know whether it has tried to decode new output or not?
We can't see the rest of your code so cannot be sure of what to expect.

Your Loop may have to go round more than once before you get a true reply from grsWaitFix

Sorry yes of course. Got wrapped up in the timeout understanding and forgot about the return.

So I am kinda stuck because from TheMemberFormerlyKnownAsAWOL post..

Because every time you call that function, you waste a second.

.

Is my limiting factor.

I will work on the loop speed first. Thanks.

kpg:
I am guessing this is a function of my remaining loop speed?

Could be.

Did I miss the post with all your code ?

kpg:
Sorry yes of course. Got wrapped up in the timeout understanding and forgot about the return.

So I am kinda stuck because from TheMemberFormerlyKnownAsAWOL post..

.

Is my limiting factor.

I will work on the loop speed first. Thanks.

But TheMemberFormerlyKnownAsAWOL's post was based on the original function that waited upto a second, now you have removed that wait from the function the loop will be executed faster.

kpg:
and in function

    if (gps.location.isUpdated() && gps.course.isUpdated() && gps.satellites.isUpdated() && gps.date.isUpdated() && gps.speed.isUpdated())

{
     courseDeg = (gps.course.deg());
     return true;
   }




But it doesnt seem to be able to decode the output

Maybe not all of the fields are updated with every message. Try:

    if (gps.course.isUpdated())
    {
      courseDeg = (gps.course.deg());
      return true;
    }

If in the future you want more than one field:

    boolean returnVal = false;

    if (gps.location.isUpdated())
    {
      myLocation = gps.location();
      returnVal = true;
    }

    if (gps.course.isUpdated())
    {
      courseDeg = gps.course.deg();
      returnVal = true;
    }

    return returnVal;

smet

I will clean it up a bit and post it

I am sure it wont be functionally pretty. I will have to make an attachment.

Thanks again

johnwasser:
Maybe not all of the fields are updated with every message. Try: ....... gps.course.isUpdated()

They are not and therin lies a problem.

If you check for just a single item being updated, such as;

if(gps.course.isUpdated())

and then go off and process stuff or display it, you can find that some of the fields you want are empty and then by the time you get back to reading the GPS again the next sentence you needed to read (for a full update) has long gone.

You can get stuck in a loop with some GPS fields (in TinyGPS++) never updating.

The minimum I know of to ensure that all fields are updated is to keep encoding characters until this is true;

if (gps.location.isUpdated() && gps.altitude.isUpdated())