五一期间,在安装了ubuntu mate系统的树莓派3b上,使用串口通讯进行了GPS模块的调试。
调试的基本步骤如下:
1.修改串口设置
2.将GPS模块和树莓派串口连接
3.通过minicom工具来获取串口上的数据
4.编程获取串口数据
5.解析GPS数据
具体如下:
一、修改串口设置
树莓派CPU内部有两个串口:
1.硬件串口(官方称为PL011 UART)
2.迷你串口(官方成为mini-uart)
在树莓派2B/B+这些老版树莓派上,官方设计时都是将“硬件串口”分配给GPIO的UART(GPIO14&GPIO15),因此可以独立调整串口的速率和模式。
而树莓派3B的设计上,官方在设计时将硬件串口分配给了新增的蓝牙模块上,而将一个没有时钟源,必须由内核提供时钟参考源的“迷你串口”分配给了GPIO的串口,这样以来由于内核的频率本身是变化的,就会导致“迷你串口”的速率不稳定,这样就出现了无法正常使用的情况。
目前解决方法:
关闭蓝牙对硬件串口的使用,将硬件串口重新恢复给GPIO的串口使用,也就意味着树莓派3的板载蓝牙和串口,两者是无法兼得的。
1.关闭蓝牙:
sudo systemctl disable hciuart
2.修改第一个配置文件
sudo nano /lib/systemd/system/hciuart.service
将文档中的所有“ttyAMA0”(若没有,就改serial1)改成“ttyS0”,总共需要修改两处,修改完后Ctrl+O保存退出。
3.修改第三个配置文件
sudo nano /boot/config.txt
在文档的结尾加上
dtoverlay=pi3-miniuart-bt
4.修改第四个配置文件
sudo nano /boot/cmdline.txt
把内容改成如下
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
5.更新系统后重启
一条一条的逐步执行以下命令
sudo apt-get update
sudo apt-get upgrade
sudo reboot
6.重启后关闭蓝牙串口,打开硬件串口
Interfacing Options => Serial =>No =>Yes
7.输入命令检查结果
ls -l /dev
结果应该是serial0 ->ttyAMA0,serial1 ->ttyS0
二、将GPS模块和树莓派串口连接
将GPS模块和树莓派模块进行连接
根据GPS模块的文档和树莓派的针脚定义一共需要连接4根线:VCC 5V、GND 接地、TXD和RXD
三、通过minicom工具来获取串口上的数据
1.安装minicom工具
sudo apt-get install minicom
2.通过命令获取串口上的数据
minicom -b 9600 -o -D /dev/ttyAMA0
其中9600为波特率,需要根据自己的GPS模块实际情况进行修改。我们之前买的模块版本就是4800的,所以需要集体问题具体分析。
获取的数据,模块在室内没有信号时如下:
模块在室外有信号时获得数据如下:
四、用Python编程获取串口的GPS数据
import serial
import pynmea2
import time
import datetime
from datetime import datetime,timezone,timedelta
dt=datetime.utcnow() #output computer utc time
#print(type(dt))
#print(dt)
dt=dt.replace(tzinfo=timezone.utc)
#print(dt)
tzutc_8=timezone(timedelta(hours=8))
local_dt=dt.astimezone(tzutc_8) #convert utc time to local time
print()
print("OUTCOME".center(60,"="))
print("the computer time is:",local_dt) #output computer local time
ser=serial.Serial("/dev/ttyAMA0",4800)
time.sleep(2) #delay the start time
count=ser.inWaiting() #judge the presence of GPS
while count!=0:
line= ser.readline() #pick up data of first line and the type of line is bytes
line=str(line) #convert bytes to str
pline=line[3:8] #intercept a part of the str
#print(pline)
if pline=="GNRMC":
line=line[2:-5] #intercept the valid part that can be prased
#print(line)
rmc=pynmea2.parse(line) #use the module named pynmea2 to parse the line
#print(rmc.status)
if rmc.status=="A": #judge the GPS's status of signal
print("-"*60)
print("surprise! the status is active!")
time=str(rmc.timestamp) #parse the GPS's time from line,then covert it to str
date=str(rmc.datestamp) #parse the GPS's date from line,then covert it to str
utctime=date+" "+time #combine the date and time
LOCAL_format = "%Y-%m-%d %H:%M:%S"
a=datetime.strptime(utctime,LOCAL_format) #convert type of timr from str to datetime
a=a.replace(tzinfo=timezone.utc)
tzutc_8=timezone(timedelta(hours=8))
local_a=a.astimezone(tzutc_8) #convert utc time to local time
print("the local GPS time is:",local_a)
latitude=int(float(rmc.lat)/100)+((float(rmc.lat)/100)-int(float(rmc.lat)/100))*100/60
longtitude=int(float(rmc.lon)/100)+(float(rmc.lon)/100-int(float(rmc.lon)/100))*100/60
print ("the local latitude is: ",round(latitude,6),'',rmc.lat_dir)
print ("the local longitude is: ",round(longtitude,6),'',rmc.lon_dir)
print("="*60)
else:
print("-"*60)
print("sorry! the status is void !\nlocation is not available!")
print("="*60)
break
五、解析GPS数据
pynmea2 模块兼容 Python 2 和 Python 3,能够解析 GPGSA、GPGGA、GPGSV、GPRMC、GPVTG、GPGLL 等 NMEA 0183 协议定义的各类数据,功能强大。
参考资料:
3.树莓派3(raspberry pi)串口(TTL) 通讯,试用于ubuntu mate系统