Skip to content

Commit 6416856

Browse files
authored
Merge pull request #8 from ladyada/master
Make compatible with pyserial, add some examples as well for computer usage
2 parents e737b79 + 567f65c commit 6416856

File tree

5 files changed

+122
-20
lines changed

5 files changed

+122
-20
lines changed

adafruit_gps.py

+12-9
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class GPS:
7676
"""GPS parsing module. Can parse simple NMEA data sentences from serial GPS
7777
modules to read latitude, longitude, and more.
7878
"""
79-
def __init__(self, uart):
79+
def __init__(self, uart, debug=False):
8080
self._uart = uart
8181
# Initialize null starting values for GPS attributes.
8282
self.timestamp_utc = None
@@ -90,6 +90,7 @@ def __init__(self, uart):
9090
self.velocity_knots = None
9191
self.speed_knots = None
9292
self.track_angle_deg = None
93+
self.debug = debug
9394

9495
def update(self):
9596
"""Check for updated data from the GPS module and process it
@@ -101,11 +102,13 @@ def update(self):
101102
sentence = self._parse_sentence()
102103
if sentence is None:
103104
return False
105+
if self.debug:
106+
print(sentence)
104107
data_type, args = sentence
105-
data_type = data_type.upper()
106-
if data_type == 'GPGGA': # GGA, 3d location fix
108+
data_type = bytes(data_type.upper(), "ascii")
109+
if data_type == b'GPGGA': # GGA, 3d location fix
107110
self._parse_gpgga(args)
108-
elif data_type == 'GPRMC': # RMC, minimum location info
111+
elif data_type == b'GPRMC': # RMC, minimum location info
109112
self._parse_gprmc(args)
110113
return True
111114

@@ -115,15 +118,15 @@ def send_command(self, command, add_checksum=True):
115118
Note you should NOT add the leading $ and trailing * to the command
116119
as they will automatically be added!
117120
"""
118-
self._uart.write('$')
121+
self._uart.write(b'$')
119122
self._uart.write(command)
120123
if add_checksum:
121124
checksum = 0
122125
for char in command:
123-
checksum ^= ord(char)
124-
self._uart.write('*')
125-
self._uart.write('{:02x}'.format(checksum).upper())
126-
self._uart.write('\r\n')
126+
checksum ^= char
127+
self._uart.write(b'*')
128+
self._uart.write(bytes('{:02x}'.format(checksum).upper(), "ascii"))
129+
self._uart.write(b'\r\n')
127130

128131
@property
129132
def has_fix(self):

examples/computer_datalogging.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Simple GPS datalogging demonstration for use with a computer like Linux/desktop.
2+
# This actually doesn't even use the GPS library and instead just reads raw
3+
# NMEA sentences from the GPS unit and dumps them to a file.
4+
5+
import serial # pyserial is required
6+
7+
# Path to the file to log GPS data. By default this will be appended to
8+
# which means new lines are added at the end and all old data is kept.
9+
# Change this path to point at the filename desired
10+
LOG_FILE = 'gps.txt' # Example for writing to local file gps.txt
11+
12+
# File more for opening the log file. Mode 'ab' means append or add new lines
13+
# to the end of the file rather than erasing it and starting over. If you'd
14+
# like to erase the file and start clean each time use the value 'wb' instead.
15+
LOG_MODE = 'ab'
16+
17+
# Create a serial connection for the GPS connection using default speed and
18+
# a slightly higher timeout (GPS modules typically update once a second).
19+
# Update the serial port name to match the serial connection for the GPS!
20+
uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=3000)
21+
22+
# Main loop just reads data from the GPS module and writes it back out to
23+
# the output file while also printing to serial output.
24+
with open(LOG_FILE, LOG_MODE) as outfile:
25+
while True:
26+
sentence = uart.readline()
27+
print(str(sentence, 'ascii').strip())
28+
outfile.write(sentence)
29+
outfile.flush()

examples/gps_echotest.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Simple GPS module demonstration.
2+
# Will print NMEA sentences received from the GPS, great for testing connection
3+
# Uses the GPS only to send some commands, then reads directly from UART
4+
import time
5+
import board
6+
import busio
7+
8+
import adafruit_gps
9+
10+
11+
# Define RX and TX pins for the board's serial port connected to the GPS.
12+
# These are the defaults you should use for the GPS FeatherWing.
13+
# For other boards set RX = GPS module TX, and TX = GPS module RX pins.
14+
RX = board.RX
15+
TX = board.TX
16+
17+
# Create a serial connection for the GPS connection using default speed and
18+
# a slightly higher timeout (GPS modules typically update once a second).
19+
uart = busio.UART(TX, RX, baudrate=9600, timeout=3000)
20+
21+
# for a computer, use the pyserial library for uart access
22+
#import serial
23+
#uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=3000)
24+
25+
# Create a GPS module instance.
26+
gps = adafruit_gps.GPS(uart)
27+
28+
# Initialize the GPS module by changing what data it sends and at what rate.
29+
# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
30+
# PMTK_220_SET_NMEA_UPDATERATE but you can send anything from here to adjust
31+
# the GPS module behavior:
32+
# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
33+
34+
# Turn on the basic GGA and RMC info (what you typically want)
35+
gps.send_command(b'PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
36+
# Turn on just minimum info (RMC only, location):
37+
#gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
38+
# Turn off everything:
39+
#gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
40+
# Tuen on everything (not all of it is parsed!)
41+
#gps.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.
44+
gps.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+
# Main loop runs forever printing data as it comes in
53+
timestamp = time.monotonic()
54+
while True:
55+
data = uart.read(32) # read up to 32 bytes
56+
# print(data) # this is a bytearray type
57+
58+
if data is not None:
59+
# convert bytearray to string
60+
data_string = ''.join([chr(b) for b in data])
61+
print(data_string, end="")
62+
63+
if time.monotonic() - timestamp > 5:
64+
# every 5 seconds...
65+
gps.send_command(b'PMTK605') # request firmware version
66+
timestamp = time.monotonic()

examples/gps_simpletest.py

+14-10
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818
# a slightly higher timeout (GPS modules typically update once a second).
1919
uart = busio.UART(TX, RX, baudrate=9600, timeout=3000)
2020

21+
# for a computer, use the pyserial library for uart access
22+
#import serial
23+
#uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=3000)
24+
2125
# Create a GPS module instance.
22-
gps = adafruit_gps.GPS(uart)
26+
gps = adafruit_gps.GPS(uart, debug=False)
2327

2428
# Initialize the GPS module by changing what data it sends and at what rate.
2529
# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
@@ -28,22 +32,22 @@
2832
# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
2933

3034
# Turn on the basic GGA and RMC info (what you typically want)
31-
gps.send_command('PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
35+
gps.send_command(b'PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
3236
# Turn on just minimum info (RMC only, location):
33-
#gps.send_command('PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
37+
#gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
3438
# Turn off everything:
35-
#gps.send_command('PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
39+
#gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
3640
# Tuen on everything (not all of it is parsed!)
37-
#gps.send_command('PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
41+
#gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
3842

3943
# Set update rate to once a second (1hz) which is what you typically want.
40-
gps.send_command('PMTK220,1000')
44+
gps.send_command(b'PMTK220,1000')
4145
# Or decrease to once every two seconds by doubling the millisecond value.
4246
# Be sure to also increase your UART timeout above!
43-
#gps.send_command('PMTK220,2000')
47+
#gps.send_command(b'PMTK220,2000')
4448
# You can also speed up the rate, but don't go too fast or else you can lose
4549
# data during parsing. This would be twice a second (2hz, 500ms delay):
46-
#gps.send_command('PMTK220,500')
50+
#gps.send_command(b'PMTK220,500')
4751

4852
# Main loop runs forever printing the location, etc. every second.
4953
last_print = time.monotonic()
@@ -71,8 +75,8 @@
7175
gps.timestamp_utc.tm_hour, # not get all data like year, day,
7276
gps.timestamp_utc.tm_min, # month!
7377
gps.timestamp_utc.tm_sec))
74-
print('Latitude: {} degrees'.format(gps.latitude))
75-
print('Longitude: {} degrees'.format(gps.longitude))
78+
print('Latitude: {0:.6f} degrees'.format(gps.latitude))
79+
print('Longitude: {0:.6f} degrees'.format(gps.longitude))
7680
print('Fix quality: {}'.format(gps.fix_quality))
7781
# Some attributes beyond latitude, longitude and timestamp are optional
7882
# and might not be present. Check if they're None before trying to use!

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1+
pyserial

0 commit comments

Comments
 (0)