解析序列

时间:2016-10-23 13:14:12

标签: c++ serialization arduino gps

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

我按照TinyGPS ++的例子,但我遇到了两个问题:

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

2) 在TinyGPS ++ BasicExample中,示例NMEA字符串在只读存储器中定义:

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

并由

解析
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] = '\0';
    }
  }
}

并尝试通过以下方式解析它:

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

但是这不能按预期工作。检查位置isValid()是否始终返回不为真。

不幸的是,我有几种可能的不良行为来源。

  1. 句子太短(不太可能)
  2. 通过串行读取数据的方式不正确。
  3. 我只提交一行。
  4. 别的。
  5. 我对NMEA和串行数据通信都没有经验,而且我对Arduino / C只有很少的经验。你能指点我如何解决这些(这些)问题吗?

1 个答案:

答案 0 :(得分:0)

基本上,您不需要累积NMEA字符。只需在收到它们时将它们送到GPS库。你不提供整个循环,但在那里遇到问题也很常见。

在与几个GPS库及其示例挣扎之后,我最终写了NeoGPS。它比所有其他库更快,更小,它验证校验和,并且示例结构正确。与其他库不同,NeoGPS不会将GPS值存储为浮点值,因此它可以保持GPS设备的完整精度。

如果您想尝试一下,请务必遵循安装说明。 NMEA.ino示例将为您发送的每批GPS句子发出一行信息(CSV格式),以默认的RMC句子结束。请务必对其进行修改以使用Serial对象而不是gps_port,或者只需将其定义为:

  #define gps_port Serial

它还将显示已解析的字符数,已收到的好句数以及校验和错误的句数。如果您没有正确生成校验和,这可能有助于调试。 This site也很有用。

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

虽然可能在PC上开发某些内容然后将其移植到像Arduino这样的嵌入式环境中,但您必须注意(1)线性程序结构和(2)忽略资源限制(程序大小,MCU速度和RAM)。 Arduino环境存在许多怪癖,通常会使“草图”移入/移出PC时会感到沮丧。 :P