GPS Trying to Get Better Initial Fix

Hi,
I am currently working on a radio controlled tracked crawler. I am not a C++ expert by any stretch of the imagination but I am very happy with progress. I have the RC part working well, I have the GY-NEO6MV2 NEO-6M Ublox GPS receiver working and everything works well.
I am using a GPS receiver because I want to know how far away the crawler is away from where it started from. I have all that working BUT, I want to get a better 'initial fix' by receiving lets say 10 fixes. I read that somewhere that this will give you better data to work from ( or even take an average.)
I am using a function called InitFix() which is called during the setup routine. In the setup because I only want to run this once.
My problem is, and I have been tearing what is left of my hair out trying to get, what to me looks like a simple matter, of getting 10 fixes before going into the main void loop().
I am working on the small sketch below to get this part to work. I have tried using a for loop but only get two fixes.
Any suggestions would be greatly received.
Thanks in advance

  // include libraries
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

static const int RXPin = 4, TXPin = 3;  // define Tx Rx pins
static const uint32_t GPSBaud = 9600;
int i = 0;

// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

void setup() {
 Serial.begin(115200);
  ss.begin(GPSBaud);       //start serial comms
  
InitFix();        // A function to initially receive GPS fixes
}

void loop() {
Serial.println (" In main loop");       // Lets me see when the main loop is entered
}


  void InitFix(){
   
while(!gps.location.isValid())       // Check that no gps is true
   while(ss.available() > 0) {     //Get data if available

     if(gps.encode(ss.read())){  //check data is valid
       Serial.println("Waiting for GPS Fix");  
       delay(2000);  //Delay for 2 seconds until GPS data is received....This all works ok
     }            
   }
      for ( i =0; i<=9; i++){        Trying to loop 10x to get better fix
       while(ss.available() > 0) { 
       gps.encode(ss.read());
      if (gps.location.isUpdated()){
        
           
 Serial.print( " Init Lat = ");
 Serial.print(gps.location.lat() ,6);
 Serial.print( " Init Long = ");
 Serial.print(gps.location.lng() ,6);
 Serial.print( "  Time = ");
 Serial.println(gps.time.value()/100);
     
}}
}
}

The information you want is available in the GPS receiver but you might have to use the u-blox proprietary UBX protocol to enable that information in the NMEA output or request it directly.

Take a look at the relevant document about that.

I'm not much aware of what a "fix" does. I made some extra trick to gain a parameter not presented by Tiny_GPS++. That's a fix?

I use a NEO-6M GPS as a speedsensor. When staring it it quickly showed "standard time" that after some 20 seconds changed to summertime, 1 hour forwarded du to date.
Then it takes several minutes before some sattelites are spotted.

Some knowing guys have told that the GPS chip might remember its last position.... Suppose You move the not powered unit and turn it on. Then it will need time to pick up the sattelites.
Any help? As I told, what does "a fix" do?

Get rid of the delay(2000) -- that makes your program miss GPS sentences.

Just collect and average 10 different readings, after the "initial fix", using this test for position update:

if (gps.location.isUpdated()) {
// collect and add ten sets of lat/lon, then average
}

Thanks for the replies.
All I am trying to do is take 10 readings. It shouldn't be that difficult, I must be missing something obvious.

jremington....I have tried without the delay, but no luck. In fact I have tried all sorts of different things for 3 days.

if (gps.location.isUpdated()) {
// collect and add ten sets of lat/lon, then average
}
I am using this as you can see from my code, but how do I get 10 ten sets??

To collect and average ten sets of data, most people would use a loop.

Something like this, untested. Be aware that on 8 bit Arduinos, double is the same as float and gives only about 6 digits of precision, which does not help much, or at all with GPS coordinate accuracy.

int count=0;
double latsum=0.0,lonsum=0.0;

while (count<10) {
if (gps.location.isUpdated()){
latsum += gps.location.lat();
lonsum += gps.location.lng();
count++;
}
}
double latavg=latsum/10.0;
double lonavg=lonsum/10.0;

I strongly suggest to spend some time with the TinyGPS++ documentation, to get the most out of the library. For example, consider this advisory:

Similarly, isUpdated() indicates whether the object’s value has been updated (not necessarily changed) since the last time you queried it.

Lastly, if you want to know how stale an object’s data is, call its age() method, which returns the number of milliseconds since its last update. If this returns a value greater than 1500 or so, it may be a sign of a problem like a lost fix.

jremington

Thanks so much for your time, I really do appreciate it
The loop method you described looks like a solution. I will experiment tomorrow. (Not allowed anymore time on my project today, wife's orders!!)

I have been delving into the documentation for more knowledge. This little problem has/had me stumped though, it seems so easy but as I say I am new to programming.

Yes, the double/float issue and 6 decimal places with the gps is an issue. I am wondering if just taking the final fix rather than averaging will reduce the error. From my research, the fix improves with time so averaging with some early inaccurate fixes might sway the final result, rather than just taking one last fix. Once I get it working as I want, I will experiment with averaging.
I have had the crawler driving around the large farmyard and the distance-from-start figure is pretty accurate but it does drift, I am hoping this is due to currently using the first fix as the initial position rather than float's 6 digits of accuracy.

Cheers and thanks again.

This loop is only trying 10 times to see if any characters have arrived. It can easily run through all ten tries in a millisecond without finding any characters.

  for ( i = 0; i <= 9; i++)
  {
    // Trying to loop 10x to get better fix
    while (ss.available() > 0)
    {

You want more like:

  // Trying to loop 10x to get a fix
  int positionCount = 0;
  while (positionCount < 10)
  {
    // If a character is available, and it completes a message, and the message updates the location
    if (ss.available() && gps.encode(ss.read()) && gps.location.isUpdated())
    {
      positionCount++;  // Position was updated

      Serial.print( " Init Lat = ");
      Serial.print(gps.location.lat(), 6);
      Serial.print( " Init Long = ");
      Serial.print(gps.location.lng(), 6);
      Serial.print( "  Time = ");
      Serial.println(gps.time.value() / 100);
    }
  } // End while()

Yes, the double/float issue and 6 decimal places with the gps is an issue.

You can get around that. Internally, TinyGSP++ maintains coordinates as pairs of signed long integers, in 10 billionths of a degree.

You can access that internal representation and average those values, without losing precision.

As for getting a better initial fix, you can sometimes tell whether the estimate has been improved by examining the HDOP (horizontal dilution of precision) or PDOP values in certain GPS sentences. Generally, the smaller the better. Also, check the number of satellites used in the fix, obtained from other GPS sentences. Generally, the more the better. But there are always sources of major error that may intrude.

See this PDF presentation Wayback Machine

Thanks John for your suggested approach. That looks good.
And again jr, I have been monitoring the number of satellites, I am 'seeing' 8, with the crawler balancing on my study window! I will look into the HDOP idea.
Just feeding the Mrs with some fine French red in the hope she will have an early night and I can play with both your ideas!
Cheers to you both.

jr

Just uploaded your code, works a treat. Now I will experiment with averaging.

Thanks

stevetyphoon:
I am hoping this is due to currently using the first fix as the initial position rather than float's 6 digits of accuracy.

The first fix a GPS produces, from cold, will generally improve as time goes on, but there is no absolute guarantee of this the fix accuracy could get worse.

You really need to be checking the reported HDOP, that number will normally drop as the fix quality improves.

So if the HDOP at first fix is seen to fall, then you can be relativly sure that the position accuracy is improving.

Averaging, may or may not improve accuracy, and if improving accuracy was so simple you would think the GPS would do it for you ............