Hi all.
If I'd like to have the code continue till GPS fixed or at least connected, what code should I use please?
is this while (gps.available() != available) a good one, seems not work?
Thanks
Adam
What GPS library are you using for decoding the GPS sentences, and can you post your code?
The GPS library I have used requires you to constantly read characters from the serial port the GPS is connected to, and pass those characters to the decode library one at a time. The decode library will return true only when the character you just passed is the last character of a valid GPS sentence and that sentence indicates that the GPS has acquired a lock.
Thank you.
the sketch attached here which is a example of TinyGPS library, it didn't have the question I asked. the topic up cause of I'd like to add some function in it.
#include <SoftwareSerial.h>
#include <TinyGPS.h>
/* This sample code demonstrates the normal use of a TinyGPS object.
It requires the use of SoftwareSerial, and assumes that you have a
4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
TinyGPS gps;
SoftwareSerial ss(4, 3);
static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
void setup()
{
Serial.begin(115200);
Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
Serial.println("by Mikal Hart");
Serial.println();
Serial.println("Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum");
Serial.println(" (deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail");
Serial.println("-------------------------------------------------------------------------------------------------------------------------------------");
ss.begin(4800);
}
void loop()
{
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
gps.f_get_position(&flat, &flon, &age);
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
print_date(gps);
print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 7, 2);
print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0xFFFFFFFF : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? TinyGPS::GPS_INVALID_F_ANGLE : TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);
gps.stats(&chars, &sentences, &failed);
print_int(chars, 0xFFFFFFFF, 6);
print_int(sentences, 0xFFFFFFFF, 10);
print_int(failed, 0xFFFFFFFF, 9);
Serial.println();
smartdelay(1000);
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void print_float(float val, float invalid, int len, int prec)
{
if (val == invalid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(' ');
}
smartdelay(0);
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
Serial.print(sz);
smartdelay(0);
}
static void print_date(TinyGPS &gps)
{
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
if (age == TinyGPS::GPS_INVALID_AGE)
Serial.print("********** ******** ");
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
month, day, year, hour, minute, second);
Serial.print(sz);
}
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
smartdelay(0);
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
smartdelay(0);
}
Take care with a lot of the Library examples for GPSs.
Especially when using softwareserial to read the GPS, avoid printing out heaps of stuff to the serial monitor that has not changed, it can easily cause characters from the GPS to be missed the symtom of which is no reported fix.
The GPS position information and time is normally only updated when the GPGGA and GPRMC sentences are read. So although you might be reading and passing to encode all the other sentences, fix info does not update until the GPS actually has a fix and the GPGGA and GPRMC sentences are read. Pointless printing piles of stuff until this happens.
So if you were using the TinyGPS++ library you would read it like so;
bool gpsWaitFix(uint16_t waitSecs)
{
//waits a specified number of seconds for a fix, returns true for updated fix
uint32_t startmS, waitmS;
uint8_t GPSchar;
Serial.print(F("Wait GPS Fix "));
Serial.print(waitSecs);
Serial.println(F(" seconds"));
waitmS = waitSecs * 1000; //convert seconds wait into mS
startmS = millis();
while ( (uint32_t) (millis() - startmS) < waitmS) //allows for millis() overflow
{
if (GPSserial.available() > 0)
{
GPSchar = GPSserial.read();
gps.encode(GPSchar);
Serial.write(GPSchar);
}
if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.date.isUpdated())
{
endFixmS = millis(); //record the time when we got a GPS fix
return true;
}
}
return false;
}
Note the function keeps reading the GPS until the location is actually updated.
The tiny GPS library doesn't have an available function, which is why that won't work.
Telling if the GPS is connected is easy. The GPS will start sending sentences the moment it is connected, so as soon as ss.available() reports data, you can assume the GPS is connected. This does not mean it has a fix.
To wait for a fix, you have to read characters from the serial port, and feed them to the encode() function. That function returns true when it has a valid sentence.
Here is an example that will wait forever until the GPS gets a fix.
do
{
while (ss.available())
{
char c = ss.read();
// Serial.write(c); // uncomment this line if you want to see the GPS data flowing
if (gps.encode(c)) // Did a new valid sentence come in?
newData = true;
}
} while (newData != true)
To add a timeout to this, you would have to combine this with the smartdelay() function in the example program. Exit the outer loop when either newData is true, or when the timeout is reached.
Detecting when the GPS has lost the fix is a bit harder. One of the things returned by the get_position() function is the fix age. This is equal the time in milliseconds since the last valid fix. You can pick whatever maximum fix age you want to use, and if the returned value is greater than that, assume the fix has been lost. The GPS sends out the sentences every second, so most of the time that should be less than 1000 mS. I tend to use 60000 mS as my limit, indicating that the GPS has not had a fix for at least one minute.
thank you !
I am testing that.
is it possible to use GPS time init system time and keep it, then power off GPS?