Simple test
Ensure your device works with this simple test.
1# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
2# SPDX-License-Identifier: MIT
3
4# Simple GPS module demonstration.
5# Will wait for a fix and print a message every second with the current location
6# and other details.
7import time
8
9import board
10import busio
11
12import adafruit_gps
13
14# Create a serial connection for the GPS connection using default speed and
15# a slightly higher timeout (GPS modules typically update once a second).
16# These are the defaults you should use for the GPS FeatherWing.
17# Connect UART rx to GPS module TX, and UART tx to GPS module RX.
18tx = board.TX # Use board.GP4 or other UART TX on Raspberry Pi Pico boards.
19rx = board.RX # Use board.GP5 or other UART RX on Raspberry Pi Pico boards.
20uart = busio.UART(tx, rx, baudrate=9600, timeout=10)
21
22# for a computer, use the pyserial library for uart access
23# import serial
24# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
25
26# If using I2C, we'll create an I2C interface to talk to using default pins
27# i2c = board.I2C() # uses board.SCL and board.SDA
28# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
29
30# Create a GPS module instance.
31gps = adafruit_gps.GPS(uart, debug=False) # Use UART/pyserial
32# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
33
34# Initialize the GPS module by changing what data it sends and at what rate.
35# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
36# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust
37# the GPS module behavior:
38# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
39
40# Turn on the basic GGA and RMC info (what you typically want)
41gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
42# Turn on the basic GGA and RMC info + VTG for speed in km/h
43# gps.send_command(b"PMTK314,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
44# Turn on just minimum info (RMC only, location):
45# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
46# Turn off everything:
47# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
48# Turn on everything (not all of it is parsed!)
49# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
50
51# Set update rate to once a second (1hz) which is what you typically want.
52gps.send_command(b"PMTK220,1000")
53# Or decrease to once every two seconds by doubling the millisecond value.
54# Be sure to also increase your UART timeout above!
55# gps.send_command(b'PMTK220,2000')
56# You can also speed up the rate, but don't go too fast or else you can lose
57# data during parsing. This would be twice a second (2hz, 500ms delay):
58# gps.send_command(b'PMTK220,500')
59
60# Main loop runs forever printing the location, etc. every second.
61last_print = time.monotonic()
62while True:
63 # Make sure to call gps.update() every loop iteration and at least twice
64 # as fast as data comes from the GPS unit (usually every second).
65 # This returns a bool that's true if it parsed new data (you can ignore it
66 # though if you don't care and instead look at the has_fix property).
67 gps.update()
68 # Every second print out current location details if there's a fix.
69 current = time.monotonic()
70 if current - last_print >= 1.0:
71 last_print = current
72 if not gps.has_fix:
73 # Try again if we don't have a fix yet.
74 print("Waiting for fix...")
75 continue
76 # We have a fix! (gps.has_fix is true)
77 # Print out details about the fix like location, date, etc.
78 print("=" * 40) # Print a separator line.
79 print(
80 "Fix timestamp: {}/{}/{} {:02}:{:02}:{:02}".format( # noqa: UP032
81 gps.timestamp_utc.tm_mon, # Grab parts of the time from the
82 gps.timestamp_utc.tm_mday, # struct_time object that holds
83 gps.timestamp_utc.tm_year, # the fix time. Note you might
84 gps.timestamp_utc.tm_hour, # not get all data like year, day,
85 gps.timestamp_utc.tm_min, # month!
86 gps.timestamp_utc.tm_sec,
87 )
88 )
89 print(f"Latitude: {gps.latitude:.6f} degrees")
90 print(f"Longitude: {gps.longitude:.6f} degrees")
91 print(f"Precise Latitude: {gps.latitude_degrees} degs, {gps.latitude_minutes:2.4f} mins")
92 print(f"Precise Longitude: {gps.longitude_degrees} degs, {gps.longitude_minutes:2.4f} mins")
93 print(f"Fix quality: {gps.fix_quality}")
94 # Some attributes beyond latitude, longitude and timestamp are optional
95 # and might not be present. Check if they're None before trying to use!
96 if gps.satellites is not None:
97 print(f"# satellites: {gps.satellites}")
98 if gps.altitude_m is not None:
99 print(f"Altitude: {gps.altitude_m} meters")
100 if gps.speed_knots is not None:
101 print(f"Speed: {gps.speed_knots} knots")
102 if gps.speed_kmh is not None:
103 print(f"Speed: {gps.speed_kmh} km/h")
104 if gps.track_angle_deg is not None:
105 print(f"Track angle: {gps.track_angle_deg} degrees")
106 if gps.horizontal_dilution is not None:
107 print(f"Horizontal dilution: {gps.horizontal_dilution}")
108 if gps.height_geoid is not None:
109 print(f"Height geoid: {gps.height_geoid} meters")
Echo test
Simple GPS module demonstration. This will print NMEA sentences received from the GPS, great for testing connection. This uses the GPS to send some commands, then reads directly from the GPS.
1# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
2# SPDX-License-Identifier: MIT
3
4# Simple GPS module demonstration.
5# Will print NMEA sentences received from the GPS, great for testing connection
6# Uses the GPS to send some commands, then reads directly from the GPS
7import time
8
9import board
10import busio
11
12import adafruit_gps
13
14# Create a serial connection for the GPS connection using default speed and
15# a slightly higher timeout (GPS modules typically update once a second).
16# These are the defaults you should use for the GPS FeatherWing.
17# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
18uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
19
20# for a computer, use the pyserial library for uart access
21# import serial
22# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
23
24# If using I2C, we'll create an I2C interface to talk to using default pins
25# i2c = board.I2C() # uses board.SCL and board.SDA
26# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
27
28# Create a GPS module instance.
29gps = adafruit_gps.GPS(uart) # Use UART/pyserial
30# gps = adafruit_gps.GPS_GtopI2C(i2c) # Use I2C interface
31
32# Initialize the GPS module by changing what data it sends and at what rate.
33# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
34# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust
35# the GPS module behavior:
36# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
37
38# Turn on the basic GGA and RMC info (what you typically want)
39gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
40# Turn on just minimum info (RMC only, location):
41# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
42# Turn off everything:
43# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
44# Tuen on everything (not all of it is parsed!)
45# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
46
47# Set update rate to once a second (1hz) which is what you typically want.
48gps.send_command(b"PMTK220,1000")
49# Or decrease to once every two seconds by doubling the millisecond value.
50# Be sure to also increase your UART timeout above!
51# gps.send_command(b'PMTK220,2000')
52# You can also speed up the rate, but don't go too fast or else you can lose
53# data during parsing. This would be twice a second (2hz, 500ms delay):
54# gps.send_command(b'PMTK220,500')
55
56# Main loop runs forever printing data as it comes in
57timestamp = time.monotonic()
58while True:
59 data = gps.read(32) # read up to 32 bytes
60 # print(data) # this is a bytearray type
61
62 if data is not None:
63 # convert bytearray to string
64 data_string = "".join([chr(b) for b in data])
65 print(data_string, end="")
66
67 if time.monotonic() - timestamp > 5:
68 # every 5 seconds...
69 gps.send_command(b"PMTK605") # request firmware version
70 timestamp = time.monotonic()
Time source
Simple script using GPS timestamps as RTC time source. The GPS timestamps are available without a full location fix if a single satellite can be seen. The GPS unit will keep the track of time while there is power source (i.e. a coin cell battery.)
1# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
2# SPDX-License-Identifier: MIT
3
4# Simple script using GPS timestamps as RTC time source
5# The GPS timestamps are available without a fix and keep the track of
6# time while there is powersource (ie coin cell battery)
7
8import time
9
10import board
11import busio
12import rtc
13
14import adafruit_gps
15
16uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
17# i2c = busio.I2C(board.SCL, board.SDA)
18
19gps = adafruit_gps.GPS(uart, debug=False)
20# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
21
22gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
23gps.send_command(b"PMTK220,1000")
24
25print("Set GPS as time source")
26rtc.set_time_source(gps)
27the_rtc = rtc.RTC()
28
29
30def _format_datetime(datetime):
31 date_part = f"{datetime.tm_mon:02}/{datetime.tm_mday:02}/{datetime.tm_year}"
32 time_part = f"{datetime.tm_hour:02}:{datetime.tm_min:02}:{datetime.tm_sec:02}"
33 return f"{date_part} {time_part}"
34
35
36last_print = time.monotonic()
37while True:
38 gps.update()
39 # Every second print out current time from GPS, RTC and time.localtime()
40 current = time.monotonic()
41 if current - last_print >= 1.0:
42 last_print = current
43 if not gps.timestamp_utc:
44 print("No time data from GPS yet")
45 continue
46 # Time & date from GPS informations
47 print(f"Fix timestamp: {_format_datetime(gps.timestamp_utc)}")
48
49 # Time & date from internal RTC
50 print(f"RTC timestamp: {_format_datetime(the_rtc.datetime)}")
51
52 # Time & date from time.localtime() function
53 local_time = time.localtime()
54
55 print(f"Local time: {_format_datetime(local_time)}")
Data logging
Simple GPS datalogging demonstration. This example uses the GPS library and to read raw NMEA sentences over I2C or UART from the GPS unit and dumps them to a file on an SD card (recommended), microcontroller internal storage (be careful as only a few kilobytes are available), or to a filesystem.
If you are using a microcontroller, before writing to internal storage you MUST carefully follow the steps in this guide to enable writes to the internal filesystem: Writing to the filesystem
1# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
2# SPDX-License-Identifier: MIT
3
4# Simple GPS datalogging demonstration.
5# This example uses the GPS library and to read raw NMEA sentences
6# over I2C or UART from the GPS unit and dumps them to a file on an SD card
7# (recommended), microcontroller internal storage (be careful as only a few
8# kilobytes are available), or to a filesystem.
9# If you are using a microcontroller, before writing to internal storage you
10# MUST carefully follow the steps in this guide to enable writes to the
11# internal filesystem:
12# https://learn.adafruit.com/adafruit-ultimate-gps-featherwing/circuitpython-library
13import sys
14
15import board
16import busio
17
18import adafruit_gps
19
20# Path to the file to log GPS data. By default this will be appended to
21# which means new lines are added at the end and all old data is kept.
22# Change this path to point at internal storage (like '/gps.txt') or SD
23# card mounted storage ('/sd/gps.txt') as desired.
24LOG_FILE = "gps.txt" # Example for writing to internal path gps.txt
25
26# File more for opening the log file. Mode 'ab' means append or add new lines
27# to the end of the file rather than erasing it and starting over. If you'd
28# like to erase the file and start clean each time use the value 'wb' instead.
29LOG_MODE = "ab"
30
31# sdcardio and adafruit_sdcard are NOT supported on blinka. If you are using a
32# Raspberry Pi or other single-board linux computer, the code will save the
33# output to the path defined in LOG_FILE above.
34if sys.platform != "linux":
35 import storage
36
37 SD_CS_PIN = board.D10 # CS for SD card using Adalogger Featherwing
38 try:
39 import sdcardio
40
41 sdcard = sdcardio.SDCard(board.SPI, SD_CS_PIN)
42 except ImportError:
43 import adafruit_sdcard
44 import digitalio
45
46 sdcard = adafruit_sdcard.SDCard(
47 board.SPI(),
48 digitalio.DigitalInOut(SD_CS_PIN),
49 )
50
51 vfs = storage.VfsFat(sdcard)
52 storage.mount(vfs, "/sd") # Mount SD card under '/sd' path in filesystem.
53 LOG_FILE = "/sd/gps.txt" # Example for writing to SD card path /sd/gps.txt
54
55# Create a serial connection for the GPS connection using default speed and
56# a slightly higher timeout (GPS modules typically update once a second).
57# These are the defaults you should use for the GPS FeatherWing.
58# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
59uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
60
61# If using a USB/Serial converter, use pyserial and update the serial
62# port name to match the serial connection for the GPS!
63# import serial
64# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
65
66# If using I2C, we'll create an I2C interface to talk to using default pins
67# i2c = board.I2C() # uses board.SCL and board.SDA
68# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
69
70# Create a GPS module instance.
71gps = adafruit_gps.GPS(uart) # Use UART/pyserial
72# gps = adafruit_gps.GPS_GtopI2C(i2c) # Use I2C interface
73
74# Main loop just reads data from the GPS module and writes it back out to
75# the output file while also printing to serial output.
76with open(LOG_FILE, LOG_MODE) as outfile:
77 while True:
78 sentence = gps.readline()
79 if not sentence:
80 continue
81 print(str(sentence, "ascii").strip())
82 outfile.write(sentence)
83 outfile.flush()
Satellite fix
This example uses GSA and GSV sentences from the GPS device to report on the quality of the received data from the satellites.
GSA - DOP(Dilution of Precision) and active satellites
GSV - Satellites in view
1# SPDX-FileCopyrightText: 2021 lesamouraipourpre
2# SPDX-License-Identifier: MIT
3
4# This example uses GSA and GSV sentences from the GPS device to report on the
5# quality of the received data from the satellites.
6# * GSA - DOP(Dilution of Precision) and active satellites
7# * GSV - Satellites in view
8
9import time
10
11import board
12
13import adafruit_gps
14
15# Create a serial connection for the GPS connection using default speed and
16# a slightly higher timeout (GPS modules typically update once a second).
17# These are the defaults you should use for the GPS FeatherWing.
18# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
19# import busio
20# uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
21
22# for a computer, use the pyserial library for uart access
23# import serial
24# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
25
26# If using I2C, we'll create an I2C interface to talk to using default pins
27i2c = board.I2C() # uses board.SCL and board.SDA
28# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
29
30# Create a GPS module instance.
31# gps = adafruit_gps.GPS(uart, debug=False) # Use UART/pyserial
32gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
33
34# Initialize the GPS module by changing what data it sends and at what rate.
35# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
36# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust
37# the GPS module behavior:
38# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
39
40# Turn on everything (not all of it is parsed!)
41gps.send_command(b"PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0")
42
43# Set update rate to once a second (1hz) which is what you typically want.
44gps.send_command(b"PMTK220,1000")
45# Or decrease to once every two seconds by doubling the millisecond value.
46# Be sure to also increase your UART timeout above!
47# gps.send_command(b'PMTK220,2000')
48# You can also speed up the rate, but don't go too fast or else you can lose
49# data during parsing. This would be twice a second (2hz, 500ms delay):
50# gps.send_command(b'PMTK220,500')
51
52
53def format_dop(dop):
54 # https://en.wikipedia.org/wiki/Dilution_of_precision_(navigation)
55 if dop > 20:
56 msg = "Poor"
57 elif dop > 10:
58 msg = "Fair"
59 elif dop > 5:
60 msg = "Moderate"
61 elif dop > 2:
62 msg = "Good"
63 elif dop > 1:
64 msg = "Excellent"
65 else:
66 msg = "Ideal"
67 return f"{dop} - {msg}"
68
69
70talkers = {
71 "GA": "Galileo",
72 "GB": "BeiDou",
73 "GI": "NavIC",
74 "GL": "GLONASS",
75 "GP": "GPS",
76 "GQ": "QZSS",
77 "GN": "GNSS",
78}
79
80# Main loop runs forever printing the location, etc. every second.
81last_print = time.monotonic()
82while True:
83 # Make sure to call gps.update() every loop iteration and at least twice
84 # as fast as data comes from the GPS unit (usually every second).
85 # This returns a bool that's true if it parsed new data (you can ignore it
86 # though if you don't care and instead look at the has_fix property).
87 if not gps.update() or not gps.has_fix:
88 time.sleep(0.1)
89 continue
90
91 if gps.nmea_sentence[3:6] == "GSA":
92 print(f"{gps.latitude:.6f}, {gps.longitude:.6f} {gps.altitude_m}m")
93 print(f"2D Fix: {gps.has_fix} 3D Fix: {gps.has_3d_fix}")
94 print(f" PDOP (Position Dilution of Precision): {format_dop(gps.pdop)}")
95 print(f" HDOP (Horizontal Dilution of Precision): {format_dop(gps.hdop)}")
96 print(f" VDOP (Vertical Dilution of Precision): {format_dop(gps.vdop)}")
97 print("Satellites used for fix:")
98 for s in gps.sat_prns:
99 talker = talkers[s[0:2]]
100 number = s[2:]
101 print(f" {talker}-{number} ", end="")
102 if gps.sats is None:
103 print("- no info")
104 else:
105 try:
106 sat = gps.sats[s]
107 if sat is None:
108 print("- no info")
109 else:
110 print(f"Elevation:{sat[1]}* Azimuth:{sat[2]}* SNR:{sat[3]}dB")
111 except KeyError:
112 print("- no info")
113 print()