I wrote the following codes in Arduino uno with the header file TinyGPSPlus,and uses GPS SKG 13BL(GPS module).
#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();
}
It obtained the required output.Displays the lines of data continusly on serial monitor. But now i need to get these data exactly at every 5 secs (i.e At every 5 Secs the above code should generate output as per that instant).I tried to do this using delay and rewrote the loop code as follows
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);
}
}
But this doesnt obtained the output as desired.Can anyone please help me to solve this.Where should i edit and what changes should i make.
With an Arduino board, you can use your GPS module to advance beyond reading coordinates; you can even set up your device react to its conditions. The TinyGPS library makes a variety of time and position values available.
Accuracy: 2.5m GPS Horizontal Position Accuracy.
This is EXACTLY why I wrote NeoGPS. The example programs for all other libraries are just not structured properly. I'm looking at you, smartDelay()
...
NeoGPS is structured around receiving a complete fix
from the GPS device. This usually requires several sentences to be received. Other GPS libraries only tell you when one sentence is received. Furthermore, it's difficult to tell if two sentences are from the same 1-second update interval, or two consecutive intervals.
You want to display information once every 5 seconds, but that may be once every 20 sentences. And according to the Arduino millis()
clock, it will be about 5000ms, but not exactly. millis()
will drift against the GPS interval, depending on how accurate your crystal is. The GPS interval is very accurate,to the limits of the atomic clock, serial baud rate, and GPS device calculation time.
Here is your sketch, modified to use 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();
}
This sketch displays every fifth fix
, without using the inaccurate millis()
, or the nasty delay()
. Ain't nobody got time for dat!
And each fix is accumuated from all the sentences in each 1-second interval, whether it's one sentence (RMC?), or 8 sentences (GGA, GLL, RMC, GSV*3, GSA and VTG). In NeoGPS, counting fixes is equivalent to counting seconds.
NOTE: if you need a super-accurate 5-second interval, consider using the PPS pin, if available.
The local time is CORRECTLY computed in this sketch, even if the timezone shift steps into a new hour, day, month or year. Your sketch does not cross day boundaries correctly. 5.5 hour shift, if I read your sketch correctly.
Should I mention NeoGPS is smaller, faster and more accurate than all other libraries? :) It's available from the Arduino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries.
You should also consider using something besides SoftwareSerial
. It is very inefficient, because it disables interrupts for long periods of time. This can interfere with other parts of your sketch or with other libraries.
The best software serial port library is AltSoftSerial. If you can switch to pins 8 & 9, I would strongly recommend doing so.
If you can't switch pins (are you really sure?), you should use my NeoSWSerial. It works on any two pins, and is almost as efficient. It supports the 9600 baud rate you are using.
You should avoid using the normal delay function when working with this library, as it requires a new fix at a regular interval. In the example code you will find a function called smartDelay()
copy this function in to your code and use this instead. It looks like this.
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
Put this code in the bottom of your code at call smartDelay(5000);
instead of delay(5000);
in the bottom of the void loop()
You should also place the call to displayInfo();
just below smartDelay()
like this.
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();
}
A even better way, especially if you like to do other stuff while you showing the data, is to use millis()
. this will also be called more precise every 5 sec.
You wil have to declare a variable at the top for this to work. It will look like this.
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 give me an answer on how to get data in 5 secs interval from GPS.He also provided some improved methods, which when i followed obtains perfect output.It solved some bugs in the code i provided too.Link to the answer :
https://stackoverflow.com/a/43009260/7699452
result : https://i.stack.imgur.com/pzvsu.png
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With