ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

IoT-For-Beginners 实战:Wio Terminal 上使用 TinyGPSPlus 解码 GPS NMEA 数据

IoT-For-Beginners 实战:Wio Terminal 上使用 TinyGPSPlus 解码 GPS NMEA 数据 IoT-For-Beginners 实战Wio Terminal 上使用 TinyGPSPlus 解码 GPS NMEA 数据【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners本篇指南对应 IoT-For-Beginners 课程「运输场景 · 第 1 课位置跟踪Location tracking」的第二阶段在前一课通过 UART 读取出 GPS 模块的原始 NMEA 报文之后如何使用开源库 TinyGPSPlus 逐字符解码这些报文最终提取出十进制度表示的纬度、经度与参与定位的卫星数量。读完后你将掌握在 Wio Terminal 上配置 PlatformIO 库依赖、编写 NMEA 解码循环并通过串口监视器验证 GPS 定位结果的完整流程。Wio Terminal 左侧 Grove 接口连接的 Grove GPS 传感器前提你已经能从 Wio Terminal 读到原始 NMEA 数据本节是 位置跟踪课程 的延续。其前置步骤记录在 Read GPS data - Wio Terminal 中Grove GPS Air530 传感器通过 Grove 线接到 Wio Terminal 屏幕朝你时左侧的 Grove 接口代码侧通过自定义的Serial3UART 端口9600 波特率读取数据。运行前置课程代码后串口监视器里会看到如下看似乱码的输出——它们其实是标准 GPS 数据$GNGGA,020604.001,4738.538654,N,12208.341758,W,1,3,,164.7,M,-17.1,M,,*67 $GPGSA,A,1,,,,,,,,,,,,,,,*1E $BDGSA,A,1,,,,,,,,,,,,,,,*0F $GPGSV,1,1,00*79 $BDGSV,1,1,00*68理解这些报文的关键点来自课程 Location tracking 主文档GPS 传感器按NMEA 0183 标准输出文本报文。每条报文sentence以$开头后跟 2 个字符表示消息来源GP为美国 GPS 系统GN为综合导航系统BD为北斗等再跟 3 个字符表示消息类型其余为逗号分隔的字段以换行符结尾。常见的消息类型包括GGAGPS 定位数据含纬度、经度、海拔与参与定位的卫星数、ZDA当前日期与时间、GSV可见卫星详情。GGA中的经纬度采用(dd)dmm.mmmm格式并附带方向字符d是度m是分秒以小数分钟表示。例如$GNGGA报文中的纬度部分4738.538654,N表示北纬 47°38.538654换算成十进制度即47.6423109经度部分12208.341758,W表示西经 122°08.341758换算为-122.1390293N/S表示南北纬E/W表示东西经西经取负值。坐标的书写顺序始终是latitude, longitude纬度在前经度在后。手工按上述规则解析字段固然可行但更稳健的做法是使用现成的 NMEA 解码库——这正是本篇要做的事。第 1 步为项目添加 TinyGPSPlus 库依赖打开gps-sensor应用工程如果尚未打开。TinyGPSPlus 是一个专门用于解码 NMEA 报文的开源库需要把它声明为 PlatformIO 的库依赖。在工程的 platformio.ini 中添加lib_deps配置lib_deps mikalhart/TinyGPSPlus 1.0.2仓库中该工程的完整 platformio.ini 如下可以看到lib_deps是在 Wio Terminal 目标环境声明下追加的; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:seeed_wio_terminal] platform atmelsam board seeed_wio_terminal framework arduino lib_deps mikalhart/TinyGPSPlus 1.0.2各配置项含义platform atmelsam指定 Atmel SAM 芯片平台Wio Terminal 搭载 SAMD21board seeed_wio_terminal指定具体板卡framework arduino使用 Arduino 框架编译lib_deps固定引用 TinyGPSPlus 的1.0.2版本保证不同人编译时依赖版本一致。执行构建时 PlatformIO 会自动下载该库并参与编译。第 2 步在 main.cpp 中引入 TinyGPSPlus 解码器在 src/main.cpp 顶部为 TinyGPSPlus 库添加 include 指令#include TinyGPS.h然后在Serial3声明的下方声明一个 TinyGPSPlus 对象用它来逐字符处理 NMEA 语句TinyGPSPlus gps;对照仓库中解码版工程的 src/main.cpp文件头部的完整声明区为#include Arduino.h #include wiring_private.h #include TinyGPS.h static Uart Serial3(sercom3, PIN_WIRE_SCL, PIN_WIRE_SDA, SERCOM_RX_PAD_1, UART_TX_PAD_0); TinyGPSPlus gps;其中Serial3是前置课程已建立的 UART 端口复用 Grove 口上的PIN_WIRE_SCL/PIN_WIRE_SDA引脚为 SERCOM3TinyGPSPlus gps;即为本次新增的 NMEA 解码器实例。从源码结构看gps是一个纯软件状态机对象不直接绑定任何硬件只负责接收字符流并维护「是否收到完整语句」「位置是否有效」等内部状态因此它可以被喂入来自任意串口、文件甚至虚拟设备模拟的数据源。第 3 步改写 printGPSData 函数实现逐字符解码将printGPSData函数的内容修改为if (gps.encode(Serial3.read())) { if (gps.location.isValid()) { Serial.print(gps.location.lat(), 6); Serial.print(F(,)); Serial.print(gps.location.lng(), 6); Serial.print( - from ); Serial.print(gps.satellites.value()); Serial.println( satellites); } }仓库中 src/main.cpp 的printGPSData与此一致。这段代码的工作方式是逐字符驱动的Serial3.read()从 UART 串口读出下一个字符-1 表示无数据gps.encode(...)把该字符送入 TinyGPSPlus 的 NMEA 解码器。解码器内部按 NMEA 0183 规则累积字符只有当它成功解析出一条完整且校验通过的语句时才返回true每当encode返回true即刚读完一条有效语句再调用gps.location.isValid()判断解码器是否已从GGA等语句中确认出一个有效位置位置有效时把gps.location.lat()纬度与gps.location.lng()经度以 6 位小数打印到串口监视器并附上gps.satellites.value()报告的参与本次定位的卫星数量。Serial.print(value, 6)的第二个参数 6 即小数位数正好对应 GGA 报文「以小数分表示秒」精度换算到十进制度后的小数位F(,)使用 PROGMEM 字符串宏把字面量放进程序存储器以节省 RAM。也就是说每读取一个字符就检查一次解码器是否凑齐了一条有效语句若凑齐且位置有效就把「纬度,经度 - 由 N 颗卫星定位」的输出推送到串口监视器。第 4 步构建、上传并验证构建并把代码上传到 Wio TerminalPlatformIO 的 Upload 命令或命令面板中的相应任务。代码上传完成后打开串口监视器观察 GPS 定位数据。预期输出形如 Executing task: platformio device monitor --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time --- More details at http://bit.ly/pio-monitor-filters --- Miniterm on /dev/cu.usbmodem1201 9600,8,N,1 --- --- Quit: CtrlC | Menu: CtrlT | Help: CtrlT followed by CtrlH --- 47.6423109,-122.1390293 - from 3 satellites示例中输出的47.6423109,-122.1390293正是前置章节用$GNGGA,020604.001,4738.538654,N,12208.341758,W,...手工换算得到的坐标可用来交叉验证解码结果的正确性。监视器头部显示9600,8,N,1说明串口监视器需与Serial.begin(9600)保持一致的波特率。 该工程的完整代码位于 code-gps-decode/wio-terminal 目录工程根目录为3-transport/lessons/1-location-tracking/code-gps-decode/wio-terminal/gps-sensor/。至此你的 GPS 传感器程序就成功实现了 NMEA 数据解码。源码细节解码版工程与原始读取版的差异将解码版工程 code-gps-decode/wio-terminal/.../src/main.cpp 与前一步原始读取版工程 code-gps/wio-terminal/.../src/main.cpp 对比可以清楚看到本步骤的最小改动面关注点原始读取版code-gps解码版code-gps-decode头文件Arduino.h、wiring_private.h额外新增#include TinyGPS.h全局对象仅static Uart Serial3(...)新增TinyGPSPlus gps;printGPSData实现Serial.println(Serial3.readStringUntil(\n));整行打印原始报文gps.encode(Serial3.read())逐字符解码后打印结构化坐标setup/loop9600 初始化、pinPeripheral(PIN_WIRE_SCL, PIO_SERCOM_ALT)、while (Serial3.available() 0)循环完全相同SERCOM3 中断处理SERCOM3_0_Handler~SERCOM3_3_Handler四个弱中断入口转调Serial3.IrqHandler()完全相同两个值得注意的实现细节读取粒度的变化原始版用readStringUntil(\n)一次读完一整条 NMEA 语句NMEA 语句以换行符结尾这与 wio-terminal-gps-sensor.md 中的解释一致整行转发到监视器解码版改为每次只读一个字符交给gps.encode()把「按行切分 字段解析」的责任全部交给库的状态机这也是 NMEA 解码的推荐方式。中断与引脚复用src/main.cpp 底部保留的SERCOM3_0_Handler至SERCOM3_3_Handler四个函数是 Atmel SAMD 系列 SERCOM3 外设的中断入口负责把 UART 中断转发给Serial3.IrqHandler()setup中的pinPeripheral(PIN_WIRE_SCL, PIO_SERCOM_ALT)则把 Grove 引脚复用为 SERCOM 功能。这部分硬件层配置由前置课程负责解码库完全不关心数据来源二者职责分离清晰。延伸其他设备的解码方式与课程挑战本课还面向树莓派/虚拟设备提供了平行的解码指南见 single-board-computer-gps-decode.md虚拟设备则可用 Counterfit 虚拟 GPS 传感器 通过预设经纬度或 NMEA 语句流来模拟定位数据方便在无实体硬件时验证解码逻辑。课程主文档 Location tracking 中还有一个进阶挑战不依赖第三方库自己编写一个 NMEA 解码器从GGA语句中提取经纬度。结合本文介绍的(dd)dmm.mmmm字段格式、方向字符符号规则N/S、E/W与十进制度换算公式十进制度 度 分 / 60你可以尝试仅用字符串切分与算术运算复现4738.538654,N - 47.6423109这类换算作为对 TinyGPSPlus 内部逻辑的一次「白盒验证」。【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表