Location stays the same after delay

Hi everyone.
I'm trying to build a compass using a GPS module (grove gps by seeed) and the TinyGPS++ library.
My plan was to have a StartingLat object, fill that with the current location, then wait 7 seconds and mark down the new current location. If the receiver is moving, the values should be different from each other, and from there I would be able to figure out in what direction (north, south, east, west) I'm moving.
Problem is, both locations are always the same.
I thought maybe the issue was using normal delays, as that interrups the flow of data, but using smart delay didn't change anything.
The control led is on, so I am getting consistent data.
Does anyone have any ideas?

Here is my code:

#include "TinyGPS++.h" // für NMEA Data
#include <SmartDelay.h>
#include "SoftwareSerial.h"
#include <LiquidCrystal.h>

TinyGPSPlus gps; // TinyGPSPlus Objekt
SoftwareSerial serial_connection(10, 11);        //gps module
LiquidCrystal lcd(9, 8, 5, 4, 3, 2);

double StartLat;                                 //first latitude
double CurrentLat;                               //second latitude
int LedRed = 7;                                 
SmartDelay Timer(7000000UL);                     //SmartDelay for 7 seconds

void setup() {
  serial_connection.begin(9600);                 
  pinMode(LedRed, OUTPUT);                       // Led to make sure the location is being updated
  lcd.begin(16, 2);
  lcd.print("Start");
  delay(2000);
  lcd.clear();
}

void loop() {
  
  while(serial_connection.available())
  {
    gps.encode(serial_connection.read());         //NMEA Data is decoded
  }
  
  if(gps.location.isUpdated()){                   //new data is coming in
    digitalWrite(LedRed, HIGH);   
    StartLat = (gps.location.lat());              //save the current lattitude
    if(Timer.Now()){                              //wait 7 seconds
      CurrentLat = (gps.location.lat());          //save current latitude in a different object
      lcd.print(StartLat, 8);                     //print both latitudes
      lcd.setCursor(0, 1);
      lcd.print(CurrentLat, 8);
      delay(2000);
      lcd.clear();
    } 
  } 
}

Waiting seven seconds makes no difference to a message you've already decoded

Thank you for your reply.
I'm afraid I don't quite understand. The data is always being decoded. The point of the delay is to get new values. Or does it not work like that?

The GPS modules I have used do not produce data on demand. Instead they produce data as the device gets it and spits it out. It's up to the consumer of the data to sync to the new data, receive it and consume it.

In your case, the code asks is the info updated?

Then you ask the GPS to send you the last updated data you requested, which was 7 seconds ago. At the end of 7 seconds new data should be sought not the old 7 second ago data.

Yes data is always being decoded but you do not ask the GPS to give you the new data, you ask for the old data.

Ah, I think I get it. Would you have an idea of how it would work?

Using the #include <TinyGPS++.h> library I did distance traveled as per the below.

void fGPS_Parse( void * parameter )
{
  TickType_t xDoDistanceExpireTicks;
  struct stuTime *pxTime;
  //  struct stuDate pxDate;
  struct stuPosit pxPosit;
  struct stuDistance pxDistance;
  struct stuSpeed pxSpeed;
  float Alti;
  float Hdg;
  int Sats;
  float LatNow;
  float LonNow;
  float LatPast;
  float LonPast;
  int DoDistanceTicks = 5000;
  ////
  xDoDistanceExpireTicks = xTaskGetTickCount() + pdMS_TO_TICKS( DoDistanceTicks ); // add DoDistanceTicks mS worth of ticks to current tick count
  for (;;)
  {
    xEventGroupWaitBits (eg, GPS_Parse, pdTRUE, pdTRUE, portMAX_DELAY) ;
    //query GPS: has a new complete chunk of data been received?
    if ( GPSSerial.available() > 1 )
    {
      if ( GPS.encode(GPSSerial.read()) )
      {
        //         if (totalGPGSVMessages.isUpdated()) ///????????????????
        //         {
        if (  GPS.location.isValid())
        {
          //used for distance calculation
          LatNow = GPS.location.lat();
          LonNow = GPS.location.lng();
          //          //
          if ( xSemaphoreTake( sema_Posit, xSemaphoreTicksToWait ) == pdTRUE )
          {
            pxPosit.Lat = LatNow; // store data into structure
            pxPosit.Lon = LonNow;
            xQueueOverwrite( xQ_Posit, (void *) &pxPosit );
            if ( xSemaphoreTake( sema_UTM, xSemaphoreTicksToWait ) == pdTRUE )  // place lat lon for utm calculation
            {
              xUTM_Posit.Lat = pxPosit.Lat;
              xUTM_Posit.Lon = pxPosit.Lon;
              xSemaphoreGive( sema_UTM );
            }
            xSemaphoreGive( sema_Posit );
          }
        } // if (  GPS.location.isValid())
        // do distance calculations
        if ( xTaskGetTickCount() >= xDoDistanceExpireTicks ) // do only once every xDoDistanceExpireTicks
        {
          if ( xSemaphoreTake( sema_CalDistance, xSemaphoreTicksToWait ) == pdTRUE )  // has tick count expired
          {
            if ( LatPast != 0.0 )
            {
              pxDistance.Distance = (unsigned long)TinyGPSPlus::distanceBetween( LatNow, LonNow, LatPast, LonPast) / 1000; // in Kilometers
              xQueueSendToBack( xQ_DistanceMessage, (void *) &pxDistance, xTicksToWait0 );
              // unsigned long distanceKmToLondon = (unsigned long)TinyGPSPlus::distanceBetween( gps.location.lat(), gps.location.lng(), LONDON_LAT, LONDON_LON) / 1000;
            }
            LatPast = LatNow; // update past lat n lon with now lat lon for next calculation
            LonPast = LonNow;
            xSemaphoreGive( sema_CalDistance );
          }
          xDoDistanceExpireTicks = xTaskGetTickCount() + pdMS_TO_TICKS( DoDistanceTicks ); // set new time peorid to do distance calculation
        } //  if ( xTaskGetTickCount() >= xDoDistanceExpireTicks )
        if (GPS.speed.isValid())
        {
          if ( xSemaphoreTake( sema_Speed, xSemaphoreTicksToWait ) == pdTRUE )  // has tick count expired
          {
            pxSpeed.MPH = GPS.speed.mph();
            pxSpeed.KPH = GPS.speed.kmph();
            // xSpeed.MPH = GPS.speed.mph();
            // xSpeed.KPH = GPS.speed.kmph();
            xQueueOverwrite( xQ_Speed, (void *) &pxSpeed );
            xSemaphoreGive( sema_Speed );
          }
          //}
        } //  if (  GPS.location.isValid())
        if (GPS.time.isValid())
        {
          xTime.iSeconds = GPS.time.second();
          xTime.iMinutes = GPS.time.minute();
          xTime.iHours = GPS.time.hour();
          if ( xSemaphoreTake( sema_Time, xSemaphoreTicksToWait ) == pdTRUE )
          {
            pxTime = &xTime;
            xQueueOverwrite( xQ_Time, (void *) &pxTime );
            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.satellites.isValid() )
        {
          if ( xSemaphoreTake( sema_Sats, xSemaphoreTicksToWait ) == pdTRUE )
          {
            Sats = GPS.satellites.value();
            xQueueOverwrite( xQ_Sats, ( void * ) &Sats );
            xSemaphoreGive( sema_Sats );
          }
        }
        if (  GPS.altitude.isValid() )
        {
          if ( xSemaphoreTake( sema_Alti, xSemaphoreTicksToWait ) == pdTRUE )
          {
            Alti = GPS.altitude.meters();
            xQueueOverwrite( xQ_Alti, ( void * ) &Alti );
            xSemaphoreGive( sema_Alti );
          }
        } //  if (  GPS.altitude.isValid() )
        if ( GPS.course.isUpdated() )
        {
          if ( xSemaphoreTake( sema_Hdg, xSemaphoreTicksToWait ) == pdTRUE )
          {
            Hdg = GPS.course.deg();
            xQueueOverwrite( xQ_Hdg, ( void * ) &Hdg );
            xSemaphoreGive( sema_Hdg );
          }
        } // if ( GPS.course.isUpdated() )
        //                Serial.print( "fGPS_Parse " );
        //                Serial.print( " " );
        //                Serial.print(uxTaskGetStackHighWaterMark( NULL ));
        //                Serial.println();
        //                Serial.flush();

      } // if ( GPS.encode(GPSSerial.read()))
    } // if ( GPSSerial.available() > 0 )
    //    else
    //    {
    xSemaphoreGive( sema_GPS_Gate ); // see (xSemaphoreTakeFromISR(sema_GPS_Gate, &xHigherPriorityTaskWoken)) in void IRAM_ATTR onTimer()
    //    }
  } // for (;;)
  vTaskDelete( NULL );
} // void fGPS_Parse( void *pdata )

Wow, I think I might be in a bit over my head... . When I try to compile the sketch, the first error message I get is :
"aggregate 'fGPS_Parse(void*)::stuPosit pxPosit' has incomplete type and cannot be defined".
Do I have to change or add something?
My second question: do the "x"s infront of the names have any meaning (xDoDistanceExpireTicks, xEventGroupWaitBits, xEventGroupWaitBits, etc.)?
I appologize if these are very simple questions, but I have never worked with anything like this before.

Of course the code would not compile for you. My point was for you to read the code where I use the thing to get distance. You can see where/how I keep track of a previous and current lat/long to use for the distance calculations. Also, you can see that to get the current lat and lon the GPS must be queried for new information. Your original issue.

Right, so if I understand this correctly: you check if the location data is valid, then store that data in a float object, which in turn is stored in a structure. Then you wait a certain amount of time, and on the first time around the loop the "current" position is turned into the "old" position, so that during the second loop you have to "sets" of data.
Could I leave out the part where the data is stored in a structure, and just keep it as a float?

1 Like

Yes.

And waiting an amount of time is important. Also, you can use your certain amount of time between readings as the t in r=dt for dead reckoning.

I think it finally works, at least a little. Thank you so much for your help!

Well. Post your code and explain what's wonky and perhaps we can point you in the right direction.