Друзья! Есть у меня 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); }
Вы как бы не стой стороны к нему подходите Чтобы обновлять координаты 5 раз в секунду, надо подключить модуль к компу (через конвертер usart->usb ), запустить фирменное приложение U-center и уже ним настроить модуль на выдачу каждые 200мс. Однако, эти модули не блещут точностью. Бывают залеты на пару сотен метров. Плавали, знаем
Печаль...Т.е., чтобы мне установить 5 Гц, нужно каждый раз подключать этот GPS к компьютеру? Я так понимаю, этот U-center отправляет туда NMEA команды и готово. А останутся ли там они после ресета...Просто передо мной стоит задача сделать логгер, который включил в нужный момент, он записал как можно больше данных в интервале примерно 20 мин и дальше их обработать (при этом отсутствует возможность использовать ПК/Ноутбук).
Рано волосы рвете, товарищ Если на модуле стоит 8-ноговая микрушка, то это память и туда можно пихнуть настройки по-умолчанию. Так что все достаточно реально. Цепляйтесь к ю-центру. Кстати, он командует не НМЕА, а на своем UBX протоколе, который гораздо проще в обработке. И не забудьте отключить все не используемые вами сообщения, а то на малых скоростях обмена они забивают выходной буфер у модуля и начинают теряться.
Снова вернулся, к данной теме. Как я и думал на шилде памяти для хранения настроек не оказалось. Поискав в интернетах примеры, нашел, то что нужно мне. Теперь GPS работает на частоте 5Гц. Цепляюсь к U -centre все работает. Далее хотел организовать запись на СД карту и тут встрял (опыта не хватает). Смотрю в Serial и там вижу UBX комманды, добавляю строки для записи на СД и тут понеслась ересь... Открываю файлик на флешки, а там такая надпись " short line 17 character line too long for buffer" Друзья, прошу помощи, направьте посоветуйте, где с буфером, что сделать...Код ниже
Код (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); // Печатать имя }