Хотите получать данные GPS каждые 5 секунд с помощью arduino
Я написал следующие коды в Arduino uno с заголовочным файлом TinyGPSPlus, и использует GPS SKG 13BL (GPS модуль).
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
/*
This program sketch obtain and print the lati,logi,speed,date and time
It requires the use of SoftwareSerial, and assumes that you have a
9600-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 4, TXPin = 3;
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(9600);
ss.begin(GPSBaud);
Serial.println(F("GPS LOADING....."));
Serial.println(F("Obtain and print lati,logi,speed,date and time"));
Serial.println(F("Testing by : "));
Serial.println(F("Billa"));
Serial.println();
}
void loop()
{
// This sketch displays information every time a new sentence is correctly encoded.
while (ss.available() > 0)
if (gps.encode(ss.read()))
displayInfo();
if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("No GPS detected: check wiring."));
while(true);
}
}
void displayInfo()
{
Serial.print(F("Location: "));
if (gps.location.isValid())
{
Serial.print(gps.location.lat(), 6);
Serial.print(F(","));
Serial.print(gps.location.lng(), 6);
}
else
{
Serial.print(F("INVALID"));
}
Serial.print(F(" Speed: "));
if (gps.speed.isValid())
{
Serial.print(gps.speed.kmph());
Serial.print(F(" KMPH "));
}
else
{
Serial.print(F("INVALID"));
}
Serial.print(F(" Date : "));
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(" Time : "));
if (gps.time.isValid())
{
int hour= gps.time.hour() + 5;
if (hour < 10) Serial.print(F("0"));
if(hour > 12) hour-=11;
Serial.print(hour);
Serial.print(F(":"));
int minute = gps.time.minute() + 30;
if(minute >= 60) minute-=60;
if (minute < 10) Serial.print(F("0"));
Serial.print(minute);
Serial.print(F(":"));
if (gps.time.second() < 10) Serial.print(F("0"));
Serial.print(gps.time.second());
}
else
{
Serial.print(F("INVALID"));
}
Serial.println();
}
Он получил требуемый результат.Отображает линии данных непрерывно на последовательном мониторе.
Но теперь мне нужно получать эти данные ровно через каждые 5 секунд (т. е. через каждые 5 секунд приведенный выше код должен генерировать выходные данные в соответствии с этим моментом).я попытался сделать это с помощью delay и переписал код цикла следующим образом: следует
void loop()
{
delay(5000);
// This sketch displays information every time a new sentence is correctly encoded.
while (ss.available() > 0)
if (gps.encode(ss.read()))
displayInfo();
if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("No GPS detected: check wiring."));
while(true);
}
}
Но это не дает желаемого результата.Может кто-нибудь помочь мне решить эту проблему.Где я должен редактировать и какие изменения я должен внести.
3 ответов:
Именно поэтому я написалNeoGPS . Примеры программ для всех других библиотек просто не структурированы должным образом. Я смотрю на тебя,
smartDelay()...NeoGPS структурирована вокруг получения полного
Вы хотите отображать информацию один раз в 5 секунд, но это может быть один раз в 20 предложений. И согласно часам Arduinofixот GPS-устройства. Обычно для этого требуется несколько предложений. Другие библиотеки GPS сообщают вам только о получении одного предложения. Кроме того, трудно сказать, относятся ли два предложения к одному и тому же 1-секундному интервалу обновления или к двум последовательным интервалы.millis(), это будет около 5000 мс, , но не совсем.millis()будет дрейфовать против интервала GPS, в зависимости от того, насколько точен ваш кристалл. Интервал GPS очень точен, в пределах атомных часов, последовательной скорости передачи данных и времени расчета GPS-устройства.Вот ваш эскиз, модифицированный для использования. NeoGPS:
#include <NMEAGPS.h> /* This program sketch obtain and print the lati,logi,speed,date and time It requires the use of SoftwareSerial, and assumes that you have a 9600-baud serial GPS device hooked up on pins 4(rx) and 3(tx). */ #include <NeoSWSerial.h> static const int RXPin = 4, TXPin = 3; NeoSWSerial gpsPort(RXPin, TXPin); static const uint32_t GPSBaud = 9600; NMEAGPS gps; gps_fix fix; uint8_t fixCount = 0; void setup() { Serial.begin(9600); gpsPort.begin(GPSBaud); Serial.println(F("GPS LOADING.....")); Serial.println(F("Obtain and print lati,logi,speed,date and time")); Serial.println(F("Testing by : ")); Serial.println(F("Billa")); Serial.println(); } void loop() { while (gps.available( gpsPort )) { fix = gps.read(); // Once every 5 seconds... if (++fixCount >= 5) { displayInfo(); fixCount = 0; } } if ((gps.statistics.chars < 10) && (millis() > 5000)) { Serial.println( F("No GPS detected: check wiring.") ); while(true); } } void displayInfo() { Serial.print(F("Location: ")); if (fix.valid.location) { Serial.print( fix.latitude(), 5 ); Serial.print( ',' ); Serial.print( fix.longitude(), 5 ); } else { Serial.print(F("INVALID")); } Serial.print(F(" Speed: ")); if (fix.valid.speed) { Serial.print(fix.speed_kph()); Serial.print(F(" KMPH ")); } else { Serial.print(F("INVALID")); } // Shift the date/time to local time NeoGPS::clock_t localSeconds; NeoGPS::time_t localTime; if (fix.valid.date && fix.valid.time) { using namespace NeoGPS; // save a little typing below... localSeconds = (clock_t) fix.dateTime; // convert structure to a second count localSeconds += 5 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE; // shift timezone localTime = localSeconds; // convert back to a structure } Serial.print(F(" Date : ")); if (fix.valid.date) { Serial.print(localTime.month); Serial.print('/'); Serial.print(localTime.date); Serial.print('/'); Serial.print(localTime.year); } else { Serial.print(F("INVALID")); } Serial.print(F(" Time : ")); if (fix.valid.time) { Serial.print(localTime.hours); Serial.print(':'); if (localTime.minutes < 10) Serial.print('0'); Serial.print(localTime.minutes); Serial.print(':'); if (localTime.seconds < 10) Serial.print(F("0")); Serial.print(localTime.seconds); } else { Serial.print(F("INVALID")); } Serial.println(); }Этот эскиз отображает каждый пятый
fix, не используя неточныйmillis()или неприятныйdelay(). Ни у кого нет времени на это!И каждое исправление накапливается из всех предложений в каждом 1-секундном интервале, будь то одно предложение (RMC?), или 8 предложений (GGA, GLL, RMC, GSV*3, GSA и VTG). В NeoGPS подсчет исправлений эквивалентен подсчету секунд.
Примечание: Если вам нужен сверхточный 5-секундный интервал, рассмотрите возможность использования пин-код PPS, если таковой имеется.
В этом эскизе местное время вычисляется правильно, даже если сдвиг часового пояса переходит в новый час, день, месяц или год. Ваш эскиз не пересекает границы дня правильно. 5.5 часовая смена, если я правильно прочитал ваш эскиз. Должен ли я упомянуть, что NeoGPS меньше, быстрее и точнее, чем все другие библиотеки? :) Он доступен из менеджера библиотек Arduino IDE, в меню Sketch - > Include Library - > Manage Библиотеки .Вы также должны рассмотреть возможность использования чего-то помимо
SoftwareSerial. Это очень неэффективно, потому что он отключает прерывания на длительные периоды времени. Это может повлиять на другие части вашего эскиза или на другие библиотеки.Лучшая библиотека последовательных портов программного обеспечения-AltSoftSerial. Если вы можете переключиться на контакты 8 и 9, я настоятельно рекомендую сделать это.
Если вы не можете переключать контакты (вы действительно уверены?), вы должны использовать мойNeoSWSerial . Это работает на любых двух булавках, и почти так же эффективно. Он поддерживает скорость передачи данных 9600 бод, которую вы используете.
Следует избегать использования обычной функции задержки при работе с этой библиотекой, так как она требует нового исправления с регулярным интервалом. В примере кода Вы найдете функцию под названием
smartDelay()скопируйте эту функцию в свой код и используйте ее вместо этого. Это выглядит так.static void smartDelay(unsigned long ms) { unsigned long start = millis(); do { while (ss.available()) gps.encode(ss.read()); } while (millis() - start < ms); }Поместите этот код в нижней части вашего кода при вызове
smartDelay(5000);вместоdelay(5000);в нижней частиvoid loop()Вы также должны поместить вызов вdisplayInfo();чуть нижеsmartDelay(), как это.void loop() { while (ss.available() > 0) if (gps.encode(ss.read())) if (millis() > 5000 && gps.charsProcessed() < 10) { Serial.println(F("No GPS detected: check wiring.")); while(true); } smartDelay(5000); displayInfo(); }
Редактировать: даже лучший способ
Еще лучший способ, особенно если вам нравится делать другие вещи, показывая данные, - это использовать
millis(). это также будет называться более точным каждые 5 секунд. Вам придется объявить переменную в верхней части, чтобы это сработало. Это будет выглядеть так.long timeToDisplay = 0; // Declare this at the top void loop() { while (ss.available() > 0) if (gps.encode(ss.read())) if (millis() > 5000 && gps.charsProcessed() < 10) { Serial.println(F("No GPS detected: check wiring.")); while(true); } if(timeToDisplay <= millis()) { timeToDisplay = millis() + 5000; displayInfo(); } }
Slash-dev дайте мне ответ о том, как получить данные в интервале 5 секунд от GPS.Он также предоставил некоторые улучшенные методы, которые, когда я следовал, достигают совершенства output.It решил некоторые ошибки в коде, который я предоставил тоже.Ссылка на ответ:
Https://stackoverflow.com/a/43009260/7699452
Результат : https://i.stack.imgur.com/pzvsu.png
Comments