我正在尝试使用Arduino uno及以下代码解析传入的GPGGA NMEA GPS字符串。 我想要做的是,我只使用GPGGA NMEA字符串来获取纬度,经度和海拔高度的值。在我的下面的代码中,我已经进行了某些检查以检查传入的字符串是否为GPGGA,然后存储数组中的其他字符串,可以进一步解析surt strtok函数,所有3个GPS坐标都可以轻松找到。
但我无法弄清楚如何只存储GPGGA字符串而不是另外的字符串。我正在使用for循环,但它无效。
我没有尝试使用任何库。我遇到了某些existing codes like this.
Here is the GPGGA string information link
我想尝试以下功能 i)检查传入的字符串是否为GPGGA ii)如果是,则在数组中将以下字符串存储到EOL或upto *(后跟数组的校验和),数组长度是可变的(我无法找到解决方案) iii)然后解析存储的数组(这已完成,我尝试使用不同的数组)
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10,11); // 10 RX / 11 TX
void setup()
{
Serial.begin(9600);
mySerial.begin(9600);
}
void loop()
{
uint8_t x;
char gpsdata[65];
if((mySerial.available()))
{
char c = mySerial.read();
if(c == '$')
{char c1 = mySerial.read();
if(c1 == 'G')
{char c2 = mySerial.read();
if(c2 == 'P')
{char c3 = mySerial.read();
if(c3 == 'G')
{char c4 = mySerial.read();
if(c4 == 'G')
{char c5 = mySerial.read();
if(c5 == 'A')
{for(x=0;x<65;x++)
{
gpsdata[x]=mySerial.read();
while (gpsdata[x] == '\r' || gpsdata[x] == '\n')
{
break;
}
}
}
else{
Serial.println("Not a GPGGA string");
}
}
}
}
}
}
}
Serial.println(gpsdata);
}
编辑1: 考虑到Joachim Pileborg,在代码中编辑for循环。
我正在添加一张图片来显示未定义的代码输出。
代码输入:
$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76
$GPGSA,A,3,10,07,05,02,29,04,08,13,,,,,1.72,1.03,1.38*0A
$GPGSV,3,1,11,10,63,137,17,07,61,098,15,05,59,290,20,08,54,157,30*70
$GPGSV,3,2,11,02,39,223,19,13,28,070,17,26,23,252,,04,14,186,14*79
$GPGSV,3,3,11,29,09,301,24,16,09,020,,36,,,*76
$GPRMC,092750.000,A,5321.6802,N,00630.3372,W,0.02,31.66,280511,,,A*43
$GPGGA,092751.000,5321.6802,N,00630.3371,W,1,8,1.03,61.7,M,55.3,M,,*75
$GPGSA,A,3,10,07,05,02,29,04,08,13,,,,,1.72,1.03,1.38*0A
$GPGSV,3,1,11,10,63,137,17,07,61,098,15,05,59,290,20,08,54,157,30*70
$GPGSV,3,2,11,02,39,223,16,13,28,070,17,26,23,252,,04,14,186,15*77
$GPGSV,3,3,11,29,09,301,24,16,09,020,,36,,,*76
$GPRMC,092751.000,A,5321.6802,N,00630.3371,W,0.06,31.66,280511,,,A*45
答案 0 :(得分:3)
在快速检查了NMEA 0183协议上的链接文章之后,我跳了出来:
<CR><LF>
结束了此消息。
这意味着,您应该寻找该序列,而不是只是从串口中不加选择地读取。如果找到,你应该终止字符串,并打破循环。
此外,您可能希望将数据字符串初始化为零,以便轻松查看其中是否有任何数据要打印(使用例如strlen
)。
答案 1 :(得分:0)
提供此作为支持您正在做的事情的建议......
在循环中替换所有嵌套的if()
并不会有用:
编辑 添加全局字符串以将myString复制到捕获的内容
char globalString[100];//declare a global sufficiently large to hold you results
void loop()
{
int chars = mySerial.available();
int i;
char *myString;
if (chars>0)
{
myString = calloc(chars+1, sizeof(char));
for(i=0;i<chars;i++)
{
myString[i] = mySerial.read();
//test for EOF
if((myString[i] == '\n') ||(myString[i] == '\r'))
{
//pick this...
myString[i]=0;//strip carriage - return line feed(or skip)
//OR pick this... (one or the other. i.e.,I do not know the requirements for your string)
if(i<chars)
{
myString[i+1] = mySerial.read() //get remaining '\r' or '\n'
myString[i+2]=0;//add null term if necessary
}
break;
}
}
if(strstr(myString, "GPGGA") == NULL)
{
Serial.println("Not a GPGGA string");
//EDIT
strcpy(globalString, "");//if failed, do not want globalString populated
}
else
{ //EDIT
strcpy(globalString, myString);
}
}
//free(myString) //somewhere when you are done with it
}
现在,来自mySerial.available()
的 返回值 告诉您 完全 要读取的字节数,你可以阅读整个缓冲区,并测试所有的有效性。
答案 2 :(得分:0)
我有一个项目需要从同一个句子中提取相同的信息。 我从日志文件中得到了这个
import serial
import time
ser = serial.Serial(1)
ser.read(1)
read_val = ("nothing")
gpsfile="gpscord.dat"
l=0
megabuffer=''
def buffThis(s):
global megabuffer
megabuffer +=s
def buffLines():
global megabuffer
megalist=megabuffer.splitlines()
megabuffer=megalist.pop()
return megalist
def readcom():
ser.write("ati")
time.sleep(3)
read_val = ser.read(size=500)
lines=read_val.split('\n')
for l in lines:
if l.startswith("$GPGGA"):
if l[:len(l)-3].endswith("*"):
outfile=open('gps.dat','w')
outfile.write(l.rstrip())
outfile.close()
readcom()
while 1==1:
readcom()
answer=raw_input('not looping , CTRL+C to abort')
结果如下: gps.dat
$GPGGA,225714.656,5021.0474,N,00412.4420,W,0,00,50.0,0.0,M,18.0,M,0.0,0000*5B
答案 3 :(得分:0)
答案 4 :(得分:0)
答案 5 :(得分:0)
每次读取字符串时都使用“malloc”会产生大量的计算开销。 (并没有看到相应的free()函数调用。没有它,你永远不会得到那个内存,直到程序终止或系统内存不足。)只需选择你需要的最长字符串的大小,添加10到它,并声明你的字符串数组大小。设置一次并完成。
有几个C函数可以从字符串中获取子字符串,使用昏迷的strtok()可能是开销最小的。
您使用的是嵌入式微控制器。保持小,保持头顶下降。 :)
答案 6 :(得分:0)
您可以使用C库libnmea中的一些功能。 Theres用于通过逗号将句子拆分为值,然后解析它们。