0

I am trying to get the current speed of my car using the GPS Neo, but my code always returns that the speed from the GPS is invalid. The green led of the GPS Neo is blinking. What is the isValid() function? Below the code:

#include <EEPROM.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
//LOAD WIRE LIB
#include<Wire.h>
static const int RXPin = 10, TXPin = 9;
static const uint32_t GPSBaud = 9600;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
//***************************************************************
int aux = 0;
int vel_prog = 20; //programed SPEED
float vel_atual;// actual SPEED
int val_inc = 0;
int val_dec = 0;
int led0 = 2;//led pin
int led20 = 3;//led pin
int led60 = 4;//led pin
int led80 = 5;//led pin
int ledsinal = 6;//led pin
int buzzer = 7;//buzzer pin
int incrementa = 8;//button pin
//****************************************************************
void setup()
{
 Serial.begin(115200);
 ss.begin(GPSBaud);
 pinMode(incrementa, INPUT);
 pinMode(led0, OUTPUT); // declare LED as output
 pinMode(led20, OUTPUT); // declare LED as output
 pinMode(led60, OUTPUT); // declare LED as output
 pinMode(led80, OUTPUT); // declare LED as output
 pinMode(ledsinal, OUTPUT); // declare LED as output
 pinMode(buzzer, OUTPUT); // dbuzeer
 delay(10);
}
void loop()
{
 smartDelay(1000);
 val_inc = digitalRead(incrementa); // read increment button
 if (val_inc == 1) {
 if (vel_prog > 80) {
 vel_prog = -20;
 }
 vel_prog = vel_prog + 20;
 }
 if (vel_prog == 0) {
 digitalWrite(led0,HIGH);
 digitalWrite(led20,LOW);
 digitalWrite(led60,LOW);
 digitalWrite(led80,LOW);
 } else if (vel_prog == 20) {
 digitalWrite(led0,LOW);
 digitalWrite(led20,HIGH);
 digitalWrite(led60,LOW);
 digitalWrite(led80,LOW);
 } else if (vel_prog == 60) {
 digitalWrite(led0,LOW);
 digitalWrite(led20,LOW);
 digitalWrite(led60,HIGH);
 digitalWrite(led80,LOW);
 } else if (vel_prog == 80) {
 digitalWrite(led0,LOW);
 digitalWrite(led20,LOW);
 digitalWrite(led60,LOW);
 digitalWrite(led80,HIGH);
 }
 if (gps.speed.isValid()){
 Serial.print(gps.speed.kmph());
 } else {
 Serial.print("*");
 }
 if (gps.speed.isValid()) { 
 if (gps.speed.kmph() >= vel_prog && aux == 0) { //comparacao da velocidades
 digitalWrite(ledsinal, HIGH); // turn LED OFF
 tone(buzzer, 2200);
 delay(5000);
 digitalWrite(ledsinal, LOW); // turn LED OFF
 noTone(buzzer);
 aux = 1;
 }
}
}
static void smartDelay(unsigned long ms)
{
 unsigned long start = millis();
 do
 {
 while (ss.available())
 gps.encode(ss.read());
 } while (millis() - start < ms);
}
asked Apr 9, 2017 at 16:56
6
  • What specific device are you using? Commented Apr 9, 2017 at 17:44
  • Arduino Nano AtMega 168, and a GY-GPSV3- NEO M8N GPS Commented Apr 9, 2017 at 20:03
  • No, I mean which GPS device! Commented Apr 9, 2017 at 20:03
  • Sorry, I edited the post Commented Apr 9, 2017 at 20:04
  • Looks like it should support Velocity reporting. Maybe you don't have a good enough fix, or maybe it needs turning on in the config. Step 1 is to examine exactly what NMEA messages it's sending while running. Use the ubiquitous serial pass-through sketch to read the raw NMEA data. Commented Apr 9, 2017 at 20:13

1 Answer 1

0

These lines of code will wreak havoc with reading the GPS data:

tone(buzzer, 2200);
delay(5000);
digitalWrite(ledsinal, LOW); // turn LED OFF
noTone(buzzer);

The Arduino is "blocked" at these lines for seconds. During that time, the GPS keeps babbling and eventually overflows the input buffer. The next call to smartDelay only waits for 1 second, and it may not get a complete sentence.

Here is a NeoGPS version of your sketch that does not block:

#include <EEPROM.h>
#include <NMEAGPS.h>
#include <NeoSWSerial.h>
#include <Wire.h>
NMEAGPS gps;
static const int RXPin = 10, TXPin = 9;
static const uint32_t GPSBaud = 9600;
NeoSWSerial gpsPort(RXPin, TXPin);
//***************************************************************
int aux = 0;
int vel_prog = 20; //programed SPEED
float vel_atual;// actual SPEED
int val_inc = 0;
int val_dec = 0;
int led0 = 2;//led pin
int led20 = 3;//led pin
int led60 = 4;//led pin
int led80 = 5;//led pin
int ledsinal = 6;//led pin
int buzzer = 7;//buzzer pin
bool buzzing = false;
uint32_t buzzTime;
int incrementa = 8;//button pin
//****************************************************************
void setup()
{
 Serial.begin(115200);
 gpsPort.begin(GPSBaud);
 pinMode(incrementa, INPUT);
 pinMode(led0, OUTPUT); // declare LED as output
 pinMode(led20, OUTPUT); // declare LED as output
 pinMode(led60, OUTPUT); // declare LED as output
 pinMode(led80, OUTPUT); // declare LED as output
 pinMode(ledsinal, OUTPUT); // declare LED as output
 pinMode(buzzer, OUTPUT); // dbuzeer
 delay(10);
}
void loop()
{
 // Check the buttons
 val_inc = digitalRead(incrementa); // read increment button
 if (val_inc == 1) {
 if (vel_prog > 80) {
 vel_prog = -20;
 }
 vel_prog = vel_prog + 20;
 }
 if (vel_prog == 0) {
 digitalWrite(led0,HIGH);
 digitalWrite(led20,LOW);
 digitalWrite(led60,LOW);
 digitalWrite(led80,LOW);
 } else if (vel_prog == 20) {
 digitalWrite(led0,LOW);
 digitalWrite(led20,HIGH);
 digitalWrite(led60,LOW);
 digitalWrite(led80,LOW);
 } else if (vel_prog == 60) {
 digitalWrite(led0,LOW);
 digitalWrite(led20,LOW);
 digitalWrite(led60,HIGH);
 digitalWrite(led80,LOW);
 } else if (vel_prog == 80) {
 digitalWrite(led0,LOW);
 digitalWrite(led20,LOW);
 digitalWrite(led60,LOW);
 digitalWrite(led80,HIGH);
 }
 // Check the GPS
 while (gps.available( gpsPort )) {
 gps_fix fix = gps.read();
 if (fix.valid.speed) {
 if ((fix.speed_kph() >= vel_prog) && (aux == 0)) { //comparacao da velocidades
 digitalWrite(ledsinal, HIGH); // turn LED OFF
 tone(buzzer, 2200);
 aux = 1;
 buzzing = true;
 buzzTime = millis();
 }
 Serial.print( fix.speed_kph() );
 } else {
 Serial.print( '*' );
 }
 }
 // Check the buzzer
 if (buzzing && (millis() - buzzTime > 5000)) {
 digitalWrite(ledsinal, LOW); // turn LED OFF
 noTone(buzzer);
 aux = 0; // Need this?
 buzzing = false;
 }
}

Notice how it checks millis() every time through loop to see if the buzzer has been on for 5 seconds. It doesn't block for 5 seconds.

It only checks the speed when a new GPS fix arrives. This happens once per second, not every time through loop.

Your original version uses 11472 bytes of program space and 786 bytes of RAM. The NeoGPS version uses 10722 bytes of program space and 590 bytes of RAM, a significant savings.

NeoGPS is smaller, faster and more accurate than all other libraries. If you want to try it, NeoGPS is available from the Arduino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries.

The above sketch also uses my NeoSWSerial. It is much more efficient than SoftwareSerial. SoftwareSerial blocks interrupts for long periods of time, which can interfere with other parts of your sketch.

It would be even better to use AltSoftSerial on pins 8 & 9 (on an UNO).

answered Apr 9, 2017 at 21:01
2
  • Thanks, now it's working, but another doubt, If I put the antenna pointing to the sky towards the front glass of the car, can the glass disturb the signal? Or should I put the antenna out of the car? Commented Apr 10, 2017 at 13:42
  • It should be fine inside the car. Unless you have a metallic mirror coating... Commented Apr 11, 2017 at 1:52

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.