-
Notifications
You must be signed in to change notification settings - Fork 1
/
NMEAGPS.py
212 lines (161 loc) · 4.47 KB
/
NMEAGPS.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
"""
A basic GPS NMEA reader for UART on micropython.
Based on the servicepunkten.com FGPMMOPA6H breakout board but should probably work on others as well as they all follow the same standards.
http://www.servicepunkten.com/?p=62
Code by xix xeaon @ XIXIT.
See usage at the bottom.
"""
FXT_NONE = 0
FXT_NORMAL = 1
FXT_DIFFER = 2
FXT_dict = {0:"NONE", 1:"NORMAL", 2:"DIFFER"}
FXD_NONE = 1
FXD_2D = 2
FXD_3D = 3
FXD_dict = {1:"NONE", 2:"2D", 3:"3D"}
ANT_ACTIVE_SHORT = 1
ANT_INTERNAL = 2
ANT_ACTIVE = 3
ANT_dict = {1:"ACTIVE_SHORT", 2:"INTERNAL", 3:"ACTIVE"}
message_lengths = {
"GPGGA": 15,
"GPGSA": 18,
#"GPGSV": 0,
"GPRMC": 13,
"GPVTG": 10,
"PGTOP": 2,
}
def nmea_checksum(d):
c = 0
for x in d:
c = c ^ x
return c
def verify_data(data):
if not (
data.startswith(b"$") and
data[-5:].startswith(b"*") and
data.endswith(b"\r\n")
):
return None
cs = int(data[-4:-2], 16)
msg = data[1:-5]
if "$" in msg or "*" in msg:
return False
if not cs == nmea_checksum(msg):
return False
msg = msg.split(b',')
if msg[0] in message_lengths and not len(msg) == message_lengths[msg[0]]:
return False
return msg
def deg2dec(d):
return int(d[:-7]) + float(d[-7:].decode())/60
class NMEAGPS():
def __init__(self, uart):
self.uart = uart
self.date = None
self.time = None
self.fix_type = None
self.fix_dim = None
self.satellites = None
self.antenna = None
self.latitude = None
self.longitude = None
self.altitude = None
self.pdop = None
self.hdop = None
self.vdop = None
self.heading = None
self.speed = None
def read_sentences(self):
while self.uart.any():
data = uart.readline()
msg = verify_data(data)
if not msg: continue
#print("debug: %s" % (msg,))
if msg[0] == b'GPGGA': # Global Positioning System Fixed Data
self.handle_GPGGA(msg)
elif msg[0] == b'GPGSA': # GNSS DOP and Active Satellites
self.handle_GPGSA(msg)
elif msg[0] == b'GPGSV': # GNSS Satellites in View
pass
elif msg[0] == b'GPRMC': # Recommended Minimum Navigation Information
self.handle_GPRMC(msg)
elif msg[0] == b'GPVTG': # Course and speed information relative to the ground
self.handle_GPVTG(msg)
elif msg[0] == b'PGTOP': # Status of antenna
self.handle_PGTOP(msg)
#else:
#print(msg)
def handle_GPGGA(self, msg):
if msg[1]:
self.time = (int(msg[1][:2]), int(msg[1][2:4]), float(msg[1][4:].decode()))
else: self.time = None
fix = int(msg[6])
if fix in FXT_dict:
self.fix_type = fix
else:
self.fix_type = None
print("debug: unknown fix_type: %s" % fix) # seen 6?
self.satellites = int(msg[7])
if msg[2]:
self.latitude = deg2dec(msg[2]) * (1 if msg[3] == b'N' else -1)
else: self.latitude = None
if msg[4]:
self.longitude = deg2dec(msg[4]) * (1 if msg[5] == b'E' else -1)
else: self.longitude = None
if msg[9]:
self.altitude = float(msg[9].decode())
if msg[11]:
self.altitude += float(msg[11].decode())
else: self.altitude = None
if msg[8]:
self.hdop = float(msg[8].decode())
else: self.hdop = None
def handle_GPGSA(self, msg):
fix = int(msg[2])
if fix in FXD_dict:
self.fix_dim = fix
else:
self.fix_dim = None
print("debug: unknown fix_dim: %s" % fix)
if msg[15]:
self.pdop = float(msg[15].decode())
else: self.pdop = None
if msg[16]:
self.hdop = float(msg[16].decode())
else: self.hdop = None
if msg[17]:
self.vdop = float(msg[17].decode())
else: self.vdop = None
def handle_PGTOP(self, msg):
ant = int(msg[2])
if ant in ANT_dict:
self.antenna = ant
else:
self.antenna = None
print("debug: unknown antenna: %s" % ant)
def handle_GPRMC(self, msg):
if msg[9]:
self.date = (int(msg[9][:2]), int(msg[9][2:4]), int(msg[9][4:]))
else: self.date = None
def handle_GPVTG(self, msg):
if msg[1]:
self.heading = float(msg[1].decode())
else: self.heading = None
if msg[7]:
self.speed = float(msg[7].decode()) /60/60 *1000
else: self.speed = None
if __name__ == "__main__":
import pyb
uart = pyb.UART(3, baudrate=9600, bits=8, stop=1, parity=None)
gps = NMEAGPS(uart)
while True:
gps.read_sentences()
print("%sT%s | %s, %s, %sm | %s, %s, %s | %s*, %sm/s | type:%s, dim:%s, sats:%s, ant:%s" % (
gps.date, gps.time,
gps.latitude, gps.longitude, gps.altitude,
gps.pdop, gps.hdop, gps.vdop,
gps.heading, gps.speed,
FXT_dict.get(gps.fix_type), FXD_dict.get(gps.fix_dim), gps.satellites, ANT_dict.get(gps.antenna),
))
pyb.delay(100)