从序列中解析NMEA句子

Parsing NMEA sentences from serial

本文关键字:NMEA 句子      更新时间:2023-10-16

我想在Arduino上使用TinyGPS++来解析NMEA数据并在OLED显示器上显示信息。但是,NMEA数据将通过USB接收,而不是使用软件串行和TX/RX引脚。

我遵循了TinyGPS++的例子,但是我遇到了两个问题:

1) 当我在串行监视器(Windows, Arduino 1.6.9)上发送一个NMEA句子时,只有前64个字符被Arduino接收。我该如何克服这个限制?我通过删除几个小数点来帮助自己,但这不是首选的方法。

2) 在TinyGPS++ basic示例中,在只读内存中定义了一个示例NMEA字符串:

// A sample NMEA stream.
const char *gpsStream =
  "$GPRMC,045103.0,A,3014.0,N,09748.0,W,36.88,65.02,030913,,,A*7Crn"
  "$GPGGA,045104.0,3014.0,N,09749.0,W,1,09,1.2,211.6,M,-22.5,M,,*62rn"
  "$GPRMC,045200.0,A,3014.0,N,09748.0,W,36.88,65.02,030913,,,A*77rn"
  "$GPGGA,045201.0,3014.0,N,09749.0,W,1,09,1.2,211.6,M,-22.5,M,,*6Crn"
  "$GPRMC,045251.0,A,3014.0,N,09748.0,W,36.88,65.02,030913,,,A*7Drn"
  "$GPGGA,045252.0,3014.0,N,09749.0,W,1,09,1.2,211.6,M,-22.5,M,,*6Frn";

并由

解析
while (*gpsStream) {
  Serial.print(*gpsStream);
  gps.encode(*gpsStream++);
}

我这样接收我的NMEA(不幸的是只有一行):

if (Serial.available()) {
  while (Serial.available() > 0) {
    if(index < 80)
    {
      inChar = Serial.read();
      inData[index] = inChar;
      index++;
      inData[index] = '';
    }
  }
}

,并尝试通过:

来解析它
index = 0;
while (index < 80) {
  gps.encode(inData[index]);
  Serial.print(inData[index]);
  index++;
}

但是这并没有像期望的那样工作。检查位置isValid()是否总是返回不为真。

不幸的是,我有几个可能的原因导致这个不希望的行为。

  1. 句子过短(不太可能)
  2. 通过串行读取数据的方式不正确。
  3. 我只提交了一行。

我既没有NMEA经验,也没有串行数据通信经验,我对Arduino/C只有很少的经验。你能给我指点一下如何解决这些问题吗?

基本上,您不需要累积NMEA字符。当你收到它们时,把它们输入GPS库。您不提供整个循环,但是这里也很容易出现问题。

在与几个GPS库及其示例进行了斗争之后,我最终编写了NeoGPS。它比所有其他库更快、更小,它验证校验和,并且示例结构正确。与其他库不同,NeoGPS不将GPS值存储为浮点值,因此它能够保留GPS设备的全部精度。

如果您想尝试一下,请务必遵循安装说明。n mea。没有一个示例将为您发送的每批GPS句子发出一行信息(CSV格式),以默认的RMC句子结束。确保将其修改为使用Serial对象而不是gps_port,或者简单地这样定义它:

  #define gps_port Serial

它还将显示已解析的字符数,已接收的好句子的数量,以及有校验和错误的句子的数量。如果没有正确生成校验和,这有助于进行调试。这个网站也很有用。

这些CSV行将通过USB端口(到PC)发送回来,但您可以轻松地更改它以发送特定字段到OLED(见NMEAloc.ino)。

虽然可以在PC上开发一些东西,然后将其移植到像Arduino这样的嵌入式环境中,但您必须小心(1)线性程序结构和(2)忽略资源限制(程序大小,MCU速度和RAM)。Arduino环境中有许多怪癖,通常使将"草图"移植到PC上感到沮丧。,,: P