Sometimes the obvious just slaps you up in the face like a cold, wet fish.
I have an old Parallax GPS module from the days of 2007. It outputs 4800 BAUD. The idea is to build one GPS controlled clock so that the time/date would always be accurate. In this clock, I would put a transmitter to relay the serial TTL via radio to other Arduino'ish devices that needed correct time. So far, so good.
I breadboarded the GPS module, applied power, used an FTDI to connect to my PC and a piece of software on the PC called VisualGPSView. http://www.visualgps.net/VisualGPSView/default.htm I was amazed that even with this old GPS and it's patch antenna that I could get signals from the satellites down in the basement of my house; that is through the plywood floor, the mat and rug, the ceiling, the attic insulation, the attic floor, the plywood roof, and the tar-paper and asphalt roof shingles. But getting a "lock" took a long time and was problematic although it did occur. And so this thing has been on the bench for nearly a week before I got around to a sketch to take the place of VisualGPSView and parse out just the time and date.
I used the Adafruit library GitHub - adafruit/Adafruit_GPS: An interrupt-based GPS Arduino library for no-parsing-required use and started with her parse script. I stripped out lots of stuff, it is hardly recognizable.
/*
Originally based on Adafruit example sketch: "parsing"
Utilizes the Adafruit_GPS library https://github.com/adafruit/Adafruit-GPS-Library
20131115: GPS_Parsing_Test
Heavily mucked by M. Ray Burnette to simply use (most) any dumb serial TTL GPS for time-date
Tested with ancient #28146 Parallax module
Arduino 1.0.5:
Program: 9090 bytes
(.text + .data + .bootloader)
Data: 754 bytes
(.data + .bss + .noinit)
*/
#include "Adafruit_GPS.h"
#include <SoftwareSerial.h>
#include <Streaming.h>
// Connect the GPS TX (transmit) pin to Digital 3
SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
// Set GPSDEBUG to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences.
// Could be as simple as checking a digital pin to-Gnd state
#define GPSDEBUG false // should be a check of a digital pin to Gnd
uint8_t last_seconds ;
uint8_t TimeZoneHour = -5 ; // needs to be a pin-to-ground adjustment for DST
uint8_t LocalHour ;
void setup()
{
// connect at 115200 so we can read the GPS fast enough and echo without dropping chars
Serial.begin(115200);
Serial.println("GPS time-date:");
// Some GPS are 4800 and some are 9600 or faster
GPS.begin(4800);
delay(1000);
// Add a DST check of a digital pin for DayLightSavingTime or
// Use multiple digital pins to set any TimeZone
}
void loop()
{
// read data from the GPS
char c = GPS.read();
if (GPSDEBUG) // Raw character echo to monitor
if (c) Serial.print(c);
// if a sentence is received, check the checksum, parse it...
if (GPS.newNMEAreceived()) {
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
return; // return to top of loop() if sentence does not verify correctly or completely
}
// BIG if() active only once per second since this sketch is time-date focused
if (last_seconds != GPS.seconds) { last_seconds = GPS.seconds;
LocalHour = GPS.hour + TimeZoneHour;
Serial.print("\nTime: ") ;
Serial << ((LocalHour<10)?"0":"") ;
Serial.print(LocalHour, DEC);
Serial << (':') ;
Serial << ((GPS.minute<10)?"0":"") ;
Serial.print (GPS.minute, DEC);
Serial << (':') ;
Serial << ((GPS.seconds<10)?"0":"") ;
Serial.print(GPS.seconds, DEC) ;
Serial.print("\nDate: ");
Serial << ((GPS.day<10)?"0":"") ;
Serial.print(GPS.day, DEC) ; //DD
Serial << "/" << ((GPS.month<10)?"0":"") ;
Serial.print(GPS.month, DEC) ; //MM
Serial << "/20" ;
Serial.println(GPS.year, DEC) ; //YYYY
if (GPS.fix && GPSDEBUG) {
Serial.print("Location: ");
Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
Serial.print(", ");
Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
// Serial.print("Speed (knots): "); Serial.println(GPS.speed);
// Serial.print("Angle: "); Serial.println(GPS.angle);
Serial.print("Altitude: "); Serial.println(GPS.altitude);
Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
}
} // BIG if
} // loop
So, here is what I did not know until today: It is NOT necessary to have a GPS lock to get the time and date. From my experiments, you need very little quality satellite data for the time and date to populate. It is really quiet amazing to me. What I did was just feed the Adafruit GPS object with the entire GPS module stream and allow the object to populate the 6 values that I wanted. This seems to happen in just a few seconds and stays reasonably stable no matter how I orient the patch antenna. Edit: Almanac (definitely) and Ephemeris (maybe) data from at least one satellite does appear to be required;
( GPS signals - Wikipedia )
so depending on the age of your GPS receiver, the time-date may require upwards to 15 minutes; however, I tried a GPS PMB-648 that had not been used in weeks and got the correct time&date in under 20 seconds (as they say, your results may vary!)
How GPS Works
Sample sketch output:
GPS time-date: <== from program setup()
Time: 11:45:58
Date: 00/00/200 <== variables not initialized
Time: 11:45:59
Date: 15/11/2013 <== object variables all populated
Time: 11:46:00
Date: 15/11/2013
Time: 11:46:01
Date: 15/11/2013
Time: 11:46:02
Date: 15/11/2013
Time: 11:46:03
Date: 15/11/2013
Time: 11:46:04
Date: 15/11/2013
Time: 11:46:05
Date: 15/11/2013
Time: 11:46:06
Date: 15/11/2013
Time: 11:46:07
Date: 15/11/2013
Time: 11:46:08
Date: 15/11/2013
Time: 11:46:09
Date: 15/11/2013
Time: 11:46:10
Date: 15/11/2013
Time: 11:46:11
Date: 15/11/2013
Time: 11:46:12
Date: 15/11/2013
And here is raw GPS sentences printed with DEBUG on (time/date inter-spaced with GPS input to sketch:
Time: 11:06:14
Date: 00/00/0
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,160614.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*61
$GPGGA,160615.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*43
Time: 11:06:15
Date: 11/15/13
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,160615.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*60
$GPGGA,160616.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*40
Time: 11:06:16
Date: 11/15/13
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGSV,3,1,12,02,89,171,25,12,64,322,,04,43,046,,10,35,099,*7F
$GPGSV,3,2,12,24,33,226,,25,23,316,,05,22,160,,29,12,277,*71
$GPGSV,3,3,12,17,12,077,,31,-9,339,,14,-10,299,,28,-10,133,*6C
$GPRMC,160616.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*63
$GPGGA,160617.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*41
Time: 11:06:17
Date: 11/15/13
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,160617.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*62
$GPGGA,160618.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*4E
Time: 11:06:18
Date: 11/15/13
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,160618.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*6D
$GPGGA,160619.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*4F
Time: 11:06:19
Date: 11/15/13
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,160619.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*6C
$GPGGA,160620.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*45
Time: 11:06:20
Date: 11/15/13
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,160620.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*66
$GPGGA,160621.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*44
Time: 11:06:21
Date: 11/15/13
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPGSV,3,1,12,02,89,171,24,12,64,322,,04,43,046,,10,35,099,*7E
$GPGSV,3,2,12,24,33,226,,25,23,316,,05,22,160,,29,12,277,*71
$GPGSV,3,3,12,17,12,077,,31,-9,339,,14,-10,299,,28,-10,133,*6C
$GPRMC,160621.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*67
$GPGGA,160622.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*47
Time: 11:06:22
Date: 11/15/13
No Fix...Satellites: 0
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GPRMC,160622.295,V,3355.2535,N,08402.2105,W,,,151113,,,N*64
$GPGGA,160623.295,3355.2535,N,08402.2105,W,0,00,,305.9,M,-31.0,M,,0000*46
That GPS clock is just a little formatting on the serial OLED display away from being completed!
Ray
GPS_TimeDate.zip (5.75 KB)