Introduction: GPS Time (UTC) to Local Time Conversion Using Arduino
I have a GPS receiver, Holux M-1000, which you can use it with a laptop, a PDA, or a cellphone through Bluetooth. I had used it for navigation with Palm TX and Treo700p (yes, I have long been a big fan of Palm PDA series) and Geocaching until I bought an Android smartphone which has a built-in GPS module. So Holux M-1000 has been in my drawer collecting dust for more than a year.
Recently, I wanted to make a small GPS device for measuring distance between two locations, for example, while you are playing golf you can measure how good your driver shot is. There are a lot of commercial product that can do this and much more, but buying is far less fun than making one by yourself (I'm sure Instructables visitor and author will strongly agree with me, right?) There are Android applications as well, but none of them attracts me.
My idea is to add a small LCD, similar size as the size of the GPS, and a microprocessor to acquire data from the GPS, calculate distance, and show it on the LCD along with time and date. I have ordered one of the popular LCD, Nokia 5110, and started doing research on how to get the GPS data, how to interprete the data, and what kind of data I can get.
Well, calculating distance seemed to be easy. I could find a couple of ways to calculate the distance between two locations. However, converting GPS time(UTC) into local time seemed to be a little tricky, but it was fun to figure out the way to convert time to local time including daylight saving time and date. I have already posted this part in my blog page and decided to share my Arduino program here. Once I get the LCDand finish assembling the device, I will post another Instructable with full program and pictures, too. This Instructable includes only how to get the data from the GPS (Holux M-1000) through serial bus and how to convert the GPS time to local time.
Step 1: Connection Between the GPS and Arduino
- Pin 4 and 3 on the USB mini B connector on Holux M-1000 are TX and RX (so I don’t have to add wires from the PCB. That’s good news to make my life easier. In fact, I had thought the USB jack is only for charging the battery!)
- Pins 5 and 1 of the USB connector are Vcharge (5V) and GND, respectively as standard USB pinouts.
- Those two RX and TX pins’ voltage range is 3.3 – 5V
- Data format: NMEA0183 V3.01, GGA, RMC, VTG, GSA, GSV
- Power consumption: 40 – 50mA in normal mode, 35mA in power saving mode
And another picture shows how they are connected each other. The FTDI breakout board is connected to my computer through USB cable.
Step 2: GPS Data Structure and Arduino Parsing Functions
RMC - NMEA has its own version of essential gps pvt (position, velocity, time) data. It is called RMC, The Recommended Minimum, which will look similar to:
RMC Recommended Minimum sentence C
123519 Fix taken at 12:35:19 UTC
A Status A=active or V=Void.
4807.038,N Latitude 48 deg 07.038' N
01131.000,E Longitude 11 deg 31.000' E
022.4 Speed over the ground in knots
084.4 Track angle in degrees True
230394 Date - 23rd of March 1994
003.1,W Magnetic Variation
*6A The checksum data, always begins with *
Each parameter is separated by a comma. From Arduino version 1.0, serial library includes parsing function which makes serial data reading much easier than before. Below is a part of my program to read these data from RMC sentence.
gps.parseFloat(); //discard unnecessary part
gpsLatLong(gps.parseInt(), gps.parseInt(), gps.parseInt(), gps.parseInt());
gpsSpeed = gps.parseFloat()*1.852; //knot to km/h
gpsBearing = gps.parseFloat();
gpdTime(), gpsLatLong() and gpsDate() are functions I made, which I will explain in the next step, and .parseInt(), .parseFloat() are the Arduino functions to parse integer and float values from serial bus. The 'gps' in front of those parsing functions is just the name of my serial port which is defined in the beginning of the program. The entire program will be attached to the last step.
Step 3: Functions to Interpret GPS Data
gpsTime() extracts hour, minute and second which is UTC.
gpsLatLong() extracts latitude and longitude.
gpsDate() extracts date.
void gpsTime(long UTC)
gpsHour = int(UTC/10000);
gpsMin = int(UTC%10000/100);
gpsSec = UTC%100;
void gpsLatLong(int lat1, int lat2, int long1, int long2)
gpsLat = int(lat1/100) + (lat1%100)/60.0 + float(lat2)/10000.0/60.0;
gpsLong = int(long1/100) + (long1%100)/60.0 + float(long2)/10000.0/60.0;
void gpsDate(long dateRead)
gpsDay = int(dateRead/10000);
gpsMonth = int(dateRead%10000/100);
gpsYear = dateRead%100; //last 2 digits, e.g. 2013-> 13
The calculation used in these functions are quite straightforward so I won't elaborate to explain the detail, but if you have any questions, let me know.
Step 4: GPS Time (UTC) to Local Time Conversion
if (gpsYear%4 == 0) DaysAMonth = 29; //leap year check
If it is leap year, add one day to the number of days of February. Actually the leap year is not simply every 4 years but there are more conditions but for the next 10-20 years it won't happen and we can simply calculate it every 4 years.
//Time zone adjustment
gpsHour += TimeZone;
TimeZone is a constant defined at the beginning of the program. You need to change this number according to where you live.
if (gpsMonth*100+gpsDay >= DSTbegin[gpsYear-13] &&
gpsMonth*100+gpsDay < DSTend[gpsYear-13]) gpsHour += 1;
I added a DST (daylight saving time) table in an array, the starting date and ending date. If current date is withing this range, add 1 hour.
The section below is to correct time and date after the timezone adjustment. For example, if the adjusted hour is less than 0 or greater than 24, you need to adjust the day as well. As such, you need to adjust Month and Year, too.
That's all for this instructable. Hope this helps someone who wants to convert GPS time to local time.
if (gpsHour < 0)
gpsHour += 24;
gpsDay -= 1;
if (gpsDay < 1)
if (gpsMonth == 1)
gpsMonth = 12;
gpsYear -= 1;
gpsMonth -= 1;
gpsDay = DaysAMonth[gpsMonth-1];
if (gpsHour >= 24)
gpsHour -= 24;
gpsDay += 1;
if (gpsDay > DaysAMonth[gpsMonth-1])
gpsDay = 1;
gpsMonth += 1;
if (gpsMonth > 12) gpsYear += 1;
Thanks for reading.