И снова GPS - парсер

Тема в разделе "Arduino & Shields", создана пользователем ELITE, 3 апр 2018.

Метки:
  1. ELITE

    ELITE Гик

    В общем не хочу использовать библиотеку, пишу свой парсер
    на текущий момент имеется:
    Код (C++):
     
    int cnt = 0;
    int heshtemp,heshfix = 0;
    char nmea[82];

    void loop() {
    if(gps.available())   //проверяю буфер порта ЖПС
      {
        char ch=gps.read();   // Serial.print(ch);
       
         if(ch == '$') { cnt = 0; heshtemp = 0; memset(nmea,0,sizeof(nmea)); } /*начало строки/**/
         else { nmea[cnt++] = ch; /* сбор буфера символов /**/ if(ch == '*')heshfix=heshtemp ; heshtemp ^= ch; }
         if(ch == '\n'){//конец строки - разбор данных  
           if(strncmp(nmea,"GPRMC",5)==0){ /*ищем нужный блок по заголовку/**/  Serial.println(nmea); Serial.print("hesh:"); Serial.println(heshfix,HEX);
             if(nmea[sizeof(nmea)-3]==heshfix){ /*проверка хеша строки/**/Serial.println("hesh VIN!!!!");
              /******************** разбор данных на блоки ******************/
              /*     GPRMC,080725.447,A,5432.3355,N,03618.1771,E,000.0,201.2,030418,,,A*62        */

             
              /**************************************************************/
             }
           }              
         }
       
      }

    }
    по сути все данные в массиве чар
    теперь надо его разобрать на части, но чтото не хочется использовать "строковые" функции типа подстроки...

    отсюда 2 вопроса:
    1) что можно оптимизировать в данном коде для его облегчения в плане скорости выполнения и потребляемой памяти?

    2) как более правильно брать из массива символов их часть?
     
  2. Asper Daffy

    Asper Daffy Иксперд

    Это что за хрень? Ты сравниваешь символ с целым числом? И чего надеешься насравнивать?
     
  3. ELITE

    ELITE Гик

    а ну да, ошибочка
    надо эти 2 символа в число переобразовать еще atoi
     
  4. ELITE

    ELITE Гик

    да чтото совсем запутал всё
    sizeof(nmea) дает размер массива = 82 а не фактическому числу заполненных ячеек его
     
  5. Asper Daffy

    Asper Daffy Иксперд

    Да, неужели? А что, должен по-другому?
     
  6. ELITE

    ELITE Гик

    Код (C++):
     char tmp[5];itoa(heshfix,tmp,16);      Serial.println(tmp);
           
             if(atoi(nmea+67)==atoi(tmp)){
    понимаю, что чтото перемудрил, но так работает
    ---
    на остальные вопросы поможете?
     
  7. ELITE

    ELITE Гик

    вот что вышло:
    Код (C++):
     
      if(gps.available())   //проверяю буфер порта ЖПС
      {
        char ch=gps.read();   // Serial.print(ch);
       
         if(ch == '$') { cnt = 0; heshtemp = 0; memset(nmea,0,sizeof(nmea)); } /*начало строки/**/
         else { nmea[cnt++] = ch; /* сбор буфера символов /**/ if(ch == '*')heshfix=heshtemp; heshtemp ^= ch; }
         if(ch == '\n'){//конец строки - разбор данных  
           if(strncmp(nmea,"GPRMC",5)==0){ /*ищем нужный блок по заголовку/**/  Serial.print(nmea); //Serial.print("hesh:"); Serial.println(heshfix,HEX);
         
             char tmp[5];itoa(heshfix,tmp,16); //     Serial.println(tmp);
           
             if(atoi(nmea+67)==atoi(tmp)){ /*проверка хеша строки/**///Serial.println("hesh VIN!!!!");
              /******************** разбор данных на блоки ******************/
              /*     0     6         17 19       29 31        42 44    50    56    62                      
              /*     GPRMC,080725.447,A,5432.3355,N,03618.1771,E,000.0,201.2,030418,,,A*62        */

              memset(data,0,sizeof(data)); for(int i=0; i<=4; i++) {data[i]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=6; i<=15; i++) {data[i-6]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=17; i<=17; i++) {data[i-17]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=19; i<=27; i++) {data[i-19]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=29; i<=29; i++) {data[i-29]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=31; i<=40; i++) {data[i-31]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=42; i<=42; i++) {data[i-42]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=44; i<=48; i++) {data[i-44]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=50; i<=54; i++) {data[i-50]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=56; i<=61; i++) {data[i-56]=nmea[i];} Serial.print("parse:"); Serial.println(data);
           
              /**************************************************************/
             }
           }            
         }
     
      }
     
    результат
    в общем результат меня устраивает, но код явно перегружен и совсем нубский

    Подскажите как можно его оптимизировать? а то почти 20мс занимает исполнение кода
     
    Последнее редактирование: 3 апр 2018
  8. Asper Daffy

    Asper Daffy Иксперд

    if(atoi(nmea+67)==atoi(tmp)){

    Там не обязано всегда быть 67, там может быть и другое смещение, так что так делать стопудово нельзя.

    Вообще, проблема-то выеденного яйца не стоит - разодрать строку по разделителю-запятой.

    Вот здесь это делается в три строки, только не по запятой и по пробелу. Разберись с поменяй на запятую.
     
    ELITE нравится это.
  9. ELITE

    ELITE Гик

    спс это то понятно

    я просто делаю под определенный ЖПС модуль - в нем отдается фиксированная длинна строки, поэтому указал так

    но для не выполнения разбора строки . если она не верная, надо вначале проверить хош строки - 2 последних символа
    но какбрать 2 последних не пустых (не 0) символа из массива чар я не нашел пока простого решения
     
  10. Asper Daffy

    Asper Daffy Иксперд

    Не бывает таких модулей. См. протокол. Там может не быть какой-то цифири или ещё чего. Длина строки в протоколе NMEA не фиксирована.
     
  11. ELITE

    ELITE Гик

    да, по стандарту не фиктирована
    но это не значит, что какой - либо производитель не сделает фиксированным какую-либо строку

    в конкретном моем случае на имеющемся у меня примнике, именно нужный мне набор данных имеет фиксированную длину
    -----
    можно сделать так strlen(nmea)-4
    но это +150кб кода....всего из за одного действия
     
  12. Asper Daffy

    Asper Daffy Иксперд

    Не знаю. что ты куришь, но ты бы не привыкал к этой гадости
     
  13. Asper Daffy

    Asper Daffy Иксперд

    Как ты собираешься это делать не прочитав всю строку? Ты знаешь чему равны эти последние два символа? Или "в твоём мире строк фиксированной длины" они всегда одинаковые? Эти два символа - шестнадцатиричное число равное XOR-сумме всех символов строки. Т.е. тебе по любому надо прочитать сначала всю строку, просуммировать её, а потом уж сравнивать полученную сумму с этими символами.
     
  14. ELITE

    ELITE Гик

    я же код приложил - там читаются все приходящие символы и сразу ссумируются
    просто при приходе символа '$' идет обнуление (это начало строки), а при нахождении '*' хор сумма запоминается в отдельную переменную
     
  15. ELITE

    ELITE Гик

    Код (C++):
    #define gps Serial1


    int cnt = 0;

    //int spd,crs;
    //double lat,lng,latp,lngp;

    //int year, month, day, hour, minute, second;
    //String date,time;

    //bool gps_valid;

    //long dist,dist_o = 0;   //путь

    int heshtemp,heshfix = 0;

    /*************************************/
    char nmea[83];    //буфер строки nmea сообщения
    char data[12];    //буфер подстрок

    /*************************************/
    void setup() {
       Serial.begin(115200);
       gps.begin(9600);
       Serial.println("-- start --");
    }

    void loop() {
    //    Serial.print("start:");Serial.println(millis());
      if(gps.available())   //проверяю буфер порта ЖПС
      {
        char ch=gps.read();   // Serial.print(ch);
       
         if(ch == '$') { cnt = 0; heshtemp = 0; memset(nmea,"\0",sizeof(nmea)); } /*начало строки/**/
         else { nmea[cnt++] = ch; /* сбор буфера символов /**/ if(ch == '*')heshfix=heshtemp; heshtemp ^= ch; }
         if(ch == '\n'){//конец строки - разбор данных  
           if(strncmp(nmea,"GPRMC",5)==0){ /*ищем нужный блок по заголовку/**/  Serial.print(nmea); //Serial.print("hesh:"); Serial.println(heshfix,HEX);
       
             char tmp[5];itoa(heshfix,tmp,16);    //  Serial.println(tmp);
       
             if(atoi(nmea+(strlen(nmea)-4))==atoi(tmp)){ /*проверка хеша строки/**///Serial.println("hesh VIN!!!!");
              /******************** разбор данных на блоки ******************/
              /*     0     6         17 19       29 31        42 44    50    56    62                      
              /*     GPRMC,080725.447,A,5432.3355,N,03618.1771,E,000.0,201.2,030418,,,A*62        */

              memset(data,0,sizeof(data)); for(int i=0; i<=4; i++)   {data[i]=nmea[i];}    Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=6; i<=11; i++)  {data[i-6]=nmea[i];}  Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=17; i<=17; i++) {data[i-17]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=19; i<=27; i++) {data[i-19]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=29; i<=29; i++) {data[i-29]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=31; i<=40; i++) {data[i-31]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=42; i<=42; i++) {data[i-42]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=44; i<=48; i++) {data[i-44]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=50; i<=54; i++) {data[i-50]=nmea[i];} Serial.print("parse:"); Serial.println(data);
              memset(data,0,sizeof(data)); for(int i=56; i<=61; i++) {data[i-56]=nmea[i];} Serial.print("parse:"); Serial.println(data);
           
              /**************************************************************/
             }
           }            
         }
     
      }
    //Serial.print("stop:");Serial.println(millis());


     
    }

    /***************************************************************************************************/
    /*double distance_between (double lat1, double long1, double lat2, double long2)
    {
      // returns distance in meters between two positions, both specified
      // as signed decimal-degrees latitude and longitude. Uses great-circle
      // distance computation for hypothetical sphere of radius 6372795 meters.
      // Because Earth is no exact sphere, rounding errors may be up to 0.5%.
      // Courtesy of Maarten Lamers
      double delta = radians(long1-long2);
      double sdlong = sin(delta);
      double cdlong = cos(delta);
      lat1 = radians(lat1);
      lat2 = radians(lat2);
      double slat1 = sin(lat1);
      double clat1 = cos(lat1);
      double slat2 = sin(lat2);
      double clat2 = cos(lat2);
      delta = (clat1 * slat2) - (slat1 * clat2 * cdlong);
      delta = sq(delta);
      delta += sq(clat2 * sdlong);
      delta = sqrt(delta);
      double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong);
      delta = atan2(delta, denom);
      return delta * 6372795; //6367445; //6372795;
    }
    /*
    void gps_info(){
    // if (dist==0){
       Serial.print(".");
    //  }else{
        Serial.println("");
      Serial.print("GPS Valid SIGNAL!"); Serial.print(" ");
      Serial.print("Tim: "); Serial.print(time);  Serial.print(" ");      
      Serial.print("Lat: "); Serial.print(lat,6); Serial.print(" ");
      Serial.print("Lon: "); Serial.print(lng,6); Serial.print(" ");
      Serial.print("spd: "); Serial.print(spd,4); Serial.print(" ");
      Serial.print("crs: "); Serial.print(crs); Serial.print(" ");
      Serial.print("dist: "); Serial.print(dist); Serial.print(" ");
      Serial.print("Dat: "); Serial.print(date);  Serial.print(" ");
      Serial.println("------------");  
    //  }
    }*/
    результат