Adjusting GPS Date and Time to Your Time Zone

31,639

10

4

Introduction: Adjusting GPS Date and Time to Your Time Zone

About: Electronic hobbyist with an interest in programming and making stuff work.

I may be completely wrong by putting up this Instructables but I have struggled to find an easy way to correct GPS time and date data to my time zone here in Australia. I have made a few Arduino projects that have included a GPS module with some form of data logging. Each time I have had difficulties converting UTC time captured from the NMEA data string to local time or have simply gave up and used a RTC in my project.

There are a few solutions on the web include a couple here on Instructables but as a amateur coder I have struggled to integrate the code into my own sketches.

Hopefully this posting will give those equally struggling, an easy solution. I've tried to keep the code as simple as possible with plenty of options to suit your setup, Uno or Mega, software and hardware serial connections. I've also put the time zone calculation in a simple function that can be copied and pasted straight into your own sketch.

You'll need to install the TinyGPS++ Library and the AltSoftSerial Library for the sketch to compile correctly. I have had better compatibility with the GPS modules I have by using the TinyGPS++ library. The AltSoftSerial Library makes it easier to have multiple serial device connected to your Uno. This isn't a problem when using a Mega but if you do want to attach your serial devices on different digital pins, this is the easiest library I have found.

Here is the sketch below :

#include <Time.h>             // Time Library
#include <TinyGPS++.h>        // GPS Library
#include <AltSoftSerial.h>    // Allows two Serial connections

// Set GPS RX and TX pins if using software serial connections.
// See below to use hardware serial connections

//static const int RXPin = 4, TXPin = 3;  // Example Uno
static const int RXPin = 48, TXPin = 46;  // Example Mega

static const uint32_t GPSBaud = 4800;       
//static const uint32_t GPSBaud = 9600;     

// The TinyGPS++ object
TinyGPSPlus gps;

// Serial connection to the GPS device
AltSoftSerial Serial_GPS;
//#define Serial_GPS Serial1  // Uncomment this line & comment
                              // above line to use a hardware
                              // Serial Port

// Change this value to suit your Time Zone
const int UTC_offset = 10;   // Eastern Australia Time

time_t prevDisplay = 0; // Count for when time last displayed

void setup()
{
  Serial.begin(9600);
  Serial_GPS.begin(GPSBaud); // Start GPS Serial Connection
  
  Serial.println("Waiting for GPS time ... ");
}

void loop()
{
  GPS_Timezone_Adjust();  // Call Time Adjust Function
}

void GPS_Timezone_Adjust(){
  
  while (Serial_GPS.available()) {
    if (gps.encode(Serial_GPS.read())) { 
      
      int Year = gps.date.year();
      byte Month = gps.date.month();
      byte Day = gps.date.day();
      byte Hour = gps.time.hour();
      byte Minute = gps.time.minute();
      byte Second = gps.time.second();

        // Set Time from GPS data string
        setTime(Hour, Minute, Second, Day, Month, Year);
        // Calc current Time Zone time by offset value
        adjustTime(UTC_offset * SECS_PER_HOUR);           
      
    }
  }
  
  // -- Delete this section if not displaying time ------- //
  if (timeStatus()!= timeNotSet) {
    if (now() != prevDisplay) {     
      prevDisplay = now();
      SerialClockDisplay();
    }
  }
  // -- Also delete the SerialClockDisplay()function ---- //
  
} // Keep

void SerialClockDisplay(){
  // Serial Monitor display of new calculated time - 
  // once adjusted GPS time stored in now() Time Library 
  // calculations or displays can be made.
  
  if (hour() < 10) Serial.print(F("0"));
        Serial.print(hour());
        Serial.print(F(":"));
  if (minute() < 10) Serial.print(F("0"));
        Serial.print(minute());
        Serial.print(F(":"));
  if (second() < 10) Serial.print(F("0"));
        Serial.print(second()); 
        
        Serial.print(" ");
  
  if (day() < 10) Serial.print(F("0"));      
        Serial.print(day());
        Serial.print(F("/"));
  if (month() < 10) Serial.print(F("0"));
        Serial.print(month());
        Serial.print(F("/"));
        Serial.println(year());
}

I hope you've found this useful and it makes your next GPS datalogging project a lot easier.

Be the First to Share

    Recommendations

    • Make it Glow Contest

      Make it Glow Contest
    • First Time Author Contest

      First Time Author Contest
    • PCB Challenge

      PCB Challenge

    4 Discussions

    0
    delgadosouza
    delgadosouza

    11 months ago

    Hi, thank your for the tutorial!
    I tried it and the code worked most of the time.
    While updating the numbers on screen, the time adjustment is randomly not working.

    I didn't find the reason yet but I found that de adjustTime() function might bring some problems:
    https://github.com/kachok/arduino-libraries/issues/1
    https://forum.arduino.cc/index.php?topic=66054.msg2674610#msg2674610

    I am yet understanding the problem, if you have any advice it would be greatly apreciated!

    0
    ronsimon1957
    ronsimon1957

    1 year ago

    Hello,
    I adapted the sketch to Mega board:

    #include <Time.h> // Time Library
    #include <TinyGPS++.h> // GPS Library
    static const uint32_t GPSBaud = 9600;
    // The TinyGPS++ object
    TinyGPSPlus gps;
    // Change this value to suit your Time Zone
    const int UTC_offset = 2; // Israel Time
    time_t prevDisplay = 0; // Count for when time last displayed
    void setup()
    {
    Serial.begin(115200);
    Serial1.begin(GPSBaud); // Start GPS Serial Connection
    Serial.println("Waiting for GPS time ... ");
    }
    void loop()
    {
    GPS_Timezone_Adjust(); // Call Time Adjust Function
    }
    void GPS_Timezone_Adjust(){
    while (Serial1.available())
    {
    if (gps.encode(Serial1.read()))
    {
    int Year = gps.date.year();
    byte Month = gps.date.month();
    byte Day = gps.date.day();
    byte Hour = gps.time.hour();
    byte Minute = gps.time.minute();
    byte Second = gps.time.second();
    // Set Time from GPS data string
    setTime(Hour, Minute, Second, Day, Month, Year);
    // Calc current Time Zone time by offset value
    adjustTime(UTC_offset * SECS_PER_HOUR);
    }
    }
    } // Keep
    void SerialClockDisplay(){
    // Serial Monitor display of new calculated time -
    // once adjusted GPS time stored in now() Time Library
    // calculations or displays can be made.
    if (Hour() < 10) Serial.print(F("0"));
    Serial.print(hour());
    Serial.print(F(":"));
    if (minute() < 10) Serial.print(F("0"));
    Serial.print(minute());
    Serial.print(F(":"));
    if (second() < 10) Serial.print(F("0"));
    Serial.print(second());
    Serial.print(" ");
    if (day() < 10) Serial.print(F("0"));
    Serial.print(day());
    Serial.print(F("/"));
    if (month() < 10) Serial.print(F("0"));
    Serial.print(month());
    Serial.print(F("/"));
    Serial.println(year());
    }


    But I got error messages:

    Arduino: 1.8.9 (Windows 7), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"
    D:\Arduino\GPS_Local_Time01\GPS_Local_Time01.ino: In function 'void GPS_Timezone_Adjust()':
    GPS_Local_Time01:41:55: error: 'setTime' was not declared in this scope
    setTime(Hour, Minute, Second, Day, Month, Year);
    ^
    GPS_Local_Time01:43:33: error: 'SECS_PER_HOUR' was not declared in this scope
    adjustTime(UTC_offset * SECS_PER_HOUR);
    ^
    GPS_Local_Time01:43:46: error: 'adjustTime' was not declared in this scope
    adjustTime(UTC_offset * SECS_PER_HOUR);
    ^
    D:\Arduino\GPS_Local_Time01\GPS_Local_Time01.ino: In function 'void SerialClockDisplay()':
    GPS_Local_Time01:53:12: error: 'Hour' was not declared in this scope
    if (Hour() < 10) Serial.print(F("0"));
    ^
    GPS_Local_Time01:54:27: error: 'hour' was not declared in this scope
    Serial.print(hour());
    ^
    GPS_Local_Time01:56:14: error: 'minute' was not declared in this scope
    if (minute() < 10) Serial.print(F("0"));
    ^
    GPS_Local_Time01:57:29: error: 'minute' was not declared in this scope
    Serial.print(minute());
    ^
    GPS_Local_Time01:59:14: error: 'second' was not declared in this scope
    if (second() < 10) Serial.print(F("0"));
    ^
    GPS_Local_Time01:60:29: error: 'second' was not declared in this scope
    Serial.print(second());
    ^
    GPS_Local_Time01:64:11: error: 'day' was not declared in this scope
    if (day() < 10) Serial.print(F("0"));
    ^
    GPS_Local_Time01:65:26: error: 'day' was not declared in this scope
    Serial.print(day());
    ^
    GPS_Local_Time01:67:13: error: 'month' was not declared in this scope
    if (month() < 10) Serial.print(F("0"));
    ^
    GPS_Local_Time01:68:28: error: 'month' was not declared in this scope
    Serial.print(month());
    ^
    GPS_Local_Time01:70:29: error: 'year' was not declared in this scope
    Serial.println(year());
    ^
    exit status 1
    'setTime' was not declared in this scope

    0
    MagexD
    MagexD

    3 years ago

    i am use it:

    #include <streaming.h>

    SerialClockDisplay(){

    serial << day() << month() << year() << ',' << hour() << minute() << second() << end1;

    }

    0
    yorkman
    yorkman

    3 years ago

    Just a little bit shorter....

    void SerialClockDisplay(){

    // Serial Monitor display of new calculated time -
    // once adjusted GPS time stored in now() Time Library
    // calculations or displays can be made.

    char sz[32];//Make room for Date/Time

    //Format Date/Time
    sprintf(sz, "%02d-%02d-%02d %02d:%02d:%02d ",
    day(), month(), year(), hour(), minute(), second());

    Serial.println(sz);//Print the formatted Date/Time
    }