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