diff --git a/adafruit_gps.py b/adafruit_gps.py index 66d0eee..640aea9 100644 --- a/adafruit_gps.py +++ b/adafruit_gps.py @@ -76,7 +76,7 @@ class GPS: """GPS parsing module. Can parse simple NMEA data sentences from serial GPS modules to read latitude, longitude, and more. """ - def __init__(self, uart): + def __init__(self, uart, debug=False): self._uart = uart # Initialize null starting values for GPS attributes. self.timestamp_utc = None @@ -90,6 +90,7 @@ def __init__(self, uart): self.velocity_knots = None self.speed_knots = None self.track_angle_deg = None + self.debug = debug def update(self): """Check for updated data from the GPS module and process it @@ -101,11 +102,13 @@ def update(self): sentence = self._parse_sentence() if sentence is None: return False + if self.debug: + print(sentence) data_type, args = sentence - data_type = data_type.upper() - if data_type == 'GPGGA': # GGA, 3d location fix + data_type = bytes(data_type.upper(), "ascii") + if data_type == b'GPGGA': # GGA, 3d location fix self._parse_gpgga(args) - elif data_type == 'GPRMC': # RMC, minimum location info + elif data_type == b'GPRMC': # RMC, minimum location info self._parse_gprmc(args) return True @@ -115,15 +118,15 @@ def send_command(self, command, add_checksum=True): Note you should NOT add the leading $ and trailing * to the command as they will automatically be added! """ - self._uart.write('$') + self._uart.write(b'$') self._uart.write(command) if add_checksum: checksum = 0 for char in command: - checksum ^= ord(char) - self._uart.write('*') - self._uart.write('{:02x}'.format(checksum).upper()) - self._uart.write('\r\n') + checksum ^= char + self._uart.write(b'*') + self._uart.write(bytes('{:02x}'.format(checksum).upper(), "ascii")) + self._uart.write(b'\r\n') @property def has_fix(self): diff --git a/examples/computer_datalogging.py b/examples/computer_datalogging.py new file mode 100644 index 0000000..0e32132 --- /dev/null +++ b/examples/computer_datalogging.py @@ -0,0 +1,29 @@ +# Simple GPS datalogging demonstration for use with a computer like Linux/desktop. +# This actually doesn't even use the GPS library and instead just reads raw +# NMEA sentences from the GPS unit and dumps them to a file. + +import serial # pyserial is required + +# Path to the file to log GPS data. By default this will be appended to +# which means new lines are added at the end and all old data is kept. +# Change this path to point at the filename desired +LOG_FILE = 'gps.txt' # Example for writing to local file gps.txt + +# File more for opening the log file. Mode 'ab' means append or add new lines +# to the end of the file rather than erasing it and starting over. If you'd +# like to erase the file and start clean each time use the value 'wb' instead. +LOG_MODE = 'ab' + +# Create a serial connection for the GPS connection using default speed and +# a slightly higher timeout (GPS modules typically update once a second). +# Update the serial port name to match the serial connection for the GPS! +uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=3000) + +# Main loop just reads data from the GPS module and writes it back out to +# the output file while also printing to serial output. +with open(LOG_FILE, LOG_MODE) as outfile: + while True: + sentence = uart.readline() + print(str(sentence, 'ascii').strip()) + outfile.write(sentence) + outfile.flush() diff --git a/examples/gps_echotest.py b/examples/gps_echotest.py new file mode 100644 index 0000000..450e6e7 --- /dev/null +++ b/examples/gps_echotest.py @@ -0,0 +1,66 @@ +# Simple GPS module demonstration. +# Will print NMEA sentences received from the GPS, great for testing connection +# Uses the GPS only to send some commands, then reads directly from UART +import time +import board +import busio + +import adafruit_gps + + +# Define RX and TX pins for the board's serial port connected to the GPS. +# These are the defaults you should use for the GPS FeatherWing. +# For other boards set RX = GPS module TX, and TX = GPS module RX pins. +RX = board.RX +TX = board.TX + +# Create a serial connection for the GPS connection using default speed and +# a slightly higher timeout (GPS modules typically update once a second). +uart = busio.UART(TX, RX, baudrate=9600, timeout=3000) + +# for a computer, use the pyserial library for uart access +#import serial +#uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=3000) + +# Create a GPS module instance. +gps = adafruit_gps.GPS(uart) + +# Initialize the GPS module by changing what data it sends and at what rate. +# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and +# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust +# the GPS module behavior: +# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf + +# Turn on the basic GGA and RMC info (what you typically want) +gps.send_command(b'PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') +# Turn on just minimum info (RMC only, location): +#gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') +# Turn off everything: +#gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') +# Tuen on everything (not all of it is parsed!) +#gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0') + +# Set update rate to once a second (1hz) which is what you typically want. +gps.send_command(b'PMTK220,1000') +# Or decrease to once every two seconds by doubling the millisecond value. +# Be sure to also increase your UART timeout above! +#gps.send_command(b'PMTK220,2000') +# You can also speed up the rate, but don't go too fast or else you can lose +# data during parsing. This would be twice a second (2hz, 500ms delay): +#gps.send_command(b'PMTK220,500') + +# Main loop runs forever printing data as it comes in +timestamp = time.monotonic() +while True: + data = uart.read(32) # read up to 32 bytes + # print(data) # this is a bytearray type + + if data is not None: + # convert bytearray to string + data_string = ''.join([chr(b) for b in data]) + print(data_string, end="") + + if time.monotonic() - timestamp > 5: + # every 5 seconds... + gps.send_command(b'PMTK605') # request firmware version + timestamp = time.monotonic() diff --git a/examples/gps_simpletest.py b/examples/gps_simpletest.py index 27b742f..e10bb23 100644 --- a/examples/gps_simpletest.py +++ b/examples/gps_simpletest.py @@ -18,8 +18,12 @@ # a slightly higher timeout (GPS modules typically update once a second). uart = busio.UART(TX, RX, baudrate=9600, timeout=3000) +# for a computer, use the pyserial library for uart access +#import serial +#uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=3000) + # Create a GPS module instance. -gps = adafruit_gps.GPS(uart) +gps = adafruit_gps.GPS(uart, debug=False) # Initialize the GPS module by changing what data it sends and at what rate. # These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and @@ -28,22 +32,22 @@ # https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf # Turn on the basic GGA and RMC info (what you typically want) -gps.send_command('PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') +gps.send_command(b'PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') # Turn on just minimum info (RMC only, location): -#gps.send_command('PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') +#gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') # Turn off everything: -#gps.send_command('PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') +#gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0') # Tuen on everything (not all of it is parsed!) -#gps.send_command('PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0') +#gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0') # Set update rate to once a second (1hz) which is what you typically want. -gps.send_command('PMTK220,1000') +gps.send_command(b'PMTK220,1000') # Or decrease to once every two seconds by doubling the millisecond value. # Be sure to also increase your UART timeout above! -#gps.send_command('PMTK220,2000') +#gps.send_command(b'PMTK220,2000') # You can also speed up the rate, but don't go too fast or else you can lose # data during parsing. This would be twice a second (2hz, 500ms delay): -#gps.send_command('PMTK220,500') +#gps.send_command(b'PMTK220,500') # Main loop runs forever printing the location, etc. every second. last_print = time.monotonic() @@ -71,8 +75,8 @@ gps.timestamp_utc.tm_hour, # not get all data like year, day, gps.timestamp_utc.tm_min, # month! gps.timestamp_utc.tm_sec)) - print('Latitude: {} degrees'.format(gps.latitude)) - print('Longitude: {} degrees'.format(gps.longitude)) + print('Latitude: {0:.6f} degrees'.format(gps.latitude)) + print('Longitude: {0:.6f} degrees'.format(gps.longitude)) print('Fix quality: {}'.format(gps.fix_quality)) # Some attributes beyond latitude, longitude and timestamp are optional # and might not be present. Check if they're None before trying to use! diff --git a/requirements.txt b/requirements.txt index 8b13789..f6c1a1f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ - +pyserial