Как заставить работать GPS Shield на частоте 5Гц

Тема в разделе "Arduino & Shields", создана пользователем Dim_, 31 янв 2017.

  1. Dim_

    Dim_ Нуб

    Друзья! Есть у меня GPS shield и на чипе NEO-6M и необходимость записи координат как можно чаще. В спецификации написано, что он может работать на частоте 5Гц. Самое то!
    Прошу помощи может у кого получалось запустить его на такой частоте. Использую библиотеку TinyGPS++.
    Эксперементировал на стандартном примере из библиотеки.
    Пробовал менять размер буфера, время задержки и проч...координаты ооочень плавают.
    Ниже представлен немного измененный код примера из библиотеки.
    Может у кто сталкивался, поделитесь знаниями.
    Код (C++):
    #include <TinyGPS++.h>
    #include <SoftwareSerial.h>
    #define _SS_MAX_RX_BUFF 256 //Размер буфера
    /*
       This sample code 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).
    */

    static const int RXPin = 6, TXPin = 7;
    static const uint32_t GPSBaud = 9600;

    // The TinyGPS++ object
    TinyGPSPlus gps;

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

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

      Serial.println(F("FullExample.ino"));
      Serial.println(F("An extensive example of many interesting TinyGPS++ features"));
      Serial.print(F("Testing TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
      Serial.println(F("by Mikal Hart"));
      Serial.println();
      Serial.println(F("Sats HDOP Latitude   Longitude   Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum"));
      Serial.println(F("          (deg)      (deg)       Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail"));
      Serial.println(F("---------------------------------------------------------------------------------------------------------------------------------------"));
    }

    void loop()
    {
      static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

      printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
      printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
      printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
      printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
      printInt(gps.location.age(), gps.location.isValid(), 5);
      printDateTime(gps.date, gps.time);
      printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
      printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
      printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
      printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.value()) : "*** ", 6);

      unsigned long distanceKmToLondon =
        (unsigned long)TinyGPSPlus::distanceBetween(
          gps.location.lat(),
          gps.location.lng(),
          LONDON_LAT,
          LONDON_LON) / 1000;
      printInt(distanceKmToLondon, gps.location.isValid(), 9);

      double courseToLondon =
        TinyGPSPlus::courseTo(
          gps.location.lat(),
          gps.location.lng(),
          LONDON_LAT,
          LONDON_LON);

      printFloat(courseToLondon, gps.location.isValid(), 7, 2);

      const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);

      printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);

      printInt(gps.charsProcessed(), true, 6);
      printInt(gps.sentencesWithFix(), true, 10);
      printInt(gps.failedChecksum(), true, 9);
      Serial.println();
     
      smartDelay(200);// Обновление 5 раз в секунду

      if (millis() > 5000 && gps.charsProcessed() < 10)
        Serial.println(F("No GPS data received: check wiring"));
    }

    // This custom version of delay() ensures that the gps object
    // is being "fed".
    static void smartDelay(unsigned long ms)
    {
      unsigned long start = millis();
      do
      {
        while (ss.available())
          gps.encode(ss.read());
      } while (millis() - start < ms);
    }

    static void printFloat(float val, bool valid, int len, int prec)
    {
      if (!valid)
      {
        while (len-- > 1)
          Serial.print('*');
        Serial.print(' ');
      }
      else
      {
        Serial.print(val, prec);
        int vi = abs((int)val);
        int flen = prec + (val < 0.0 ? 2 : 1); // . and -
        flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
        for (int i=flen; i<len; ++i)
          Serial.print(' ');
      }
      smartDelay(0);
    }

    static void printInt(unsigned long val, bool valid, int len)
    {
      char sz[32] = "*****************";
      if (valid)
        sprintf(sz, "%ld", val);
      sz[len] = 0;
      for (int i=strlen(sz); i<len; ++i)
        sz[i] = ' ';
      if (len > 0)
        sz[len-1] = ' ';
      Serial.print(sz);
      smartDelay(0);
    }

    static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
    {
      if (!d.isValid())
      {
        Serial.print(F("********** "));
      }
      else
      {
        char sz[32];
        sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
        Serial.print(sz);
      }
     
      if (!t.isValid())
      {
        Serial.print(F("******** "));
      }
      else
      {
        char sz[32];
        sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
        Serial.print(sz);
      }

      printInt(d.age(), d.isValid(), 5);
      smartDelay(0);
    }

    static void printStr(const char *str, int len)
    {
      int slen = strlen(str);
      for (int i=0; i<len; ++i)
        Serial.print(i<slen ? str[i] : ' ');
      smartDelay(0);
    }
     
  2. sslobodyan

    sslobodyan Гик

    Вы как бы не стой стороны к нему подходите :)
    Чтобы обновлять координаты 5 раз в секунду, надо подключить модуль к компу (через конвертер usart->usb ), запустить фирменное приложение U-center и уже ним настроить модуль на выдачу каждые 200мс. Однако, эти модули не блещут точностью. Бывают залеты на пару сотен метров. Плавали, знаем :(
     
  3. Dim_

    Dim_ Нуб

    Печаль...Т.е., чтобы мне установить 5 Гц, нужно каждый раз подключать этот GPS к компьютеру? Я так понимаю, этот U-center отправляет туда NMEA команды и готово. А останутся ли там они после ресета...Просто передо мной стоит задача сделать логгер, который включил в нужный момент, он записал как можно больше данных в интервале примерно 20 мин и дальше их обработать (при этом отсутствует возможность использовать ПК/Ноутбук).
     
  4. sslobodyan

    sslobodyan Гик

    Рано волосы рвете, товарищ :)
    Если на модуле стоит 8-ноговая микрушка, то это память и туда можно пихнуть настройки по-умолчанию. Так что все достаточно реально. Цепляйтесь к ю-центру. Кстати, он командует не НМЕА, а на своем UBX протоколе, который гораздо проще в обработке. И не забудьте отключить все не используемые вами сообщения, а то на малых скоростях обмена они забивают выходной буфер у модуля и начинают теряться.
     
    Dim_ нравится это.
  5. Dim_

    Dim_ Нуб

    ОК, будем пробовать. Хоть кто-то дорогу подсказал. Спасибо!
     
  6. Dim_

    Dim_ Нуб

    Снова вернулся, к данной теме. Как я и думал на шилде памяти для хранения настроек не оказалось. Поискав в интернетах примеры, нашел, то что нужно мне. Теперь GPS работает на частоте 5Гц. Цепляюсь к U -centre все работает. Далее хотел организовать запись на СД карту и тут встрял (опыта не хватает). Смотрю в Serial и там вижу UBX комманды, добавляю строки для записи на СД и тут понеслась ересь... Открываю файлик на флешки, а там такая надпись " short line 17 character line too long for buffer" Друзья, прошу помощи, направьте посоветуйте, где с буфером, что сделать...Код ниже
     
  7. Dim_

    Dim_ Нуб

    Код (C++):
    #include <SoftwareSerial.h>
    #include <SD.h>
    #include <SPI.h>
    #define ARDUINO_USD_CS 10 // CS пин для Sd
    #define LOG_FILE_PREFIX "gpslog" // Имя файла
    #define MAX_LOG_FILES 100 // Макс число файлов
    #define LOG_FILE_SUFFIX "ubx" // расширение
    char logFileName[13]; // Строка для имени файла
    boolean gpsStatus[] = {false, false, false, false, false, false, false};
    unsigned long start;

    SoftwareSerial gpsSerial(6,7);

    void setup()
    {
      gpsSerial.begin(9600);
      // START OUR SERIAL DEBUG PORT
      Serial.begin(115200);
      updateFileName();

      byte settingsArray[] = {0x03, 0xC8, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //
      configureUblox(settingsArray);
    }

    void loop()
    {
      while(1) {
        if(gpsSerial.available())
        {
        Serial.write(gpsSerial.read());
        File logFile = SD.open(logFileName, FILE_WRITE); // Open the log file

      if (logFile)
      {
        logFile.println(gpsSerial.read());
        logFile.close();

      }

      }

      }
        }
    void configureUblox(byte *settingsArrayPointer) {
      byte gpsSetSuccess = 0;
      Serial.println("Configuring u-Blox GPS initial state...");

      byte setNav[] = {0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, *settingsArrayPointer, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
      calcChecksum(&setNav[2], sizeof(setNav) - 4);

      byte setDataRate[] = {0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, settingsArrayPointer[1], settingsArrayPointer[2], 0x01, 0x00, 0x01, 0x00, 0x00, 0x00};
      calcChecksum(&setDataRate[2], sizeof(setDataRate) - 4);

      byte setPortRate[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, settingsArrayPointer[3], settingsArrayPointer[4], settingsArrayPointer[5], 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
      calcChecksum(&setPortRate[2], sizeof(setPortRate) - 4);

      byte setGLL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2B};
      byte setGSA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x32};
      byte setGSV[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39};
      byte setRMC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40};
      byte setVTG[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46};

      delay(2500);

      while(gpsSetSuccess < 3)
      {
        Serial.print("Setting Navigation Mode... ");
        sendUBX(&setNav[0], sizeof(setNav));  //Send UBX Packet
        gpsSetSuccess += getUBX_ACK(&setNav[2]); //Passes Class ID and Message ID to the ACK Receive function
        if (gpsSetSuccess == 5) {
          gpsSetSuccess -= 4;
          setBaud(settingsArrayPointer[4]);
          delay(1500);
          byte lowerPortRate[] = {0xB5, 0x62, 0x06, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0xD0, 0x08, 0x00, 0x00, 0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xB5};
          sendUBX(lowerPortRate, sizeof(lowerPortRate));
          gpsSerial.begin(9600);
          delay(2000);    
        }
        if(gpsSetSuccess == 6) gpsSetSuccess -= 4;
        if (gpsSetSuccess == 10) gpsStatus[0] = true;
      }
      if (gpsSetSuccess == 3) Serial.println("Navigation mode configuration failed.");
      gpsSetSuccess = 0;
      while(gpsSetSuccess < 3) {
        Serial.print("Setting Data Update Rate... ");
        sendUBX(&setDataRate[0], sizeof(setDataRate));  //Send UBX Packet
        gpsSetSuccess += getUBX_ACK(&setDataRate[2]); //Passes Class ID and Message ID to the ACK Receive function    
        if (gpsSetSuccess == 10) gpsStatus[1] = true;
        if (gpsSetSuccess == 5 | gpsSetSuccess == 6) gpsSetSuccess -= 4;
      }
      if (gpsSetSuccess == 3) Serial.println("Data update mode configuration failed.");
      gpsSetSuccess = 0;


      while(gpsSetSuccess < 3 && settingsArrayPointer[6] == 0x00) {
        Serial.print("Deactivating NMEA GLL Messages ");
        sendUBX(setGLL, sizeof(setGLL));
        gpsSetSuccess += getUBX_ACK(&setGLL[2]);
        if (gpsSetSuccess == 10) gpsStatus[2] = true;
        if (gpsSetSuccess == 5 | gpsSetSuccess == 6) gpsSetSuccess -= 4;
      }
      if (gpsSetSuccess == 3) Serial.println("NMEA GLL Message Deactivation Failed!");
      gpsSetSuccess = 0;

      while(gpsSetSuccess < 3 && settingsArrayPointer[7] == 0x00) {
        Serial.print("Deactivating NMEA GSA Messages ");
        sendUBX(setGSA, sizeof(setGSA));
        gpsSetSuccess += getUBX_ACK(&setGSA[2]);
        if (gpsSetSuccess == 10) gpsStatus[3] = true;
        if (gpsSetSuccess == 5 | gpsSetSuccess == 6) gpsSetSuccess -= 4;
      }
      if (gpsSetSuccess == 3) Serial.println("NMEA GSA Message Deactivation Failed!");
      gpsSetSuccess = 0;

      while(gpsSetSuccess < 3 && settingsArrayPointer[8] == 0x00) {
        Serial.print("Deactivating NMEA GSV Messages ");
        sendUBX(setGSV, sizeof(setGSV));
        gpsSetSuccess += getUBX_ACK(&setGSV[2]);
        if (gpsSetSuccess == 10) gpsStatus[4] = true;
        if (gpsSetSuccess == 5 | gpsSetSuccess == 6) gpsSetSuccess -= 4;
      }
      if (gpsSetSuccess == 3) Serial.println("NMEA GSV Message Deactivation Failed!");
      gpsSetSuccess = 0;

      while(gpsSetSuccess < 3 && settingsArrayPointer[9] == 0x00) {
        Serial.print("Deactivating NMEA RMC Messages ");
        sendUBX(setRMC, sizeof(setRMC));
        gpsSetSuccess += getUBX_ACK(&setRMC[2]);
        if (gpsSetSuccess == 10) gpsStatus[5] = true;
        if (gpsSetSuccess == 5 | gpsSetSuccess == 6) gpsSetSuccess -= 4;
      }
      if (gpsSetSuccess == 3) Serial.println("NMEA RMC Message Deactivation Failed!");
      gpsSetSuccess = 0;

      while(gpsSetSuccess < 3 && settingsArrayPointer[10] == 0x00) {
        Serial.print("Deactivating NMEA VTG Messages ");
        sendUBX(setVTG, sizeof(setVTG));
        gpsSetSuccess += getUBX_ACK(&setVTG[2]);
        if (gpsSetSuccess == 10) gpsStatus[6] = true;
        if (gpsSetSuccess == 5 | gpsSetSuccess == 6) gpsSetSuccess -= 4;
      }
      if (gpsSetSuccess == 3) Serial.println("NMEA VTG Message Deactivation Failed!");

      gpsSetSuccess = 0;
      if (settingsArrayPointer[4] != 0x25) {
        Serial.print("Setting Port Baud Rate... ");
        sendUBX(&setPortRate[0], sizeof(setPortRate));
        setBaud(settingsArrayPointer[4]);
        Serial.println("Success!");
        delay(500);
      }
    }


    void calcChecksum(byte *checksumPayload, byte payloadSize) {
      byte CK_A = 0, CK_B = 0;
      for (int i = 0; i < payloadSize ;i++) {
        CK_A = CK_A + *checksumPayload;
        CK_B = CK_B + CK_A;
        checksumPayload++;
      }
      *checksumPayload = CK_A;
      checksumPayload++;
      *checksumPayload = CK_B;
    }

    void sendUBX(byte *UBXmsg, byte msgLength) {
      for(int i = 0; i < msgLength; i++) {
        gpsSerial.write(UBXmsg[i]);
        gpsSerial.flush();
      }
      gpsSerial.println();
      gpsSerial.flush();
    }


    byte getUBX_ACK(byte *msgID) {
      byte CK_A = 0, CK_B = 0;
      byte incoming_char;
      boolean headerReceived = false;
      unsigned long ackWait = millis();
      byte ackPacket[10] = {0xB5, 0x62, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
      int i = 0;
      while (1) {
        if (gpsSerial.available()) {
          incoming_char = gpsSerial.read();
          if (incoming_char == ackPacket[i]) {
            i++;
          }
          else if (i > 2) {
            ackPacket[i] = incoming_char;
            i++;
          }
        }
        if (i > 9) break;
        if ((millis() - ackWait) > 1500) {
          Serial.println("ACK Timeout");
          return 5;
        }
        if (i == 4 && ackPacket[3] == 0x00) {
          Serial.println("NAK Received");
          return 1;
        }
      }

      for (i = 2; i < 8 ;i++) {
      CK_A = CK_A + ackPacket[i];
      CK_B = CK_B + CK_A;
      }
      if (msgID[0] == ackPacket[6] && msgID[1] == ackPacket[7] && CK_A == ackPacket[8] && CK_B == ackPacket[9]) {
        Serial.println("Success!");
        Serial.print("ACK Received! ");
        printHex(ackPacket, sizeof(ackPacket));
        return 10;
            }
      else {
        Serial.print("ACK Checksum Failure: ");
        printHex(ackPacket, sizeof(ackPacket));
        delay(1000);
        return 1;
      }
    }


    void printHex(uint8_t *data, uint8_t length) // prints 8-bit data in hex
    {
      char tmp[length*2+1];
      byte first ;
      int j=0;
      for (byte i = 0; i < length; i++)
      {
        first = (data[i] >> 4) | 48;
        if (first > 57) tmp[j] = first + (byte)7;
        else tmp[j] = first ;
        j++;

        first = (data[i] & 0x0F) | 48;
        if (first > 57) tmp[j] = first + (byte)7;
        else tmp[j] = first;
        j++;
      }
      tmp[length*2] = 0;
      for (byte i = 0, j = 0; i < sizeof(tmp); i++) {
        Serial.print(tmp[i]);
        if (j == 1) {
          Serial.print(" ");
          j = 0;
        }
        else j++;
      }
      Serial.println();
    }

    void setBaud(byte baudSetting) {
      if (baudSetting == 0x12) gpsSerial.begin(4800);
      if (baudSetting == 0x4B) gpsSerial.begin(19200);
      if (baudSetting == 0x96) gpsSerial.begin(38400);
      if (baudSetting == 0xE1) gpsSerial.begin(57600);
      if (baudSetting == 0xC2) gpsSerial.begin(115200);
      if (baudSetting == 0x84) gpsSerial.begin(230400);
    }
    void updateFileName()
    {
      int i = 0;
      for (; i < MAX_LOG_FILES; i++)
      {
        memset(logFileName, 0, strlen(logFileName)); // очистить имя
        // Set logFileName to "gpslogXX.csv":
        sprintf(logFileName, "%s%d.%s", LOG_FILE_PREFIX, i, LOG_FILE_SUFFIX);
        if (!SD.exists(logFileName)) // если файл не существует
        {
          break; // прервать
        }
        else // Otherwise:
        {
          Serial.print(logFileName);
          Serial.println(" exists");
        }
      }
      Serial.print("File name: ");
      Serial.println(logFileName); // Печатать имя
    }