Simple test

Ensure your device works with this simple test.

examples/gps_simpletest.py
  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
  8import board
  9import busio
 10
 11import adafruit_gps
 12
 13# Create a serial connection for the GPS connection using default speed and
 14# a slightly higher timeout (GPS modules typically update once a second).
 15# These are the defaults you should use for the GPS FeatherWing.
 16# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
 17uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
 18
 19# for a computer, use the pyserial library for uart access
 20# import serial
 21# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
 22
 23# If using I2C, we'll create an I2C interface to talk to using default pins
 24# i2c = board.I2C()
 25
 26# Create a GPS module instance.
 27gps = adafruit_gps.GPS(uart, debug=False)  # Use UART/pyserial
 28# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False)  # Use I2C interface
 29
 30# Initialize the GPS module by changing what data it sends and at what rate.
 31# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
 32# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust
 33# the GPS module behavior:
 34#   https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
 35
 36# Turn on the basic GGA and RMC info (what you typically want)
 37gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
 38# Turn on just minimum info (RMC only, location):
 39# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
 40# Turn off everything:
 41# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
 42# Turn on everything (not all of it is parsed!)
 43# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
 44
 45# Set update rate to once a second (1hz) which is what you typically want.
 46gps.send_command(b"PMTK220,1000")
 47# Or decrease to once every two seconds by doubling the millisecond value.
 48# Be sure to also increase your UART timeout above!
 49# gps.send_command(b'PMTK220,2000')
 50# You can also speed up the rate, but don't go too fast or else you can lose
 51# data during parsing.  This would be twice a second (2hz, 500ms delay):
 52# gps.send_command(b'PMTK220,500')
 53
 54# Main loop runs forever printing the location, etc. every second.
 55last_print = time.monotonic()
 56while True:
 57    # Make sure to call gps.update() every loop iteration and at least twice
 58    # as fast as data comes from the GPS unit (usually every second).
 59    # This returns a bool that's true if it parsed new data (you can ignore it
 60    # though if you don't care and instead look at the has_fix property).
 61    gps.update()
 62    # Every second print out current location details if there's a fix.
 63    current = time.monotonic()
 64    if current - last_print >= 1.0:
 65        last_print = current
 66        if not gps.has_fix:
 67            # Try again if we don't have a fix yet.
 68            print("Waiting for fix...")
 69            continue
 70        # We have a fix! (gps.has_fix is true)
 71        # Print out details about the fix like location, date, etc.
 72        print("=" * 40)  # Print a separator line.
 73        print(
 74            "Fix timestamp: {}/{}/{} {:02}:{:02}:{:02}".format(
 75                gps.timestamp_utc.tm_mon,  # Grab parts of the time from the
 76                gps.timestamp_utc.tm_mday,  # struct_time object that holds
 77                gps.timestamp_utc.tm_year,  # the fix time.  Note you might
 78                gps.timestamp_utc.tm_hour,  # not get all data like year, day,
 79                gps.timestamp_utc.tm_min,  # month!
 80                gps.timestamp_utc.tm_sec,
 81            )
 82        )
 83        print("Latitude: {0:.6f} degrees".format(gps.latitude))
 84        print("Longitude: {0:.6f} degrees".format(gps.longitude))
 85        print(
 86            "Precise Latitude: {:2.}{:2.4f} degrees".format(
 87                gps.latitude_degrees, gps.latitude_minutes
 88            )
 89        )
 90        print(
 91            "Precise Longitude: {:2.}{:2.4f} degrees".format(
 92                gps.longitude_degrees, gps.longitude_minutes
 93            )
 94        )
 95        print("Fix quality: {}".format(gps.fix_quality))
 96        # Some attributes beyond latitude, longitude and timestamp are optional
 97        # and might not be present.  Check if they're None before trying to use!
 98        if gps.satellites is not None:
 99            print("# satellites: {}".format(gps.satellites))
100        if gps.altitude_m is not None:
101            print("Altitude: {} meters".format(gps.altitude_m))
102        if gps.speed_knots is not None:
103            print("Speed: {} knots".format(gps.speed_knots))
104        if gps.track_angle_deg is not None:
105            print("Track angle: {} degrees".format(gps.track_angle_deg))
106        if gps.horizontal_dilution is not None:
107            print("Horizontal dilution: {}".format(gps.horizontal_dilution))
108        if gps.height_geoid is not None:
109            print("Height geoid: {} meters".format(gps.height_geoid))

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.

examples/gps_echotest.py
 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
 8import board
 9import busio
10
11import adafruit_gps
12
13# Create a serial connection for the GPS connection using default speed and
14# a slightly higher timeout (GPS modules typically update once a second).
15# These are the defaults you should use for the GPS FeatherWing.
16# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
17uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
18
19# for a computer, use the pyserial library for uart access
20# import serial
21# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
22
23# If using I2C, we'll create an I2C interface to talk to using default pins
24# i2c = board.I2C()
25
26# Create a GPS module instance.
27gps = adafruit_gps.GPS(uart)  # Use UART/pyserial
28# gps = adafruit_gps.GPS_GtopI2C(i2c)  # Use I2C interface
29
30# Initialize the GPS module by changing what data it sends and at what rate.
31# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
32# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust
33# the GPS module behavior:
34#   https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
35
36# Turn on the basic GGA and RMC info (what you typically want)
37gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
38# Turn on just minimum info (RMC only, location):
39# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
40# Turn off everything:
41# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
42# Tuen on everything (not all of it is parsed!)
43# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
44
45# Set update rate to once a second (1hz) which is what you typically want.
46gps.send_command(b"PMTK220,1000")
47# Or decrease to once every two seconds by doubling the millisecond value.
48# Be sure to also increase your UART timeout above!
49# gps.send_command(b'PMTK220,2000')
50# You can also speed up the rate, but don't go too fast or else you can lose
51# data during parsing.  This would be twice a second (2hz, 500ms delay):
52# gps.send_command(b'PMTK220,500')
53
54# Main loop runs forever printing data as it comes in
55timestamp = time.monotonic()
56while True:
57    data = gps.read(32)  # read up to 32 bytes
58    # print(data)  # this is a bytearray type
59
60    if data is not None:
61        # convert bytearray to string
62        data_string = "".join([chr(b) for b in data])
63        print(data_string, end="")
64
65    if time.monotonic() - timestamp > 5:
66        # every 5 seconds...
67        gps.send_command(b"PMTK605")  # request firmware version
68        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.)

examples/gps_time_source.py
 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
 9import board
10import busio
11import rtc
12import adafruit_gps
13
14uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
15# i2c = busio.I2C(board.SCL, board.SDA)
16
17gps = adafruit_gps.GPS(uart, debug=False)
18# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False)  # Use I2C interface
19
20gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
21gps.send_command(b"PMTK220,1000")
22
23print("Set GPS as time source")
24rtc.set_time_source(gps)
25the_rtc = rtc.RTC()
26
27
28def _format_datetime(datetime):
29    return "{:02}/{:02}/{} {:02}:{:02}:{:02}".format(
30        datetime.tm_mon,
31        datetime.tm_mday,
32        datetime.tm_year,
33        datetime.tm_hour,
34        datetime.tm_min,
35        datetime.tm_sec,
36    )
37
38
39last_print = time.monotonic()
40while True:
41
42    gps.update()
43    # Every second print out current time from GPS, RTC and time.localtime()
44    current = time.monotonic()
45    if current - last_print >= 1.0:
46        last_print = current
47        if not gps.timestamp_utc:
48            print("No time data from GPS yet")
49            continue
50        # Time & date from GPS informations
51        print("Fix timestamp: {}".format(_format_datetime(gps.timestamp_utc)))
52
53        # Time & date from internal RTC
54        print("RTC timestamp: {}".format(_format_datetime(the_rtc.datetime)))
55
56        # Time & date from time.localtime() function
57        local_time = time.localtime()
58
59        print("Local time: {}".format(_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

examples/gps_datalogging.py
 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
17import adafruit_gps
18
19# Path to the file to log GPS data.  By default this will be appended to
20# which means new lines are added at the end and all old data is kept.
21# Change this path to point at internal storage (like '/gps.txt') or SD
22# card mounted storage ('/sd/gps.txt') as desired.
23LOG_FILE = "gps.txt"  # Example for writing to internal path gps.txt
24
25# File more for opening the log file.  Mode 'ab' means append or add new lines
26# to the end of the file rather than erasing it and starting over.  If you'd
27# like to erase the file and start clean each time use the value 'wb' instead.
28LOG_MODE = "ab"
29
30# sdcardio and adafruit_sdcard are NOT supported on blinka. If you are using a
31# Raspberry Pi or other single-board linux computer, the code will save the
32# output to the path defined in LOG_FILE above.
33if sys.platform != "linux":
34    import storage
35
36    SD_CS_PIN = board.D10  # CS for SD card using Adalogger Featherwing
37    try:
38        import sdcardio
39
40        sdcard = sdcardio.SDCard(board.SPI, SD_CS_PIN)
41    except ImportError:
42        import adafruit_sdcard
43        import digitalio
44
45        sdcard = adafruit_sdcard.SDCard(
46            board.SPI(),
47            digitalio.DigitalInOut(SD_CS_PIN),
48        )
49
50    vfs = storage.VfsFat(sdcard)
51    storage.mount(vfs, "/sd")  # Mount SD card under '/sd' path in filesystem.
52    LOG_FILE = "/sd/gps.txt"  # Example for writing to SD card path /sd/gps.txt
53
54# Create a serial connection for the GPS connection using default speed and
55# a slightly higher timeout (GPS modules typically update once a second).
56# These are the defaults you should use for the GPS FeatherWing.
57# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
58uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
59
60# If using a USB/Serial converter, use pyserial and update the serial
61# port name to match the serial connection for the GPS!
62# import serial
63# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
64
65# If using I2C, we'll create an I2C interface to talk to using default pins
66# i2c = board.I2C()
67
68# Create a GPS module instance.
69gps = adafruit_gps.GPS(uart)  # Use UART/pyserial
70# gps = adafruit_gps.GPS_GtopI2C(i2c)  # Use I2C interface
71
72# Main loop just reads data from the GPS module and writes it back out to
73# the output file while also printing to serial output.
74with open(LOG_FILE, LOG_MODE) as outfile:
75    while True:
76        sentence = gps.readline()
77        if not sentence:
78            continue
79        print(str(sentence, "ascii").strip())
80        outfile.write(sentence)
81        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

examples/gps_satellitefix.py
  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
 10import board
 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.
 18# import busio
 19# uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
 20
 21# for a computer, use the pyserial library for uart access
 22# import serial
 23# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
 24
 25# If using I2C, we'll create an I2C interface to talk to using default pins
 26i2c = board.I2C()
 27
 28# Create a GPS module instance.
 29# gps = adafruit_gps.GPS(uart, debug=False)  # Use UART/pyserial
 30gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False)  # 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 everything (not all of it is parsed!)
 39gps.send_command(b"PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0")
 40
 41# Set update rate to once a second (1hz) which is what you typically want.
 42gps.send_command(b"PMTK220,1000")
 43# Or decrease to once every two seconds by doubling the millisecond value.
 44# Be sure to also increase your UART timeout above!
 45# gps.send_command(b'PMTK220,2000')
 46# You can also speed up the rate, but don't go too fast or else you can lose
 47# data during parsing.  This would be twice a second (2hz, 500ms delay):
 48# gps.send_command(b'PMTK220,500')
 49
 50
 51def format_dop(dop):
 52    # https://en.wikipedia.org/wiki/Dilution_of_precision_(navigation)
 53    if dop > 20:
 54        msg = "Poor"
 55    elif dop > 10:
 56        msg = "Fair"
 57    elif dop > 5:
 58        msg = "Moderate"
 59    elif dop > 2:
 60        msg = "Good"
 61    elif dop > 1:
 62        msg = "Excellent"
 63    else:
 64        msg = "Ideal"
 65    return f"{dop} - {msg}"
 66
 67
 68talkers = {
 69    "GA": "Galileo",
 70    "GB": "BeiDou",
 71    "GI": "NavIC",
 72    "GL": "GLONASS",
 73    "GP": "GPS",
 74    "GQ": "QZSS",
 75    "GN": "GNSS",
 76}
 77
 78# Main loop runs forever printing the location, etc. every second.
 79last_print = time.monotonic()
 80while True:
 81    # Make sure to call gps.update() every loop iteration and at least twice
 82    # as fast as data comes from the GPS unit (usually every second).
 83    # This returns a bool that's true if it parsed new data (you can ignore it
 84    # though if you don't care and instead look at the has_fix property).
 85    if not gps.update() or not gps.has_fix:
 86        time.sleep(0.1)
 87        continue
 88
 89    if gps.nmea_sentence[3:6] == "GSA":
 90        print(f"{gps.latitude:.6f}, {gps.longitude:.6f} {gps.altitude_m}m")
 91        print(f"2D Fix: {gps.has_fix}  3D Fix: {gps.has_3d_fix}")
 92        print(f"  PDOP (Position Dilution of Precision): {format_dop(gps.pdop)}")
 93        print(f"  HDOP (Horizontal Dilution of Precision): {format_dop(gps.hdop)}")
 94        print(f"  VDOP (Vertical Dilution of Precision): {format_dop(gps.vdop)}")
 95        print("Satellites used for fix:")
 96        for s in gps.sat_prns:
 97            talker = talkers[s[0:2]]
 98            number = s[2:]
 99            print(f"  {talker}-{number} ", end="")
100            if gps.sats is None:
101                print("- no info")
102            else:
103                try:
104                    sat = gps.sats[s]
105                    if sat is None:
106                        print("- no info")
107                    else:
108                        print(f"Elevation:{sat[1]}* Azimuth:{sat[2]}* SNR:{sat[3]}dB")
109                except KeyError:
110                    print("- no info")
111        print()