我想在Arduino上使用TinyGPS++来解析NMEA数据并在OLED显示器上显示信息。但是,NMEA数据将通过USB接收,而不是使用软件串行和TX / RX引脚。
我遵循了TinyGPS ++的示例,但是遇到了两个问题:
1)
当我通过串行监视器(Windows,Arduino 1.6.9)发送一个NMEA语句时,Arduino仅接收前64个字符。如何克服这个限制?我通过删除几个小数位来帮助自己,但这不是首选的方式。
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()
是否始终返回不为真。不幸的是,对于这种不良行为,我有几种可能的来源。
太短的句子(不太可能)
通过串行读取数据的方式不正确。
我只提交一行。
还有别的
我既没有NMEA经验,也没有串行数据通信经验,并且我对Arduino / C的经验很少。您能指出我如何解决这些问题的方向吗?
最佳答案
基本上,您不需要累积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或从PC移植变得令人沮丧。 :P