#!/usr/bin/python import time import smbus2 as smbus import signal import sys import subprocess # Global variables BUS = None address = 0x42 gpsReadInterval = 0.03 def connectBus(): """Connects to the I2C bus.""" global BUS subprocess.run(['pinctrl', 'set', '26', 'op', 'dh']) BUS = smbus.SMBus(1) def parseResponse(gpsLine): """ Parses and interprets NMEA sentences. Args: gpsLine: List of bytes read from the GPS. """ gpsChars = ''.join(chr(c) for c in gpsLine if c >= 32 and c <= 122) # Filter valid characters if gpsChars.startswith('$'): try: sentence_type = gpsChars[1:6] data = gpsChars.split(',') # Process NMEA sentence types if sentence_type == "GPRMC": print(parseGPRMC(data)) elif sentence_type == "GPVTG": print(parseGPVTG(data)) elif sentence_type == "GPGGA": print(parseGPGGA(data)) elif sentence_type == "GPGSA": print(parseGPGSA(data)) elif sentence_type == "GPGSV": print(parseGPGSV(data)) elif sentence_type == "GPGLL": print(parseGPGLL(data)) else: print(f"Unknown NMEA sentence: {gpsChars}") except Exception as e: print(f"Error parsing NMEA sentence: {e}") def parseGPRMC(data): """Parse and format GPRMC sentence.""" return { "Type": "Recommended Minimum Navigation Information (RMC)", "Fix Status": "Valid" if data[2] == "A" else "Invalid", "Time (UTC)": data[1], "Latitude": data[3], "Longitude": data[5], "Speed (knots)": data[7], "Course (degrees)": data[8], "Date": data[9] } def parseGPVTG(data): """Parse and format GPVTG sentence.""" return { "Type": "Track Made Good and Ground Speed (VTG)", "Course (degrees)": data[1], "Speed (knots)": data[5], "Speed (km/h)": data[7], "Mode": data[9] } def parseGPGGA(data): """Parse and format GPGGA sentence.""" return { "Type": "Global Positioning System Fix Data (GGA)", "Time (UTC)": data[1], "Latitude": data[2], "Longitude": data[4], "Fix Quality": data[6], "Number of Satellites": data[7], "HDOP": data[8], "Altitude": data[9] } def parseGPGSA(data): """Parse and format GPGSA sentence.""" return { "Type": "GNSS DOP and Active Satellites (GSA)", "Mode": data[1], "Fix Type": data[2], "Satellites Used": data[3:15], "PDOP": data[15], "HDOP": data[16], "VDOP": data[17] } def parseGPGSV(data): """Parse and format GPGSV sentence.""" return { "Type": "GNSS Satellites in View (GSV)", "Number of Sentences": data[1], "Sentence Number": data[2], "Satellites in View": data[3], "Satellite Data": data[4:] } def parseGPGLL(data): """Parse and format GPGLL sentence.""" return { "Type": "Geographic Position (Latitude/Longitude) (GLL)", "Latitude": data[1], "Longitude": data[3], "Fix Status": "Valid" if data[6] == "A" else "Invalid", "Time (UTC)": data[5] } def handle_ctrl_c(signal, frame): """Handles Ctrl+C signal to exit gracefully.""" sys.exit(130) signal.signal(signal.SIGINT, handle_ctrl_c) def readGPS(): """ Reads GPS data from the I2C bus. """ global BUS response = [] try: while True: c = BUS.read_byte(address) if c == 255: # Invalid byte return False elif c == 10: # Line feed (end of GPS message) parseResponse(response) response = [] # Reset for the next message else: response.append(c) except IOError: print("I/O Error, reconnecting to I2C bus...") connectBus() except Exception as e: print(f"Unexpected error: {e}") connectBus() # Main loop if __name__ == "__main__": connectBus() # Initialize the I2C bus connection while True: readGPS() time.sleep(gpsReadInterval)