【得捷电子Follow me第1期】- 简易GPS定位仪
[复制链接]
本帖最后由 慕容雪花 于 2023-6-6 12:59 编辑
非常感谢EEWorld提供的Follow-Me活动平台,下面是我参加此次活动都帖子。
本文是一篇汇总贴,之前的4个帖子分别介绍了micropython基本语法,如何驱动OLED屏幕,如何获取网络时间以及如何获取GPS数据。作为一个总结贴,本文实现的基本功能算是对之前个模块的一个汇总:在OLED显示屏上显示从网络获取到时间和从GPS模块获取到经纬度信息。
一、基本硬件介绍
本次活动使用的板卡是树莓派PICO虽然性能虽然比不上传统的树莓派,但是搭载了双核 ARM Cortex M0 + 处理器,运行频率高达 133MHz 灵活时钟,内置了 264KB 的 SRAM 和 2MB 的片上 Flash,这也弥补了没有片上FLASH的缺点。
树莓派官方提供了C/C++的SDK,同时也支持Micropython开发。Micropython是Python3编程语言的完全实现,它直接运行中Raspberry Pi Pico等嵌入式硬件上。
Micropython是一种解释性语言,本身非常容易理解。比如下面的代码是典型的闪烁LED灯的代码:
import machine
import time
led = machine.Pin('LED', machine.Pin.OUT)
while(True):
led.on()
time.sleep(1)
led.off()
time.sleep(1)
首先引入machine和time模块,其中machine模块提供了对RP2040硬件相关的操作,time模块提供了延迟等时间相关的函数。while循环中,每隔1s中小灯亮一次,从而使用micropython实现了最基本的GPIO控制操作。下面是演示视频,注意USB插座左侧的LED灯每隔1s中小灯亮一次
3ef136d2bd52288579165cc9c02a0d16
二、OLED屏幕驱动
这个OLED扩展板使用的是SSD1315,而大家最熟悉的莫过于SSD1306。这两者分辨率都是128*64,电压都在3.3v,实际上它们可以互相替代。
from machine import Pin, I2C
from ssd1315_goBro import SSD1315_I2C
i2c=I2C(0,sda=Pin(8), scl=Pin(9), freq=400000)
oled = SSD1315_I2C(128, 64, i2c)
oled.text("WELCOME!", 0, 0)
oled.text("This is EEWORLD", 0, 16)
oled.text("FOLLOW ME", 0, 32)
oled.text("JOIN US", 0, 48)
oled.show()
效果展示:
三、网络时间获取
网络时间点获取首先要解决联网的问题,其次要找到获取网络时间点方法。 比较重要的两个库是time和network,要在代码中首先import过来。其次要选择PICO-W的联网模式,STA_IF表示PICO-W作为station,连接到附近的AP(access point)也就是家里的路由器。
import time
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
access_points = wlan.scan()
for AP in access_points:
print(AP)
wlan.connect("TP-LINK_xxx", "xxxx")
while not wlan.isconnected() and wlan.status() >= 0:
print("Waiting to connect:")
led.toggle()
time.sleep(1)
led.off()
print(wlan.isconnected())
print("Pico-W IP addr is: " + wlan.ifconfig()[0])
联网成功后,可以在控制台看到相应的IP地址等信息。
(b'WaKuWaKu', b'\x00K\xf3n\xc5\x8f', 8, -71, 7, 2)
(b'ComeOn', b'\x14\xe9\xb27\x84M', 1, -88, 7, 1)
True
Pico-W IP addr is: 192.168.0.101
micropython有一个开源的获取网络时间的库ntptime.py。这个库在Github上有源代码,可以拷贝到本地然后重命名即可在自己对代码中作为库来用。注意本文选用了aliyun的服务器,比较稳定。
def get_time():
print("同步時間")
print()
print("同步前本地時間:%s" %str(time.localtime()))
print("##")
ntptimeVer2.host = 'ntp1.aliyun.com'
ntptimeVer2.settime() # 修改設備時間
print("同步后本地時間:%s" %str(time.localtime()))
print("##################################################")
rtc = RTC()
print(rtc.datetime())
mytime = rtc.datetime()
mytime2='%d-%d-%d %s %d:%d:%d'%(mytime[0],mytime[1],mytime[2],week[mytime[3]], mytime[4],mytime[5],mytime[6])
print(mytime2)
在控制台可以看到获取到的网络时间
同步時間
同步前本地時間:(2023, 6, 6, 10, 7, 36, 1, 157)
##
Inside settime, using Host: %s ntp1.aliyun.com
同步后本地時間:(2023, 6, 6, 10, 7, 37, 1, 157)
##################################################
(2023, 6, 6, 1, 10, 7, 37, 0)
2023-6-6 Tue 10:7:37
2023-06-06 Tue 10:07:37
2023-06-06 Tue 10:07:38
2023-06-06 Tue 10:07:39
2023-06-06 Tue 10:07:40
2023-06-06 Tue 10:07:41
2023-06-06 Tue 10:07:42
2023-06-06 Tue 10:07:43
2023-06-06 Tue 10:07:44
2023-06-06 Tue 10:07:45
四、GPS数据获取
这个GPS模块是自己参加这期FOLLOW-ME活动的主要原因。这次使用的GPS模块是Seeed推出的Air530,不仅仅支持GPS,还有咱们中国的北斗,包括: GPS / Beidou / Glonass / Galileo / QZSS / SBAS。
相关的参数如下:
- Supply voltage 3.3V/5V
- Working current up to 60mA
- Interface UART
- Time of warm start 4s
- Time of cold boot 30s
该模块有4个引脚,分别是:
GND |
接地 |
TX |
串口发送 |
RX |
串口接收 |
VCC |
电源 |
通过读取UART数据,可以发现有非常多种格式的卫星数据可以获取,
$GNGGA:GPS/北斗定位信息
$GNGSA:当前卫星信息
$GPGSV:可见GPS卫星信息
$BDGSV:可见北斗卫星信息
$GNRMC:推荐定位信息
$GNVTG:地面速度信息
$GNGLL:大地坐标信息
$GNZDA:当前时间UTC(1)信息
本文选择了其中一种:GNGLL。
$GNGLL,<1>,<2>,<3>,<4>,<5>,<6>,<7>*<8><CR><LF>
<1>纬度ddmm.mmmm,度分格式(前导位数不足则补0)
<2>纬度N(北纬)或S(南纬)
<3>经度dddmm.mmmm,度分格式(前导位数不足则补0)
<4>经度E(东经)或W(西经)
<5>UTC时间,hhmmss.sss格式
<6>状态,A=定位,V=未定位
<7>模式指示,A-自动模式;D-差分模式;E-估算(航位推算)模式;M-手动
输入模式;S-模拟器模式
< 8>校验值
主要的代码如下:
def getGPS(gpsModule):
global FIX_STATUS, TIMEOUT, latitude, longitude, satellites, GPStime
timeout = time.time() + 8
while True:
gpsModule.readline()
buff = str(gpsModule.readline())
parts = buff.split(',')
print(buff)
if (parts[0] == "b'$GNGLL" and len(parts) == 8):
if(parts[1] and parts[2] and parts[3] and parts[4] and parts[5] and parts[6] and parts[7]):
print(buff)
latitude = convertToDegree(parts[1])
if (parts[2] == 'S'):
latitude = -latitude
longitude = convertToDegree(parts[3])
if (parts[4] == 'W'):
longitude = -longitude
#satellites = parts[7]
GPStime = str((int(parts[5][0:2])+8)%24) + ":" + parts[5][2:4] + ":" + parts[5][4:6]
FIX_STATUS = True
break
if (time.time() > timeout):
TIMEOUT = True
break
utime.sleep_ms(500)
def convertToDegree(RawDegrees):
RawAsFloat = float(RawDegrees)
firstdigits = int(RawAsFloat/100)
nexttwodigits = RawAsFloat - float(firstdigits*100)
Converted = float(firstdigits + nexttwodigits/60.0)
Converted = '{0:.6f}'.format(Converted)
return str(Converted)
控制台输出结果如下,可以看到在获取到有效的GNGLL数据后,接下来程序正确解析出了精度和纬度。
----------------------
mytime is: 2023-06-06 Tues 09:09:44
mytime is: 2023-06-06 Tues 09:09:45
mytime is: 2023-06-06 Tues 09:09:46
mytime is: 2023-06-06 Tues 09:09:47
mytime is: 2023-06-06 Tues 09:09:48
b'$GNGSA,A,3,06,08,09,16,24,39,,,,,,,3.7,2.1,3.0,4*3C\r\n'
b'$GNGLL,3168.46110,N,12176.26956,E,010943.000,A,A*49\r\n'
b'$GNGLL,3418.46110,N,12156.26956,E,010943.000,A,A*49\r\n'
Printing GPS data...
Latitude: 33.307686
Longitude: 123.437828
Satellites:
Time: 9:09:43
----------------------
五、结果展示
【得捷电子Follow me第1期】- 简易GPS定位仪
六、建议
我非常感谢EEWorld联合得捷举办的此次Follow-Me系列活动,通过此次活动,我深入了解了树莓派PICO-W这个功能强大的开发板以及Air-530这款性能卓越的GNSS模块。其实自己一直比较好奇GPS是怎么定位到,通过这次活动也让自己找到了答案。
希望eeworld能够在接下来的新一期活动中安排上更好玩的板子,直播最好安排在活动开始后的一个月内,这样大家有充足的时间来好好上手做东西。
再次感谢!祝FOLLOW-ME活动越来越好!
|