3

enter image description here

I am doing a project using a NEO 6M GPS with my Arduino LilyPad. I programmed it already, and it's working well except of the speed. I get stuck on fixing this. I wonder why the value is never getting zero although I am not moving to my place.

I need any suggestions/help that would make the speed working accurately.

Thanks.

Here is the code I used:

 #include <SoftwareSerial.h>
 #include <TinyGPS.h>

SoftwareSerial mySerial(4, 3); // RX, TX
TinyGPS gps;

void gpsdump(TinyGPS &gps);
void printFloat(double f, int digits = 2);

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  delay(1000);
  Serial.print("Sizeof(gpsobject) = ");
  Serial.println(sizeof(TinyGPS));
  Serial.println();
}

void loop() {
  bool newdata = false;
  unsigned long start = millis();
  // Every 5 seconds we print an update
  while (millis() - start < 5000) {
    if (mySerial.available()) {
      char c = mySerial.read();
      if (gps.encode(c)) {
        newdata = true;
      }
    }
  }
  if (newdata) {
    Serial.println("Acquired Data");
    Serial.println("-------------");
    gpsdump(gps);
    Serial.println("-------------");
    Serial.println();
  }
}

void gpsdump(TinyGPS &gps) {
  long lat, lon;
  float flat, flon;
  unsigned long age, date, time, chars;
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned short sentences, failed;
  gps.get_position(&lat, &lon, &age);
  Serial.print("Lat/Long(10^-5 deg): ");
  Serial.print(lat); 
  Serial.print(", ");
  Serial.print(lon); 
  Serial.print(" Fix age: ");
  Serial.print(age);
  Serial.println("ms.");
  // On Arduino, GPS characters may be lost during lengthy Serial.print()
  // On Teensy, Serial prints to USB, which has large output buffering and
  // runs very fast, so it's not necessary to worry about missing 4800 baud GPS characters.
  gps.f_get_position(&flat, &flon, &age);
  Serial.print("Lat/Long(float): ");
  printFloat(flat, 5); 
  Serial.print(", "); 
  printFloat(flon, 5);
  Serial.print(" Fix age: ");
  Serial.print(age);
  Serial.println("ms.");
  gps.get_datetime(&date, &time, &age);
  Serial.print("Date(ddmmyy): "); 
  Serial.print(date);
  Serial.print(" Time(hhmmsscc): ");
  Serial.print(time);
  Serial.print(" Fix age: "); 
  Serial.print(age); 
  Serial.println("ms.");
  Serial.print("Alt(cm): "); 
  Serial.print(gps.altitude());
  Serial.print(" Course(10^-2 deg): ");
  Serial.print(gps.course()); 
  Serial.print(" Speed(10^-2 knots): ");
  Serial.println(gps.speed());
  Serial.print("Alt(float): ");
  printFloat(gps.f_altitude()); 
  Serial.print(" Course(float): ");
  printFloat(gps.f_course()); 
  Serial.println();
  Serial.print("Speed(knots): ");
  printFloat(gps.f_speed_knots()); 
  Serial.print(" (mph): ");
  printFloat(gps.f_speed_mph());
  Serial.print(" (mps): "); 
  printFloat(gps.f_speed_mps());
  Serial.print(" (kmph): ");
  printFloat(gps.f_speed_kmph());
  Serial.println();
  gps.stats(&chars, &sentences, &failed);
  Serial.print("Stats: characters: "); 
  Serial.print(chars);
  Serial.print(" sentences: ");
  Serial.print(sentences);
  Serial.print(" failed checksum: "); 
  Serial.println(failed);
}

void printFloat(double number, int digits) {
  // Handle negative numbers
  if (number < 0.0) {
    Serial.print('-');
    number = -number;
  }
  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;
  number += rounding;
  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  Serial.print(int_part);
  // Print the decimal point, but only if there are digits beyond
  if (digits > 0)
    Serial.print(".");
  // Extract digits from the remainder one at a time
  while (digits-- > 0) {
    remainder *= 10.0;
    int toPrint = int(remainder);
    Serial.print(toPrint);
    remainder -= toPrint;
  }
}

NOTE: The altitude and longitude were already working. It's the speed that I want to fix. I want to see it as "ZERO SPEED" when at a steady state. How can I fix this? Please help me. Thanks!

dda
  • 1,595
  • 1
  • 12
  • 17

2 Answers2

6

The speed value is correct, like TisteAndi said. Your GPS location "wanders" around the same way. You can simply ignore small speed values.

One problem you may not be aware of yet: the printing isn't really coordinated with the GPS updates. Sometimes that doesn't matter, but if you want your speed to update every second, you'll need to synchronize the two. And as noted in the code, you can actually lose GPS data if you print too much.

I wrote a GPS library, called NeoGPS, to fix some of these problems. They are described in the Troubleshooting section of the online documentation.

Also, SoftwareSerial is very inefficient. I maintain a more-efficient alternative, NeoSWSerial. As you add more features to your GPS program, the efficiency will become important.

Here is your program, modified to use NeoGPS and NeoSWSerial, and it uses TisteAndi's suggestion to set the speed to zero:

#include <Arduino.h>
#include "NMEAGPS.h"
#include <NeoSWSerial.h>

NeoSWSerial mySerial(4, 3); // RX, TX//

NMEAGPS     gps;
gps_fix     fix;
uint8_t     GPSupdates = 0;

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);

  delay(1000);

  Serial.print("Sizeof(gps) = "); Serial.println(sizeof(gps));
  Serial.println();
}

void loop() // run over and over
{
  while (gps.available( mySerial )) {
    fix = gps.read();

    if (fix.valid.speed && (fix.speed_mkn() < 1000)) {
      // Too slow, zero out the speed
      fix.spd.whole = 0;
      fix.spd.frac  = 0;
    }

    GPSupdates++;
  }

  // Print once every 5 seconds
  if (GPSupdates >= 5) {
    Serial.println("Acquired Data");
    Serial.println("-------------");
    gpsdump();
    Serial.println("-------------");
    Serial.println();

    GPSupdates = 0;
  }

}

void gpsdump()
{
  Serial.print("Lat/Long(10^-7 deg): ");
  if (fix.valid.location) {
    Serial.print(fix.lat); 
    Serial.print(", ");
    Serial.print(fix.lon);
  }
  Serial.println();

  // GPS characters may be lost during lengthy Serial.print()
  //   See the NeoGPS Troubleshooting section.

  Serial.print("Lat/Long(float): ");
  if (fix.valid.location) {
    Serial.print(fix.latitude(), 5); 
    Serial.print(", "); 
    Serial.print(fix.longitude(), 5);
  }
  Serial.println();

  Serial.print("Date/Time: "); 
  if (fix.valid.date | fix.valid.time)
    Serial << fix.dateTime;
  Serial.println();

  //*
  Serial.print("Date: "); 
  if (fix.valid.date) {
    Serial.print(fix.dateTime.month); 
    Serial.print("/"); 
    Serial.print(fix.dateTime.date);
    Serial.print("/");
    Serial.print(fix.dateTime.year);
  }

  if (fix.valid.date | fix.valid.time) {
    Serial.print("  Time: "); 
    Serial.print(fix.dateTime.hours); 
    Serial.print(":"); 
    Serial.print(fix.dateTime.minutes); 
    Serial.print(":"); 
    Serial.print(fix.dateTime.seconds);
    Serial.print(".");
    Serial.print(fix.dateTime_cs);
  }
  Serial.println();
  //*/

  Serial.print("Alt(cm): "); 
  if (fix.valid.altitude)
    Serial.print(fix.altitude_cm());

  Serial.print(" Course(10^-2 deg): ");
  if (fix.valid.heading)
    Serial.print(fix.heading_cd()); 

  Serial.print(" Speed(10^-3 knots): ");
  if (fix.valid.speed)
    Serial.print(fix.speed_mkn());
  Serial.println();

  Serial.print("Alt(float): ");
  if (fix.valid.altitude)
    Serial.print(fix.altitude()); 

  Serial.print(" Course(float): ");
  if (fix.valid.heading)
    Serial.print(fix.heading()); 
  Serial.println();

  Serial.print("Speed(knots): ");
  if (fix.valid.speed)
    Serial.print(fix.speed()); 
  Serial.print(" (mph): ");
  if (fix.valid.speed)
    Serial.print(fix.speed_mph());
  Serial.print(" (mps): "); 
  if (fix.valid.speed)
    Serial.print(fix.speed_kph()*3600.0/1000.0);
  Serial.print(" (kmph): ");
  if (fix.valid.speed)
    Serial.print(fix.speed_kph());
  Serial.println();

  Serial.print("Stats: characters: "); 
  Serial.print(gps.statistics.chars);
  Serial.print(" sentences: ");
  Serial.print(gps.statistics.ok);
  Serial.print(" failed checksum: "); 
  Serial.println(gps.statistics.crc_errors);
}

(Notice the increased accuracy of the integer lat/lon! And you don't need printFloat.)

If you'd like to try it, be sure to follow the NeoGPS Installation instructions. NeoSWSerial is installed like most Arduino libraries.

DocWeird
  • 118
  • 4
slash-dev
  • 2,029
  • 13
  • 12
1

Usually, this should be solved by just going outside to get the first fix point. If you still don't manage it, try the U-center software to make sure your GPS is properly working.

M3phistos
  • 11
  • 1