GPS Speedometer, problems when still

I'm working on a GPS based speedometer, odometer (and many other functions in future) with Arduino Nano. The initial plan is to use it on my bycicle, but later I would like to be able to use it in car, while on foot etc. I have a Arduino Nano, Neo uBlox 6M module and ADXL345 accelerometer. GPS is working fine wile I'm riding my bike, it shows speed and correctly calculates odometer (distance travelled), with only small deviations from my mobile phone (Endomondo). The problems begin when I'm stopped. This GPS is not very precise so it often starts variating while I'm not moving, thus increasing the odometer. It's not that bad if I'm outside, under the bright sky but as soon as I bring the device inside the house, when it starts losing signal, sometimes it shows speeds up to 10 km/h and it increases odometer for example for 400 meters in 2-3 seconds which is unnaceptable behaviour.

So any idea how to solve this? So, basically, I want the device to be able to detect that I'm standing still and the speed must be 0 km/h and the odometer musn't increase. I wanted to use the accelerometer to detect if the device is moving or standing still, and then disable GPS while the device is still, but this seems hard to realize or almost impossible. I tried to get the speed from accelerometer but without success. Basically, what I'm getting from accelerometer are angles which changes only when I rotate the device.

I had some ideas, like to remember last few positions and if they're all inside a small circle, refuse to add these distances to odometer. But I wanted to check if there are some simpler solutions.

It's not that bad if I'm outside, under the bright sky but as soon as I bring the device inside the house, when it starts losing signal, sometimes it shows speeds up to 10 km/h and it increases odometer for example for 400 meters in 2-3 seconds which is unnaceptable behaviour.

Normal behavior for inexpensive GPS with limited reception. The more satellites, the better the performance. Fussing about it is like complaining to SirusXM that having the receive buffer runs empty while you are in a tunnel is unacceptable!

Patient tells doctor, "It hurts when I do this..."
Doctor tells patient, "Don't do that..."

Ray

Problems are there to fix them, not to avoid/ignore them. Thank you for your post, but if you don't have constructive advices, it's better to stay away from this topic.

SiriusXM is one thing, this is another thing and can be fixed. How do those GPS based speedometers on smartphones work? I bet that GPS module in phone is even more inexpesive since this "big" antenna which I have surely won't fit inside any smartphone. So I expect the same or better performance than on average smartphone. But I bet they use some smarter algorithms than just calculating distance between 2 locations every 2 seconds.

Problems are there to fix them, not to avoid/ignore them.

GPS does not work indoors. The fix is to go outside.

GPS speeds are notoriously inaccurate at low speeds, because GPS itself is inaccurate. The fix is to go faster, so that the relative error in distance measurement between timepoints is less.

Maybe add an accelerometer to detect movement and override the GPS reading when you are still.

I've ridden bikes for most of my life, and what I never do is travel at 1 mph. or less. Why don't you examine a sequence of consecutive readings, and determine if you appear to be coming to a stop? Then, when you hit 1 mph., or some threshold, just quit reading coordinates and assume you're stationary. If you start up, you can watch a series of consecutive readings again, and when you decide you're actually in motion, take readings again, and extrapolate backwards to figure out how far you went since motion was detected,and add it to your odometer. Nothing here more complicated that speedxtime = distance.

XploD:
I'm working on a GPS based speedometer, odometer (and many other functions in future) with Arduino Nano. The initial plan is to use it on my bycicle, but later I would like to be able to use it in car, while on foot etc. I have a Arduino Nano, Neo uBlox 6M module and ADXL345 accelerometer. GPS is working fine wile I'm riding my bike, it shows speed and correctly calculates odometer (distance travelled), with only small deviations from my mobile phone (Endomondo). The problems begin when I'm stopped. This GPS is not very precise so it often starts variating while I'm not moving, thus increasing the odometer. It's not that bad if I'm outside, under the bright sky but as soon as I bring the device inside the house, when it starts losing signal, sometimes it shows speeds up to 10 km/h and it increases odometer for example for 400 meters in 2-3 seconds which is unnaceptable behaviour.

Indoor use of GPS within buildings is unnaceptable behaviour.
Use GPS outdoors under open sky!

And odometer calculations seem to be done very wrong: When the GPS is travelling at 10 km/h, which is 2.78 m/s, then the odometer might increase by 4*2.78m in 4 seconds= 11.12 meters, but NOT 400 meters in 2-3 seconds at 10km/h

Check the calculations in odometer code !

To reduce a "jumpy" speed, you can use a low-pass filter on the speeds to smooth them out. And to ignore the GPS speed when you're not going very fast, use a threshold. Here's a NeoGPS program that does both:

#include "NMEAGPS.h"
//#include <NeoSWSerial.h>
//#include <AltSoftSerial.h>

// Uncomment *one* to pick a port or define your own:
//AltSoftSerial gps_port; // 8 to GPS TX, 9 to GPS RX
//NeoSWSerial gps_port(3,4); // Instead of SoftwareSerial!
HardwareSerial & gps_port = Serial1; // an alias, if you have a Mega

NMEAGPS gps;
gps_fix fix;

void setup()
{
  Serial  .begin( 9600 );
  gps_port.begin( 9600 );
}


void loop()
{
  if (gps.available( gps_port )) {
    fix = gps.read();
    displaySpeed();
  }
}

static const uint16_t MIN_KNOTS =   10; //  ~11 mph

void displaySpeed()
{
  if (fix.valid.speed) {
    uint16_t knots = fix.spd.whole;

    // For debugging, show the original GPS speed
    Serial.print( '(' );
    Serial.print( knots );
    Serial.print( '.' );
    // Print leading zeroes for fraction part, if needed
    if (fix.spd.frac < 100)
      Serial.print( '0' );
    if (fix.spd.frac < 10)
      Serial.print( '0' );
    Serial.print( fix.spd.frac );
    Serial.print( F(") -> ") );

    // Threshold first
    if (knots < MIN_KNOTS)
      knots = 0;

    // Simple Low-Pass filter with a window of 4 samples
    static uint16_t averageKnots = 0;
    averageKnots = (averageKnots * 3) / 4  + knots;
    knots        = averageKnots / 4;

    // Convert to other units
    uint16_t mph = (knots * 1151L) / 1000L;
    uint16_t kph = (knots * 1852L) / 1000L;

    // Show the speed
    Serial.print( knots );
    Serial.print( F(" knots, ") );
    Serial.print( mph );
    Serial.print( F(" mph, " ) );
    Serial.print( kph );
    Serial.println( F(" kph" ) );

  } else {
    // No speed available yet
    Serial.println( '-' );
  }
}

This also shows how to know whether you even have a speed value yet.

BTW, the NEO-6M can be configured to use a threshold. It can also be told what kind of "platform" it's on (e.g., pedestrian, stationary, automotive, etc.) to reduce some of the "jumpiness".

What have you tried for the accelerometer? It is very common to use an IMU to improve GPS accuracy, but it requires knowing orientation. When indoors, the IMU won't be real accurate by itself. Combined with a gyroscope (orientation change) and a compass (absolute orientation WRT the Earth's magnetic field), it will be even better.

The ADXL345 does not have rotational sensing, so it's not the best choice. The MPU6050 has the rotation sensors and can use a compass. It also performs internal calculations to give you better orientation, and thus better velocity information.

Cheers,
/dev

Thank you for all the replies, it surely gave me some ideas and will help me a lot with my project :).

  1. I saw that some of you didn't understand very well what I tried to say so it seems that I'm trying to use the GPS inside the house which is wrong, how could I drive a bike inside a house? :smiley: But, when I finish with my ride, I take the device with me inside the house to charge it and to work further on the project. If I leave it turned on inside the house, it still has some little GPS signal so it "works" but it shows random speeds up 10 km/h and it increases my odometer. So my intentions are not to use it inside the house to meassure speed and distance. I want to prevent it to do such things. Yes, I know that I can simply use a "STOP" button which I would press when I finish with my ride and turn off the GPS, but hey, we live in 21st century, these things have to be done automatically, without me pressing the button. I know that GPS is inaccurate at low speeds and that it doesn't work indoors and that's why I'm looking for some mechanism to turn off GPS automatically while I'm not moving and thus preventing weird speed meassurements and incorrent odometer increasing.

  2. I'm not using the speed to calculate distance (that classic s = v/t). I'm using a formula/function to calculate distance between two points (given by latitude and longitude), here's the pseudocode:

if 2 seconds passed:
if gps coordinates are valid:
odometer += calculate_distance(gps.latitude(), gps.longitude(), oldLatitude, oldLongitude)
oldLatitude = gps.latitude()
oldLongitude = gps.longitude()

There are two reasons why I'm using this way:

  1. I think that it's more precise than calculating it from the speed
  2. In case of lost signal, it will still work, it will have some error (because it calculates air distance, not real distance), but better anything than nothing. I had a few times a lost signal for 5-6 seconds and it calculated distance just fine. It remembers last known latitude and longitude and when the signal comes back, it calculates the distance between current location and last known location. If I was using the speed, those 5-6 seconds, it wouldn't calculate anything.

But that's why there is the problem when I'm not moving. If you try to show latitude and longitude on display, while I'm standing still, these data variate all the time so that's why it increases odometer all the time. And when there's weak GPS signal, it can vary a lot (from one end of the street to another end of the street) thus creating a 400m travelled distance.

  1. I already have an ADXL345 accelerometer, but I don't know how to use it to detect if I'm moving or not. I'm getting only angle of twist of the device (I done a small game which can be played with accelerometer :slight_smile: ) but nothing changes in data when I'm moving. I tried to get a speed from ax, ay and az acceleration data which I'm getting, but no success.

So the problems are only when not moving. I done yesterday a 15.5 km ride with my bycicle and the error was about 200 meters when comparing to Endomondo tracker on my phone, which I think is very good :). Respectively, my device showed 200 meter more than phone, probably due to these increasements when not moving.

I will also try to play with Neo 6M, I didn't knew that it's possible to tell it whether is pedestrian, bycicle, car etc. Thank you all once again :slight_smile:

I know that GPS is inaccurate at low speeds and that it doesn't work indoors and that's why I'm looking for some mechanism to turn off GPS automatically while I'm not moving and thus preventing weird speed meassurements and incorrent odometer increasing.

You need better filtering and probably some fuzzy logic to ignore "small" movements ("small" being whatever random/error/noise movements you're now getting). You may not need to ignore all small movements, just random small movements over a relatively long period of time. i.e. If you get 5 or 10 small movements, all in the same direction, the readings are probably true.

Yes, I know that I can simply use a "STOP" button which I would press when I finish with my ride and turn off the GPS, but hey, we live in 21st century, these things have to be done automatically, without me pressing the button.

You're the 21st century programmer... :wink:

So I expect the same or better performance than on average smartphone. But I bet they use some smarter algorithms than just calculating distance between 2 locations every 2 seconds.

The phone may use a better algorithm, or it might have a better or faster clock. It's even conceivable that it uses map information to better estimate the road-distance.

I already have an ADXL345 accelerometer, but I don't know how to use it to detect if I'm moving or not.

It doesn't sense "movement", only acceleration & deceleration. If you know you're accelerating at a certain rate in a certain over a certain period of time you can calculate speed and position. If you don't speed-up, slow-down, or change directions, there won't be any more input from the accelerometer and you know you are continuing in the same direction at the same distance. That all works perfectly "on paper", but in the real world any errors accumulate and you get relatively-large errors & noise when when the readings are small (i.e. a little or no acceleration). So it's only good for small corrections in-between GPS readings.

Highly-accurate GPS for land surveying, NASCAR, agriculture, etc., uses a local reference (or maybe more than one local reference) so it doesn't rely solely on satellite information.

XploD:
But, when I finish with my ride, I take the device with me inside the house to charge it and to work further on the project. If I leave it turned on inside the house, it still has some little GPS signal so it "works" but it shows random speeds up 10 km/h and it increases my odometer. So my intentions are not to use it inside the house to meassure speed and distance. I want to prevent it to do such things.

For the "indoor" problem, you could set some threshold on a combination of the number of satellites being tracked, the strength of signal from the satellites, and the relative orientation of the satellites (GDOP - geometric dilution of precision). The GPS may provide a "figure of merit" which is a simple indication of the goodness of it's report based on its evaluation of those parameters. Alternately it may provide an estimate of the position and or velocity error reported and you could set a threshold on those.

Even with knowing the quality of the signal, the location will move around
over a couple meters in several minutes.
One has to set a filter, even when moving that tries to make reasonably
smooth curves.
Going at slow speeds, on a bicycle, I wouldn't expect real good accuracy.
Imagine a drunk walk were you take a few extra steps to the
right or left as you are moving.
This is what the GPS is telling you, even though you are going straight.
The values from the GPS are like a drunk walking.
Before doing much more, first get a feel for the size and rate of this random
location change.
Two lines on a graph showing the X and Y drift over time.
This will give you an idea of how to best create the filter.
Dwight