Arduino代码 – 读取GPS数据 GPS接收器最好的一点是,一旦给它们供电,就会开始发送数据。
测试此数据的最佳方法是使用Arduino作为USB-TTL转换器。以下是相关的代码: - // Choose two Arduino pins to use for software serial
- int RXPin = 2;
- int TXPin = 3;
- //Default baud of NEO-6M is 9600
- int GPSBaud = 9600;
- // Create a software serial port called "gpsSerial"
- SoftwareSerial gpsSerial(RXPin, TXPin);
- void setup()
- {
- // Start the Arduino hardware serial port at 9600 baud
- Serial.begin(9600);
- // Start the software serial port at the GPS's default baud
- gpsSerial.begin(GPSBaud);
- }
- void loop()
- {
- // Displays information when new sentence is available.
- while (gpsSerial.available() > 0)
- Serial.write(gpsSerial.read());
- }
复制代码
上传程序,然后在Arduino IDE打开串口监视器。记得选择9600波特率。您应该看到如下文本:
您通过串口获取的数据实际上是NMEA 语句。
NMEA是 National Marine Electronics Association(美国国家海洋电子协会)的首字母缩写。这是几乎所有GPS接收器的标准消息格式。NMEA标准采用称为句子的数据行格式。每个句子都用逗号分隔,以便计算机和微控制器更容易解析。
这些NMEA语句以称为更新率的间隔发送出去。
NEO-6M GPS模块默认每秒更新一次此信息(1Hz 频率)。但是您可以将其配置为每秒最多5次更新(5Hz 频率)。
解析NMEA句子 NMEA标准中有很多句子,最常见的有: ● $GPRMC(全球定位推荐最小坐标)提供时间、日期、纬度、经度、高度和估计速度。 ● $GPGGA 语句提供了提供3D位置和精度数据的基本修复数据。
让我们以来自GPS接收器的$GPRMC NMEA语句为例。 - $GPRMC, 123519, A, 4807.038, N, 01131.000, E,022.4, 084.4, 230394, 003.1, W*6A
复制代码$ 每个NMEA句子都以$字符开头。 GPRMC 全球定位推荐最小坐标(Global Positioning Recommended Minimum Coordinates) 123519 UTC 当前时间 – 12:35:19 A 状态 A=活动或 V=无效。 4807.038,N 纬度 48 度 07.038′ N 01131.000,E 经度 11 度 31.000′ E 022.4 对地速度(节) 084.4 以度为单位的轨道角度 220318 当前日期 – 2018 年 3 月 22 日 003.1,W 偏差 *6A 校验和数据,总是以 * 开头
让我们举个$GPGGA NMEA语句的例子。 - $GPGGA, 123519, 4807.038, N, 01131.000, E, 1, 08, 0.9, 545.4, M, 46.9, M, , *47
复制代码$ NMEA 语句的开始。 GPGGA 全球定位系统修复数据(Global Positioning System Fix Data) 123519 UTC 当前时间 – 12:35:19 4807.038,N 纬度 48 度 07.038′ N 01131.000,E 经度 11 度 31.000′ E 1 GPS 定位 08 被跟踪的卫星数量 0.9 平面精度指标 545.4,M 以米为单位的海拔高度(高于平均海平面) 46.9,M 大地水准面高度(平均海平面) (空白)自上次 DGPS 更新以来的时间(以秒为单位) (空白) DGPS 站 ID 号 *47 校验和数据,总是以 * 开头
有关NMEA句子及其包含的数据的更多信息,请查看gpsinformation.org
Arduino代码 – TinyGPS 库 通常对于我们的项目,我们需要将NMEA句子解析为有用的信息。为了简化我们的工作,我们使用TinyGPS++库。
这个库完成了从GPS模块接收数据所需的大量繁重工作,例如在后台读取和提取有用的数据。所以,我们不需要担心解析工作。感谢Mikal Hart的巨大贡献。他的网站 Arduiniana.org 全面概述了TinyGPS++库的所有功能。
首先通过访问GitHub存储库下载库,或者只需单击此按钮即可下载 zip:
TinyGPSPlus-1.0.3.zip
(46.64 KB, 下载次数: 1)
要安装它,请打开Arduino IDE,转到 Sketch > Include Library > Add .ZIP Library,然后选择刚刚下载的TinyGPSPlus ZIP文件。如果您需要有关安装库的更多详细信息,请访问此安装Arduino库教程。
安装库后,您可以将下面的草图复制到 Arduino IDE 中。以下测试草图将在串口监视器上打印位置信息(纬度、经度和海拔)和 UTC(日期和时间)。试试草图;然后我们将详细解释它。 - #include <TinyGPS++.h>
- #include <SoftwareSerial.h>
- // Choose two Arduino pins to use for software serial
- int RXPin = 2;
- int TXPin = 3;
- int GPSBaud = 9600;
- // Create a TinyGPS++ object
- TinyGPSPlus gps;
- // Create a software serial port called "gpsSerial"
- SoftwareSerial gpsSerial(RXPin, TXPin);
- void setup()
- {
- // Start the Arduino hardware serial port at 9600 baud
- Serial.begin(9600);
- // Start the software serial port at the GPS's default baud
- gpsSerial.begin(GPSBaud);
- }
- void loop()
- {
- // This sketch displays information every time a new sentence is correctly encoded.
- while (gpsSerial.available() > 0)
- if (gps.encode(gpsSerial.read()))
- displayInfo();
- // If 5000 milliseconds pass and there are no characters coming in
- // over the software serial port, show a "No GPS detected" error
- if (millis() > 5000 && gps.charsProcessed() < 10)
- {
- Serial.println("No GPS detected");
- while(true);
- }
- }
- void displayInfo()
- {
- if (gps.location.isValid())
- {
- Serial.print("Latitude: ");
- Serial.println(gps.location.lat(), 6);
- Serial.print("Longitude: ");
- Serial.println(gps.location.lng(), 6);
- Serial.print("Altitude: ");
- Serial.println(gps.altitude.meters());
- }
- else
- {
- Serial.println("Location: Not Available");
- }
-
- Serial.print("Date: ");
- if (gps.date.isValid())
- {
- Serial.print(gps.date.month());
- Serial.print("/");
- Serial.print(gps.date.day());
- Serial.print("/");
- Serial.println(gps.date.year());
- }
- else
- {
- Serial.println("Not Available");
- }
- Serial.print("Time: ");
- if (gps.time.isValid())
- {
- if (gps.time.hour() < 10) Serial.print(F("0"));
- Serial.print(gps.time.hour());
- Serial.print(":");
- if (gps.time.minute() < 10) Serial.print(F("0"));
- Serial.print(gps.time.minute());
- Serial.print(":");
- if (gps.time.second() < 10) Serial.print(F("0"));
- Serial.print(gps.time.second());
- Serial.print(".");
- if (gps.time.centisecond() < 10) Serial.print(F("0"));
- Serial.println(gps.time.centisecond());
- }
- else
- {
- Serial.println("Not Available");
- }
- Serial.println();
- Serial.println();
- delay(1000);
- }
复制代码
以下就是串口监视器上输出的样子。
草图首先包括TinyGPS++库和软件串口库。然后,我们定义NEO-6M GPS模块连接到的Arduino引脚和存储默认GPS波特率的变量。
创建TinyGPSPlus对象将有助于访问与库相关的特殊函数。接下来,我们创建一个名为gpsSerial的软件串口,我们可以通过它与模块通信。 - #include <TinyGPS++.h>
- #include <SoftwareSerial.h>
- int RXPin = 2;
- int TXPin = 3;
- int GPSBaud = 9600;
- TinyGPSPlus gps;
- SoftwareSerial gpsSerial(RXPin, TXPin);
复制代码
在setup()函数中,我们需要启动与计算机以及GPS模块的串口通信。 - void setup()
- {
- Serial.begin(9600);
- gpsSerial.begin(GPSBaud);
- }
复制代码
在loop()函数中,我们调用displayInfo()自定义函数,每次正确编码一个新的NMEA语句时,它都会在串口监视器上打印位置信息(纬度、经度和海拔)和 UTC(日期和时间)。
如果经过5000毫秒并且没有字符通过软件串口进入,我们将显示错误“No GPS detected”。 - void loop()
- {
- while (gpsSerial.available() > 0)
- if (gps.encode(gpsSerial.read()))
- displayInfo();
- if (millis() > 5000 && gps.charsProcessed() < 10)
- {
- Serial.println(F("No GPS detected"));
- while(true);
- }
- }
复制代码
TinyGPS++库中的其他有用函数 您可以将一些有用的函数与 TinyGPS++对象一起使用。下面列出了其中的几个: ● gps.speed.value() 函数以100节为单位返回当前地速。 ● gps.course.value() 函数以100度返回当前地面层。 ● gps.satellites.value() 函数返回可见的参与卫星的数量。 ● gps.hdop.value() 函数返回精度的水平减小。 ● 如果你想知道一个对象的数据有多旧,调用它的 age() 方法,它返回自上次更新以来的毫秒数。如果这返回的值大于 1500 左右,则可能是问题的征兆,例如丢失修复。 ● 如果您想从任何其他NMEA句子中提取数据。您可以通过告诉TinyGPS++ 句子名称和您感兴趣的字段编号来使用库的自定义提取函数,如下所示:TinyGPSCustom MagneticVariation(gps, "GPRMC", 10) 并且您可以像其他人一样查询它:magneticVariation.value( ) |