GPS NEO-6M. Вытащить данные из мудрёного кода.

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

Метки:
  1. ardurino

    ardurino Нерд

    Всем привет. Мучаюсь с GPS. Нашёл для GPS NEO-6M хороший код, рабочий. Да разработчик взял написал код так, что хитро выводит данные в виде строки, которую не так просто понять. И вытащить сами значения координат не так уж и просто. Вот его видео:


    у меня микросхемка такая же. Подскажите, пожалуйста, как вытащить отдельно координаты и скорость?
    Спасибо.
    Код:
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial GPSModule(10, 11); // RX, TX
    int updates;
    int failedUpdates;
    int pos;
    int stringplace = 0;

    String timeUp;
    String nmea[15];
    String labels[12] {"Time: ", "Status: ", "Latitude: ", "Hemisphere: ", "Longitude: ", "Hemisphere: ", "Speed: ", "Track Angle: ", "Date: "};
    void setup() {
      Serial.begin(57600);
      GPSModule.begin(9600);
    }

    void loop() {
      Serial.flush();
      GPSModule.flush();
      while (GPSModule.available() > 0)
      {
        GPSModule.read();

      }
      if (GPSModule.find("$GPRMC,")) {
        String tempMsg = GPSModule.readStringUntil('\n');
        for (int i = 0; i < tempMsg.length(); i++) {
          if (tempMsg.substring(i, i + 1) == ",") {
            nmea[pos] = tempMsg.substring(stringplace, i);
            stringplace = i + 1;
            pos++;
          }
          if (i == tempMsg.length() - 1) {
            nmea[pos] = tempMsg.substring(stringplace, i);
          }
        }
        updates++;
        nmea[2] = ConvertLat();
        nmea[4] = ConvertLng();
        for (int i = 0; i < 9; i++) {
          Serial.print(labels[i]);
          Serial.print(nmea[i]);
          Serial.println("");
        }

      }
      else {

        failedUpdates++;

      }
      stringplace = 0;
      pos = 0;
    }

    String ConvertLat() {
      String posneg = "";
      if (nmea[3] == "S") {
        posneg = "-";
      }
      String latfirst;
      float latsecond;
      for (int i = 0; i < nmea[2].length(); i++) {
        if (nmea[2].substring(i, i + 1) == ".") {
          latfirst = nmea[2].substring(0, i - 2);
          latsecond = nmea[2].substring(i - 2).toFloat();
        }
      }
      latsecond = latsecond / 60;
      String CalcLat = "";

      char charVal[9];
      dtostrf(latsecond, 4, 6, charVal);
      for (int i = 0; i < sizeof(charVal); i++)
      {
        CalcLat += charVal[i];
      }
      latfirst += CalcLat.substring(1);
      latfirst = posneg += latfirst;
      return latfirst;
    }

    String ConvertLng() {
      String posneg = "";
      if (nmea[5] == "W") {
        posneg = "-";
      }

      String lngfirst;
      float lngsecond;
      for (int i = 0; i < nmea[4].length(); i++) {
        if (nmea[4].substring(i, i + 1) == ".") {
          lngfirst = nmea[4].substring(0, i - 2);
          //Serial.println(lngfirst);
          lngsecond = nmea[4].substring(i - 2).toFloat();
          //Serial.println(lngsecond);

        }
      }
      lngsecond = lngsecond / 60;
      String CalcLng = "";
      char charVal[9];
      dtostrf(lngsecond, 4, 6, charVal);
      for (int i = 0; i < sizeof(charVal); i++)
      {
        CalcLng += charVal[i];
      }
      lngfirst += CalcLng.substring(1);
      lngfirst = posneg += lngfirst;
      return lngfirst;
    }


     
     
  2. ardurino

    ardurino Нерд

    Кажется стал догадываться nmea[2] - долгота, nmea[4] - широта.
    Код (C++):
     Serial.println("LAT");
    Serial.println(nmea[2]);
       Serial.println("LONG");
       Serial.println(nmea[4]);
    Но тут другая проблема возникает ещё. Выводятся данные таким образом:
    Date: 160118
    LAT
    55.697360
    LONG
    037.569847
    Time: 153036.000
    Status: A
    Latitude: 55.697360
    Hemisphere: N
    Longitude: 037.569847
    Hemisphere: E
    Speed: 0.00
    Track Angle: 0.00
    Date: 160118

    Почему-то широта 037.569847, вместо 37.569847. Долгота правильно выводится 55.697360.
    Где же этот лишний ноль в коде?
     
  3. b707

    b707 Гуру

    чудеса дедукции :))))
    Что там "догадываться", если порядок выдаваемых данных прямо перечислен в массиве labels[] ?

    Что касается лишнего нуля - вы бы непреобразованные данные с GPS вывели в монитор и посмотрели - скорее всего этот ноль с модема идет, так как в широте максимум два знака, а в долготе - три.
    Хотя откуда он - не так уж важно, удалите его да и все.
     
    arkadyf нравится это.
  4. b707

    b707 Гуру

    Путаете широту и долготу. Слова "Latitude", и "Longitude" вам незнакомы?
     
  5. brokly

    brokly Гик

    Удаление незначащего ноля:

    if (nmea[4].charAt(0)=='0') nmea[4].remove(0);
     
  6. ardurino

    ardurino Нерд

    Ок, попробую.
     
  7. ardurino

    ardurino Нерд

    Ок, Шерлок.
     
  8. ardurino

    ardurino Нерд

    Теперь другая штука.
    У меня данные отсылаются через GPRS в POST-запросе на сервер.
    По идее для начала нужно чтобы GPS определил координаты, и только после этого их отсылать.
    Но когда пробую вставить кусок кода с GPRS - всё перестаёт работать. В какую часть кода только ни запихивал этот кусок кода для GPRS.
    Код (C++):
     InetGSM inet;
      Serial.println("GSM Shield testing.");

      //Start configuration of shield with baudrate.
      //For http uses is raccomanded to use 4800 or slower.
      if (gsm.begin(2400)){
        Serial.println("\nstatus=READY");
        started=true;
      }
      else
      {Serial.println("RESTart GSM+DisInfo");
        digitalWrite(9, HIGH);
          pinMode(9, OUTPUT);

      digitalWrite(9,LOW);

      delay(1000);

      digitalWrite(9,HIGH);

      delay(2000);

      digitalWrite(9,LOW);

      delay(3000);

        displayInfo();
        }
      delay(3000);
      Serial.println("\nstatus=IDLE");
      if(started){
        //GPRS attach, put in order APN, username and password.
        //If no needed auth let them blank.
        if (inet.attachGPRS("internet.mts.ru", "mts", "mts"))
          Serial.println("status=ATTACHED");
        else
          Serial.println("status=ERROR");
        delay(1000);
        //Read IP address.
        gsm.SimpleWriteln("AT+CIFSR");
        delay(5000);
        //Read until serial buffer is emapty.
       gsm.WhileSimpleRead();


    String str = "{\"n\":\"1\", \"t\": \"";
      str += t;
      str += "\", \"d\":\"";
      str += ltd;
      str += "\",\"g\":\"";
      str += lnd;
      str += "\", \"i\":\"2";
      //str += 28;
      str += "\"}";
     
       Serial.println(str);

      //int len = str.length()+1;
      //unsigned char* buf = new unsigned char[len];`

    // str.getBytes(buf, len);
    // Serial.println((const char*)buf);
    numdata=inet.httpPOST("site.com", 80, "/temperature ", str.c_str(), msg, 50);
    //delete buf;

        //TCP Client GET, send a GET request to the server and
        //save the reply.
    //numdata=inet.httpPOST("site.com", 80, "/temperature ", "{\"n\":\"2\", \"t\": \"22\", \"d\":\"44.752095\",\"g\":\"34.554844\", \"i\":\"8\"}",msg,50);
        //Print the results.
        Serial.println("\nNumber :");
        Serial.println(numdata);
        Serial.println("\nData :");
        Serial.println(msg);
     
        Serial.begin(9600);
     
      }
     
  9. ardurino

    ardurino Нерд

    Яволь!
     
  10. ardurino

    ardurino Нерд

    Попробовал, пропала строчка совсем.
    Код (C++):
    LAT
    55.697357
    LONG

    Time: 102752.000
    Status: A
    Latitude: 55.697357
    Hemisphere: N
    Longitude:
    Hemisphere: E
    Speed: 0.00
    Track Angle: 0.00
    Date: 170118
     
     
  11. brokly

    brokly Гик

    Конечно, пока вы три секунды в задержке "бамбучину курите", у вас буфер чтения GPS переполняется. Избавляйтесь от delay.
     
  12. ardurino

    ardurino Нерд

    А в какую строку изначального кода лучше включить функцию запускающую GPRS и отсылку?
    Над после определения не нулевых координат.
    Изначальный код:
    Код (C++):
    #include <SoftwareSerial.h>
    SoftwareSerial GPSModule(10, 11); // RX, TX
    int updates;
    int failedUpdates;
    int pos;
    int stringplace = 0;

    String timeUp;
    String nmea[15];
    String labels[12] {"Time: ", "Status: ", "Latitude: ", "Hemisphere: ", "Longitude: ", "Hemisphere: ", "Speed: ", "Track Angle: ", "Date: "};
    void setup() {
      Serial.begin(57600);
      GPSModule.begin(9600);
    }

    void loop() {
      Serial.flush();
      GPSModule.flush();
      while (GPSModule.available() > 0)
      {
        GPSModule.read();

      }
      if (GPSModule.find("$GPRMC,")) {
        String tempMsg = GPSModule.readStringUntil('\n');
        for (int i = 0; i < tempMsg.length(); i++) {
          if (tempMsg.substring(i, i + 1) == ",") {
            nmea[pos] = tempMsg.substring(stringplace, i);
            stringplace = i + 1;
            pos++;
          }
          if (i == tempMsg.length() - 1) {
            nmea[pos] = tempMsg.substring(stringplace, i);
          }
        }
        updates++;
        nmea[2] = ConvertLat();
        nmea[4] = ConvertLng();
        for (int i = 0; i < 9; i++) {
          Serial.print(labels[i]);
          Serial.print(nmea[i]);
          Serial.println("");
        }

      }
      else {

        failedUpdates++;

      }
      stringplace = 0;
      pos = 0;
    }

    String ConvertLat() {
      String posneg = "";
      if (nmea[3] == "S") {
        posneg = "-";
      }
      String latfirst;
      float latsecond;
      for (int i = 0; i < nmea[2].length(); i++) {
        if (nmea[2].substring(i, i + 1) == ".") {
          latfirst = nmea[2].substring(0, i - 2);
          latsecond = nmea[2].substring(i - 2).toFloat();
        }
      }
      latsecond = latsecond / 60;
      String CalcLat = "";

      char charVal[9];
      dtostrf(latsecond, 4, 6, charVal);
      for (int i = 0; i < sizeof(charVal); i++)
      {
        CalcLat += charVal[i];
      }
      latfirst += CalcLat.substring(1);
      latfirst = posneg += latfirst;
      return latfirst;
    }

    String ConvertLng() {
      String posneg = "";
      if (nmea[5] == "W") {
        posneg = "-";
      }

      String lngfirst;
      float lngsecond;
      for (int i = 0; i < nmea[4].length(); i++) {
        if (nmea[4].substring(i, i + 1) == ".") {
          lngfirst = nmea[4].substring(0, i - 2);
          //Serial.println(lngfirst);
          lngsecond = nmea[4].substring(i - 2).toFloat();
          //Serial.println(lngsecond);

        }
      }
      lngsecond = lngsecond / 60;
      String CalcLng = "";
      char charVal[9];
      dtostrf(lngsecond, 4, 6, charVal);
      for (int i = 0; i < sizeof(charVal); i++)
      {
        CalcLng += charVal[i];
      }
      lngfirst += CalcLng.substring(1);
      lngfirst = posneg += lngfirst;
      return lngfirst;
    }
     
  13. brokly

    brokly Гик

    Ну да, правильно, это я ошибся, нужно так

    if (mnea[4].charAt(0)=='0') mnea[4]=mnea[4].substring(1);
     
    arkadyf нравится это.
  14. ardurino

    ardurino Нерд

    Да, теперь работает, давайте зачётку. %)
     
  15. brokly

    brokly Гик

    И почему мне расхотелось помогать...
     
  16. ardurino

    ardurino Нерд

    Не знаю... Для меня это одна из лучших фраз в жизни... Ну не все же были отличниками.
     
  17. b707

    b707 Гуру

    тут не Шерлок, тут Штирлиц уже. Что за "шифрограмма в центр" вставляется в строку str? Вы этот формат сами выдумали?
    По крайней мере одну ошибку вижу сразу - в строке httpPOST запроса после слова temperature у вас пробел, а его там точно не должно быть. Ну и про задержки вам brokly написал. Код надо кардинально переписывать, просто так "склеить" скетч для GPRS и скетч GPS - не выйдет
     
    arkadyf нравится это.
  18. ardurino

    ardurino Нерд

    Раньше получилось склеить, конечно, помучился. Просто тот GSP-Shield сняли с производства и он не популярный, не найти, это REB-4216 & REB-5216. А этот POST-запрос и подключение GPRS в принципе работает удовлетворительно. А str - не моё творчество, тоже у кого-то взял, чтобы сформировать строку POST-запроса.

    Мне кажется, достаточно вставить инициализацию POST-запроса в момент, когда координаты определились. И передать эти координаты.

    Код для REB-4216 с GPRS sim 900 такой, хочу как раз его с NEO-6M сочетать. В коде и измерение температуры, и координат и отсылка и перезагрузка регулярная на всякий случай от зависания.

    Код (C++):
    #include "SIM900.h"
    #include <TinyGPS++.h>
    #include <SoftwareSerial.h>
    #include "inetGSM.h"
    InetGSM inet;
    //#include <math.h>
    #include <avr/wdt.h>
    #include <OneWire.h>
    //#include <DallasTemperature.h>

    #define POWER_MODE  0 // режим питания, 0 - внешнее, 1 - паразитное
    OneWire sensDs (4);  // датчик подключен к выводу 14
    /*
       This sample sketch demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
       It requires the use of SoftwareSerial, and assumes that you have a
       4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
    */

    byte bufData[9];
    float temperature;
    static const int RXPin = 2, TXPin = 3;
    static const uint32_t GPSBaud = 9600;
    double gpslat;
    String double2string(double n, int ndec){
        String r = "";
        int v = n;
        r += v;     // whole number part
        r += '.';   // decimal point
        int i;
        for (i=0;i<ndec;i++) {
            // iterate through each decimal digit for 0..ndec
            n -= v;
            n *= 10;
            v = n;
            r += v;
        }
        return r;
    };
    double temp, tempC;
    String ltd, lnd,t;
    char msg[50];
    int numdata;
    //char inSerial[50];
    int i=0;
    boolean started=false;
    volatile long cntr;

    // The TinyGPS++ object
    TinyGPSPlus gps;

    // The serial connection to the GPS device
    SoftwareSerial ss(RXPin, TXPin);


    void setup()
    {
     
    Serial.begin(9600);
      ss.begin(GPSBaud);

      Serial.println(F("GPS Strated..."));
      Serial.println();
      TCCR2A = 0;
      TCCR2B = 2;
      TCNT2=59;
      TIMSK2 |= (1 << TOIE2);

    }

    void reboot()
    {
      wdt_disable();
      wdt_enable(WDTO_15MS);
      while (1) {}
    }


    /* double Getterm(int RawADC) {
      temp = log(((10240000/RawADC) - 10000));
      temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
      temp = temp - 273.15;
      return temp;
    }

    */


    void displayInfo()
    {
       sensDs.reset();  // сброс шины
      sensDs.write(0xCC, POWER_MODE); // пропуск ROM
      sensDs.write(0x44, POWER_MODE); // инициализация измерения
      //delay(900);  // пауза 0,9 сек
      sensDs.reset();  // сброс шины
      sensDs.write(0xCC, POWER_MODE); // пропуск ROM
      sensDs.write(0xBE, POWER_MODE); // команда чтения памяти датчика
      sensDs.read_bytes(bufData, 9);  // чтение памяти датчика, 9 байтов

      if ( OneWire::crc8(bufData, 8) == bufData[8] ) {  // проверка CRC
        // данные правильные
        temperature=  (float)((int)bufData[0] | (((int)bufData[1]) << 8)) * 0.0625 + 0.03125;
     
        // вывод измеренной температуры на индикаторы
                   
           
        // передача температуры на компьютер
        Serial.println(temperature);  
      }
       
     
      Serial.print(F("Location: "));
      if (gps.location.isValid())
      {
      //  sensors.requestTemperatures();
        ltd = (double2string (gps.location.lat(), 6));
        lnd = (double2string (gps.location.lng(), 6));
      //tempC = (sensors.getTempCByIndex(0));
    //  Serial.print(tempC);
       
        t = (double2string (temperature, 1));
     
         Serial.println(ltd);
         Serial.println(lnd);
       
    //  ltd = (double2string (44.391922, 5));
    // lnd = (double2string (33.794126, 5));
      //Read for new byte on serial hardware,
      //and write them on NewSoftSerial.
    // serialhwread();
      //Read for new byte on NewSoftSerial.
    // serialswread();
    InetGSM inet;
      Serial.println("GSM Shield testing.");

      //Start configuration of shield with baudrate.
      //For http uses is raccomanded to use 4800 or slower.
      if (gsm.begin(2400)){
        Serial.println("\nstatus=READY");
        started=true;
      }
      else
      {Serial.println("RESTart GSM+DisInfo");
        digitalWrite(9, HIGH);
          pinMode(9, OUTPUT);

      digitalWrite(9,LOW);

      delay(1000);

      digitalWrite(9,HIGH);

      delay(2000);

      digitalWrite(9,LOW);

      delay(3000);

        displayInfo();
        }
      delay(3000);
      Serial.println("\nstatus=IDLE");
      if(started){
        //GPRS attach, put in order APN, username and password.
        //If no needed auth let them blank.
        if (inet.attachGPRS("internet.mts.ru", "mts", "mts"))
          Serial.println("status=ATTACHED");
        else
          Serial.println("status=ERROR");
        delay(1000);
        //Read IP address.
        gsm.SimpleWriteln("AT+CIFSR");
        delay(5000);
        //Read until serial buffer is emapty.
       gsm.WhileSimpleRead();


    String str = "{\"n\":\"1\", \"t\": \"";
      str += t;
      str += "\", \"d\":\"";
      str += ltd;
      str += "\",\"g\":\"";
      str += lnd;
      str += "\", \"i\":\"2";
      //str += 28;
      str += "\"}";
     
       Serial.println(str);

      //int len = str.length()+1;
      //unsigned char* buf = new unsigned char[len];`

    // str.getBytes(buf, len);
    // Serial.println((const char*)buf);
    numdata=inet.httpPOST("site.com", 80, "/temperature ", str.c_str(), msg, 50);
    //delete buf;

        //TCP Client GET, send a GET request to the server and
        //save the reply.
    //numdata=inet.httpPOST("site.com", 80, "/temperature ", "{\"n\":\"2\", \"t\": \"22\", \"d\":\"44.752095\",\"g\":\"34.554844\", \"i\":\"8\"}",msg,50);
        //Print the results.
        Serial.println("\nNumber :");
        Serial.println(numdata);
        Serial.println("\nData :");
        Serial.println(msg);
     
        Serial.begin(9600);
      ss.begin(GPSBaud);

      }
       
       
      }
      else
      {
        Serial.print(F("INVALID"));
      }

      Serial.print(F("  Date/Time: "));
      if (gps.date.isValid())
      {
        Serial.print(gps.date.month());
        Serial.print(F("/"));
        Serial.print(gps.date.day());
        Serial.print(F("/"));
        Serial.print(gps.date.year());
      }
      else
      {
        Serial.print(F("INVALID"));
      }

      Serial.print(F(" "));
      if (gps.time.isValid())
      {
        if (gps.time.hour() < 10) Serial.print(F("0"));
        Serial.print(gps.time.hour());
        Serial.print(F(":"));
        if (gps.time.minute() < 10) Serial.print(F("0"));
        Serial.print(gps.time.minute());
        Serial.print(F(":"));
        if (gps.time.second() < 10) Serial.print(F("0"));
        Serial.print(gps.time.second());
        Serial.print(F("."));
        if (gps.time.centisecond() < 10) Serial.print(F("0"));
        Serial.print(gps.time.centisecond());
          Serial.flush();
      }
      else
      {
        Serial.print(F("INVALID"));
      }


    }
    void loop()
    {
      // This sketch displays information every time a new sentence is correctly encoded.
      while (ss.available() > 0)
      {
        if (gps.encode(ss.read()))
        {
    //    double temp = Getterm(analogRead(4));
          displayInfo();
        }
      }
      if (millis() > 5000 && gps.charsProcessed() < 10)
      {
        Serial.println(F("No GPS detected: check wiring."));
        while(true);
      }
    }


    ISR(TIMER2_OVF_vect) {
      TCNT2=59;//55;
      cntr++;
      if(cntr>711111) //1511111
      {
        cntr = 0;
        Serial.println(F("Q_Reset"));
       // delay (1000);
       // resetFunc();
        reboot();

      }
    }

     
     
  19. ardurino

    ardurino Нерд

    Вот только в куда вставить функцию displayInfo() с запуском POST-запроса? Раньше в коде было более менее понятно, когда GPS стал координаты получать, а тут не пойму...
    Код (C++):
     if (gps.encode(ss.read()))
        {
           displayInfo();
        }
      }
      if (millis() > 5000 && gps.charsProcessed() < 10)
      {
        Serial.println(F("No GPS detected: check wiring."));
        while(true);
      }
     
  20. brokly

    brokly Гик

    Зачем у вас в displayInfo() рекурсия ?

    Вместо delay используйте myDelay
    Код (C++):
    void myDelay(uint32_t ms){
      uint32_t old=millis();
      while (1) {
         while (ss.available()) {
            gps.encode(ss.read())
         }
         if (millis()-old>=ms) return;
      }
    }
     
    И уберите ss.begin(...) из кода, оставьте только одно обращение в setup().
    Прям реальный говнокод получится :)
     
    Последнее редактирование: 17 янв 2018