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);
}
6
  • What specific device are you using?
    – Majenko
    Apr 9, 2017 at 17:44
  • Arduino Nano AtMega 168, and a GY-GPSV3- NEO M8N GPS
    – Mutante
    Apr 9, 2017 at 20:03
  • No, I mean which GPS device!
    – Majenko
    Apr 9, 2017 at 20:03
  • Sorry, I edited the post
    – Mutante
    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.
    – Majenko
    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).

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?
    – Mutante
    Apr 10, 2017 at 13:42
  • It should be fine inside the car. Unless you have a metallic mirror coating...
    – slash-dev
    Apr 11, 2017 at 1:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.