Your Raspberry Pi doesn’t have a built-in Real Time Clock, which means every time your Raspberry Pi has been rebooted or has been shutdown for long time, the Date & Time of the Raspberry Pi resets to “2000-01-01 00:00:00”. One way of setting the Raspberry Pi’s Date & Time is via RTC Module. Another way of setting the date & time automatically is via NTP but your RPI must be connected to the internet, or manually setting it via Graphical User Interface (GUI) or via Command Line Interface (CLI), but what if there’s no internet connection available? Getting Date & Time from GPS is one of the best solution that i know. GPS not just provides you coordinates, but provides you accurate Date & Time.
- Raspberry Pi
- Ublox Neo 6M V2
- 4 pc Male Header Pin
- 4 pc Jumper Female to Female
- SMA Female to uFL/u.FL/IPX/IPEX RF Adapter Cable (Optional but recommended)
- GPS Antenna (Optional but recommended)
Note: SMA Female to uFL/u.FL/IPX/IPEX RF Adapter Cable and GPS Antenna is optional but it is highly recommended to have it for better antenna gain.
Step 1: Solder the header pins to the GPS Module:
Step 2: Connect the SMA Female to uFL/u.FL/IPX/IPEX RF Adapter Cable and GPS Antenna:
Step 3: Connect GPS module to RPI via Jumper Wires.
- GPS <—> RPI GPIO
- VCC to PIN 4 (5V) or any 5V PIN
- RX to PIN 8 (TXD)
- TX to PIN 10 (RXD)
- GND to PIN 14 (GND) or any GND Pin
Note: Don’t be confused between RX & TX pin of RPI and GPS Module, the RX pin of RPI must be connected to the TX pin of GPS Module and vice versa.
Step 4: Turning off the Serial Console
Step 4a: We need to backup the “/boot/cmdline.txt” file:
sudo cp /boot/cmdline.txt /boot/cmdline_bak.txt
Step 4b: Edit the cmdline.txt
sudo nano /boot/cmdline.txt
Step 4c: Find and delete “console=ttyAMA0,115200” from the file, then save and exit. (ctrl + O then Y to save, then Ctrl + X to exit the nano terminal).
Note: If file doesn’t contain the “console=ttyAMA0,115200” then proceed to next step)
Step 4d: Edit the /etc/inittab and find “ttyAMA0” keyword and add “#” from the first character of the line.
Note: If file doesn’t contain the “ttyAMA0” then proceed to next step)
Step 4e: Edit the /boot/config.txt file
sudo nano /boot/config.txt
Add the following at the end of the file:
dtparam=spi=on dtoverlay=pi3-disable-bt enable_uart=1
Ctrl + O to save, then Ctrl +x to exit nano terminal.
Step 4f: Disable the RPI’s Getty Service:
sudo systemctl stop serial-getty@ttyS0.service sudo systemctl disable serial-getty@ttyS0.service
Reboot the Raspberry Pi by executing:
sudo reboot now
Step 4g: enable the ttyAMA0 by executing:
sudo systemctl enable serial-getty@ttyAMA0.service
Step 5: Test the GPS Module
Execute the following command:
sudo cat /dev/ttyAMA0
Step 6: Install python library for GPS:
sudo apt-get install python-pip sudo pip install pynmea2 sudo apt-get install python-serial
Step 7: Python Script to get the GPS time and Sync it to Raspberry Pi’s Date and Time:
import time import serial import string import pynmea2 import datetime from datetime import timedelta import operator import sys import os #port = "/dev/ttyS0" port = "/dev/ttyAMA0" def checksum(sentence): sentence = sentence.strip('\n') try: nmeadata,cksum = sentence.split('*', 1) calc_cksum = reduce(operator.xor, (ord(s) for s in nmeadata), 0) return nmeadata,int(cksum,16),calc_cksum except ValueError: return False; fetchDT = 0; def getGPS(): global fetchDT ser = serial.Serial(port, baudrate = 9600, timeout = 5) while 1: try: while(ser.inWaiting() >0): data = ser.readline().rstrip() if data[0:6] == "$GPRMC": print "" if checksum(data) != False: splitData = data.split(",") if splitData == 'A': #Valid GPS TIME print data msg = pynmea2.parse(data) dateStr="20"+splitData[4:6]+"-"+splitData[2:4]+"-"+splitData[0:2] dtStr = dateStr + " " + str(msg.timestamp) dt = datetime.datetime.strptime(dtStr, "%Y-%m-%d %H:%M:%S") + timedelta(hours=8) #OFFSET GMT8 print "GPS TIME: " +str(dt) now = datetime.datetime.now() print "SYS TIME: " +str(now.strftime("%Y-%m-%d %H:%M:%S")) if dt > now: print "GPS TIME IS NOW AHEAD OF SYS TIME" os.system("sudo date -s '"+str(dt)+"'") else: print "SYS TIME IS NOW AHEAD OF GPS TIME" if fetchDT >= 60: print "FINISH"; print msg.timestamp; ser.close() sys.exit(0) exit(); quit() fetchDT+=1; except pynmea2.nmea.ChecksumError as e: print("No data this time 0") ser.close() time.sleep(3) getGPS(); except serial.SerialException as e: print("No data this time 1") ser.close() time.sleep(3) getGPS(); except TypeError as e: print("No data this time 3") ser.close() time.sleep(3) getGPS(); except serial.serialutil.SerialException: print("No data this time 4") ser.close() time.sleep(3) getGPS(); except IOError as e: #print("No data this time") ser.close() getGPS(); except (KeyboardInterrupt, SystemExit): print "Exiting" ser.close() exit(); except Exception as e: print("No data this time 4") ser.close() time.sleep(3) getGPS(); now = datetime.datetime.now() getGPS();
Step 8: Run the application by executing:
sudo python gps_sync.py
You will see strings appeared on the terminal and wait for the correct GPS time to be appeared, the program will check if the GPS time is ahead of the RPI’s System time then it will sync.
You need also change the OFFSET on the program on Line 42, change timedelta(hours=8) to your Timezone, GPS time is based on UTC 0, in our timezone “Asia/Manila” which is UTC+8, so i assigned hours=8, Example if you are in UCT+5, you need to declare timedelta(hours=5).
Note: If you are not getting any date & time from GPS, you might need to relocate your GPS antenna which should be in outside of your house to get data from GPS Satellites. If its very cloudy, it might took time to get GPS data (Around 2-3minutes).
I’ll be updating this post to provide some screenshots soon.
To make the python program run on startup, please see “Running python script at startup“