今天在 Beetle ESP32-C3 上测试了 GNSS 功能。GNSS是 VK2828,北斗+GPS双模的,定位速度还比较快。
GNSS的电源直接用Beetle ESP32-C3上的3.3V,为了方便连接,串口使用GPIO0和GPIO1两个引脚。
参考测试程序
from machine import UART
'''
mini GNSS Data analysis
'''
class uGNSS():
GNSS_DIR = ('N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S',
'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW')
GNSS_VALID = (b'1', b'2')
version = '1.0'
def __init__(self, uart, baudrate = 9600, bufsize = 2048):
self.latitude = 0.0
self.longitude = 0.0
self.latitude_dir = 'N'
self.longitude_dir = 'E'
self.speed = 0.0
self.course = 0.0
self.altitude = 0.0
self.geoid_height = 0.0
self.date = [0, 0, 0]
self.time = [0, 0, 0]
self.datetime = [0, 0, 0, 0, 0, 0, 0, 0]
self.valid = False
self.satellites_in_view = 0
self.satellites_in_use = 0
self.satellites_used = []
self.hdop = 0.0
self.pdop = 0.0
self.vdop = 0.0
self._crc = bytearray(1)
self._buf = bytearray(256)
self._pos = 0
self._seg = []
self._dat = bytearray(bufsize)
self._dat_n = 0
self.uart = uart
self.uart.init(baudrate = 9600, rxbuf = bufsize)
def checksum(self, buf, length):
self._crc[0] = 0
for i in range(1, length):
self._crc[0] ^= buf[i]
try:
d = int(b'0x'+buf[length+1:length+3])
except:
return False
return self._crc[0] == d
def parse(self):
try:
if not self.checksum(self._buf, self._pos-4):
return False
self._seg = bytes(self._buf[1:self._pos-4]).split(b',')
if self._seg[0] in self.GNSS_CMD:
try:
self.GNSS_CMD[self._seg[0]](self)
return True
except:
return False
return False
finally:
self._pos = 0
def update_char(self, c):
if self._pos:
if self._pos > 250:
self._pos = 0
return False
else:
if type(c) is int:
self._buf[self._pos] = c
elif type(c) is str:
self._buf[self._pos] = ord(c)
else:
self._pos = 0
return False
if self._buf[self._pos] == ord('\n'):
return self.parse()
else:
self._pos += 1
else:
if c == '$' or c == ord(b'$'):
self._buf[0] = 36
self._pos = 1
def _update(self, dat, n=0):
if n == 0:
n = len(dat)
for i in range(n):
self.update_char(dat[i])
return self.valid
def update(self):
self._dat_n = self.uart.any()
if self._dat_n == 0:
return False
self.uart.readinto(self._dat)
self._update(self._dat, self._dat_n)
return self.valid
def _time(self, dat):
h, m, s = dat[0:2], dat[2:4], dat[4:6]
self.time = [int(h), int(m), int(s)]
self.datetime[4:7] = self.time
def _date(self, dat):
d, m, y = dat[0:2], dat[2:4], dat[4:6]
self.date = [int(y), int(m), int(d)]
self.datetime[0:3] = self.date
def _latlon(self, dat):
t = float(dat)
d, m = divmod(t, 100)
return d + m/60
def _GNGGA(self):
self._time(self._seg[1])
self.latitude = self._latlon(self._seg[2])
self.latitude_dir = self._seg[3].decode()
self.longitude = self._latlon(self._seg[4])
self.longitude_dir = self._seg[5].decode()
self.valid = self._seg[6] in self.GNSS_VALID
self.satellites_in_use = int(self._seg[7])
self.hdop = float(self._seg[8])
self.altitude = float(self._seg[9])
self.geoid_height = float(self._seg[11])
def _GNRMC(self):
self._time(self._seg[1])
self._date(self._seg[9])
self.valid = (self._seg[2] == b'A')
self.latitude = self._latlon(self._seg[3])
self.latitude_dir = self._seg[4].decode()
self.longitude = self._latlon(self._seg[5])
self.longitude_dir = self._seg[6].decode()
self.speed = float(self._seg[7])
self.course = float(self._seg[8])
def _GNVTG(self):
self.course = float(self._seg[1])
self.speed = float(self._seg[7])
def _GNGLL(self):
self.latitude = self._latlon(self._seg[1])
self.latitude_dir = self._seg[2]
self.longitude = self._latlon(self._seg[3])
self.longitude_dir = self._seg[4]
self._time(self._seg[5])
self.valid = (self._seg[6] == b'A')
def _GNGSA(self):
self.pdop = float(self._seg[15])
self.hdop = float(self._seg[16])
self.vdop = float(self._seg[17])
def _GPGSV(self):
self.satellites_in_view = int(self._seg[3])
GNSS_CMD = {
b'GNGGA': _GNGGA,
b'GNRMC': _GNRMC,
b'GNVTG': _GNVTG,
b'GNGLL': _GNGLL,
b'GPGSV': _GPGSV,
b'GNGSA': _GNGSA
}
def info(self):
print('GNSS valid:', self.valid)
print('lat:', self.latitude, self.latitude_dir)
print('lon:', self.longitude, self.longitude_dir)
print('speed:', self.speed)
print('altitude:', self.altitude, self.geoid_height)
print('hdop:', self.hdop)
print('pdop:', self.pdop)
print('vdop:', self.vdop)
print('UTC:', self.datetime, self.date, self.time)
print('satellites')
print(' in view:', self.satellites_in_view)
print(' in use: ', self.satellites_in_use)
print(' list: ', self.satellites_used)
def test(self, n=60, interval=1000):
from time import sleep_ms
while True:
if n > 0:
n -= 1
else:
return
self.update()
self.info()
sleep_ms(interval)
ug = UART(1, baudrate=9600, tx=0, rx=1, rxbuf=2048)
G=uGNSS(ug)
G.test()