我用头文件TinyGPSPlus在Arduino uno中编写了以下代码,并使用了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();
}
Run Code Online (Sandbox Code Playgroud)
它获得了所需的输出.在串行监视器上连续显示数据行.但现在我需要每隔5秒准确地获取这些数据(即,每隔5秒,上面的代码应按照该瞬间生成输出).我尝试使用延迟执行此操作并重写循环代码,如下所示
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);
}
}
Run Code Online (Sandbox Code Playgroud)
但这并没有得到所需的输出.任何人都可以帮我解决这个问题.我应该在哪里编辑,我应该做些什么改变.
这是我写NeoGPS的原因.所有其他库的示例程序结构不正确.我在看着你,smartDelay()......
NeoGPS的结构是fix从GPS设备接收完整.这通常需要收到几个句子.其他GPS库只会在收到一个句子时告诉您.此外,很难判断两个句子是来自相同的1秒更新间隔,还是两个连续的间隔.
您希望每5秒显示一次信息,但可能每20个句子显示一次.根据Arduino 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();
}
Run Code Online (Sandbox Code Playgroud)
这个草图显示每五分之一fix,而不使用不准确millis()或令人讨厌的delay().是不是没有人有时间用于dat!
每个修复都是从每个1秒间隔的所有句子中累积出来的,无论是一个句子(RMC?),还是8个句子(GGA,GLL,RMC,GSV*3,GSA和VTG).在NeoGPS中,计数修复相当于计算秒数.
注意:如果您需要超精确的5秒间隔,请考虑使用PPS引脚(如果有).
即使时区转换为新的小时,日,月或年,本地时间也会在此草图中正确计算.您的草图未正确跨越日界.如果我正确阅读你的草图,5.5小时轮班.
我是否应该提到NeoGPS比其他所有库更小,更快,更准确?:)它可以从Arduino IDE库管理器,菜单Sketch - > Include Library - > Manage Libraries下获得.
你还应该考虑使用其他东西SoftwareSerial.这是非常低效的,因为它会长时间禁用中断.这可能会干扰草图的其他部分或其他库.
最好的软件串口库是AltSoftSerial.如果你可以切换到引脚8和9,我强烈建议这样做.
如果你不能切换引脚(你真的确定吗?),你应该使用我的NeoSWSerial.它适用于任何两个引脚,几乎同样有效.它支持您使用的9600波特率.