2013-11-08 5 views
4

enter image description here Я пытаюсь разобрать входящую строку GPGGA NMEA GPS, используя Arduino uno и ниже кода. Что я пытаюсь сделать, так это то, что я использую только строку GPGGA NMEA для получения значений широты, долготы и высоты. В моем нижнем коде я установил определенные проверки, чтобы проверить, является ли входящая строка GPGGA или нет, а затем сохраните дальнейшая строка в массиве, которая может быть дополнительно проанализирована с использованием функции strtok, и все 3 GPS-координаты могут быть легко обнаружены.Анализ кода GPS NMEA string

Но я не могу понять, как хранить только строку GPGGA, а не следующую строку. Я использую цикл for, но он не работает.

Я не пытаюсь использовать любой library.I уже наткнулся на определенный existing codes like this.

Here is the GPGGA string information link

я пытаюсь иметь следующие functionlity я) Проверьте, если входящий строка GPGGA б) Если да, то затем сохраните следующую строку до 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: Рассмотрение Иоахима Пилеборга, редактирование цикла for в коде.

Я добавляю pic, чтобы показать undefined вывод кода.

Вход для кода:

$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

У вас есть ошибка «один за другим». Во внутреннем цикле 'for' вы повторяете от 0 до 65 и 66 записей для массива, содержащего 65 записей. Это приводит к неопределенному поведению. –

+0

Кроме того, в зависимости от данных и функции 'Serial.println', если функция' Serial.println' ожидает строку (т. Е. Данные заканчиваются нулем), а 'gpsdata' не заканчивается нулем, тогда вы снова имеют неопределенное поведение. Кроме того, если 'gpsdata' не является текстовым, а двоичным, то он может содержать внедренный нуль, который рассматривается как ограничитель строки. И поскольку 'gpsdata' является локальной переменной, это * не * заполняется нулями (все его значения неопределены, пока вы не инициализируете его), используя его в случае ошибок, также является неопределенным поведением. –

+0

Используйте возвращаемое значение из 'mySerial.available()', чтобы получить количество байтов в трубе для чтения, выделить память для массива строк, прочитать его и проверить на достоверность. См. Подробности в ответе ниже. – ryyker

ответ

3

После быстрой проверки связанной статьи по протоколу NMEA 0183, это выскочили на меня:

<CR><LF> заканчивает сообщение.

Это означает, что вместо того, чтобы просто читать без разбора из последовательного порта, вы должны искать эту последовательность. Если найдено, вы должны прервать строку и выйти из цикла.

Кроме того, вам может потребоваться нуль-инициализировать строку данных для начала, чтобы легко увидеть, есть ли на ней какие-либо данные для печати (с использованием, например, strlen).

+0

Хороший ответ. Вы думаете, 'if ((mySerial.available()' может проверять ненулевой ответ? (Относительно вашего предложения проверить с помощью 'strlen') – ryyker

+0

Тот же вопрос - ответил *** [здесь] (http: // arduino.cc/en/Reference/SoftwareSerialAvailable)*** – ryyker

+0

Я использовал и в своем коде, и это сработало для меня для первых 20-25 outpurts через порт COM16, но после того, как тот же undefined выход начал приходить. размер массива, который я определил для gpsdata [65]? – shailendra

0

Предлагая это как предложение в поддержку того, что вы делаете ...

Не было бы полезно, чтобы заменить все вложенные if() с в цикле что-то вроде:

EDIT добавил глобальную строку, чтобы скопировать 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() сообщает вам точно сколько байтов читать, вы можете прочитать весь буфер и проверить достоверность всего на одном.

+0

это не сработало для меня, так как он снова не определен, когда я попробовал it.I willl используйте функциональность malloc определенно в моем коде. – shailendra

+0

Я только что обновил этот пост, вы получили строки, которые проверяют на «\ n \ r» ?, и знаете ли вы, должны ли вы их хранить, или вы должны убрать их выключить и ap запустите символ '\ 0', чтобы завершить работу. Строка C всегда требует окончания '\ 0', чтобы она использовалась в любой строковой функции C. – ryyker

+0

Еще одна вещь, которую нужно добавить, в вашем коде вы печатаете только, если myString не имеет GPGGA, моя цель - сохранить строку, которая идет только после GPGGA. – shailendra

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 
0

Просто добавьте этот код будет работать. используйте контакт 8 и 9, как ПРД и ПРМ

Main.cgps.hgps.c

0

Просто добавьте этот код будет работать. используйте контакт 8 и 9, как ПРД и ПРМ

  1. gps.h
  2. main.c
  3. gps.c
0

Использование "таНос" каждый раз, когда вы читали строку огромное количество вычислительных накладных расходов. (И не видел соответствующего вызова функции free(). Без этого вы никогда не получите эту память до завершения программы или в системе не хватает памяти.) Просто выберите размер самой длинной строки, которая вам когда-либо понадобится, добавьте 10 к его и объявить, что ваш размер массива строк. Установите один раз и все.

Существует несколько функций C для получения подстрок из строки, strtok() с использованием комы, вероятно, является наименее затратным.

Вы находитесь на встроенном микроконтроллере. Держите его маленьким, держите сверху вниз. :)

0

Вы можете использовать некоторые функции из библиотеки C libnmea. Функция Theres разделяет предложение на значения по запятой, а затем анализирует их.