1

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!

  • Code and schematic? – TisteAndii Apr 8 '16 at 13:31
  • @TisteAndii please see the code I inserted above. Thank you for your reply. :) – Georgina Pattinson Apr 11 '16 at 0:32
  • What speed do you get when you've been stationary for a minute? – TisteAndii Apr 11 '16 at 0:36
  • Sometimes, I get 1.01, 0.89, 0.06, 0.3 but I never get zero even when stationary state. That's impossible to get that values even when you are not moving on your place, so I concluded that there is something wrong on it. – Georgina Pattinson Apr 11 '16 at 1:07
  • 2
    Not necessarily. These modules arent perfect nor is the GPS technique they use to determine your speed. There will always be some tiny offset. So if you write code based on this, you will have to account for this offset in the code. E.g. if (gps.speed <= 1) moving = False. You will have to run tests and determine the maximum value you can get from the module, when you arent moving and use that to determine motion or the lack of it. – TisteAndii Apr 11 '16 at 1:19
4

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.

0

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.

  • have you find installer of the u-center for mac? I kept searching for it but I can't even find one. – Georgina Pattinson Apr 11 '16 at 1:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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