I have been using an Adafruit Ultimate GPS with the TinyGPS++ library for about 18 months, in a little speedometer that outputs the speed in MPH onto a seven-segment display.
I have noticed recently that the speed data seems to have some sort of "smoothing" applied to it, where it drifts slowly up and down over time. I was just wondering if anyone could tell me whether this is something that always happens with GPS data itself, or if TinyGPS++ is doing this smoothing. (I don't see any TinyGPS++ code that looks like it's doing it, but I am still pretty new at this). And... is there any way to get direct observations without this smoothing?
I would like to program my own data smoothing to see if I can do it in a way that also allows for a more responsive speedometer number, e.g. when I accelerate from a stop. Currently this smoothing seems to add quite a bit of latency between when my car begins accelerating and when the GPS sends a speed signal for that acceleration.
Thanks for any insights anyone might be able to share!
Here is an example of the NMEA sentences I see (I am focused on the 'knots' field which in the below output is starting at 0.74):
$GPRMC,092000.000,A,4228.3244,N,07125.3676,W,0.74,80.95,060624,,,A*4E
$GPRMC,092000.200,A,4228.3244,N,07125.3675,W,0.75,80.66,060624,,,A*42
$GPRMC,092000.400,A,4228.3244,N,07125.3674,W,0.76,80.41,060624,,,A*43
$GPRMC,092000.600,A,4228.3244,N,07125.3674,W,0.75,80.18,060624,,,A*4E
$GPRMC,092000.800,A,4228.3245,N,07125.3674,W,0.74,79.96,060624,,,A*40
$GPRMC,092001.000,A,4228.3245,N,07125.3673,W,0.73,79.36,060624,,,A*43
$GPRMC,092001.200,A,4228.3245,N,07125.3673,W,0.71,78.32,060624,,,A*46
$GPRMC,092001.400,A,4228.3245,N,07125.3673,W,0.70,76.58,060624,,,A*43
$GPRMC,092001.600,A,4228.3246,N,07125.3672,W,0.69,75.93,060624,,,A*4F
$GPRMC,092001.800,A,4228.3246,N,07125.3671,W,0.68,74.82,060624,,,A*42
$GPRMC,092002.000,A,4228.3247,N,07125.3671,W,0.69,73.19,060624,,,A*4C
$GPRMC,092002.200,A,4228.3247,N,07125.3670,W,0.70,70.58,060624,,,A*41
$GPRMC,092002.400,A,4228.3248,N,07125.3670,W,0.71,68.83,060624,,,A*46
$GPRMC,092002.600,A,4228.3248,N,07125.3669,W,0.72,68.52,060624,,,A*43
$GPRMC,092002.800,A,4228.3248,N,07125.3669,W,0.73,68.32,060624,,,A*4A
$GPRMC,092003.000,A,4228.3249,N,07125.3668,W,0.73,67.86,060624,,,A*43
$GPRMC,092003.200,A,4228.3249,N,07125.3668,W,0.73,67.33,060624,,,A*4F
$GPRMC,092003.400,A,4228.3250,N,07125.3667,W,0.73,67.07,060624,,,A*49
$GPRMC,092003.600,A,4228.3250,N,07125.3666,W,0.72,66.73,060624,,,A*49
$GPRMC,092003.800,A,4228.3251,N,07125.3666,W,0.72,66.20,060624,,,A*40
$GPRMC,092004.000,A,4228.3251,N,07125.3666,W,0.70,65.32,060624,,,A*4D
$GPRMC,092004.200,A,4228.3252,N,07125.3665,W,0.68,65.35,060624,,,A*41
$GPRMC,092004.400,A,4228.3252,N,07125.3665,W,0.66,66.00,060624,,,A*4C
$GPRMC,092004.600,A,4228.3253,N,07125.3664,W,0.65,66.64,060624,,,A*4F
$GPRMC,092004.800,A,4228.3253,N,07125.3663,W,0.65,67.57,060624,,,A*47
$GPRMC,092005.000,A,4228.3253,N,07125.3662,W,0.65,67.24,060624,,,A*4B
$GPRMC,092005.200,A,4228.3254,N,07125.3661,W,0.66,66.45,060624,,,A*48
$GPRMC,092005.400,A,4228.3254,N,07125.3661,W,0.66,65.88,060624,,,A*4C
$GPRMC,092005.600,A,4228.3255,N,07125.3661,W,0.64,65.50,060624,,,A*48
$GPRMC,092005.800,A,4228.3255,N,07125.3661,W,0.63,64.84,060624,,,A*49
$GPRMC,092006.000,A,4228.3256,N,07125.3660,W,0.61,63.99,060624,,,A*49
$GPRMC,092006.200,A,4228.3257,N,07125.3659,W,0.61,63.16,060624,,,A*47
$GPRMC,092006.400,A,4228.3257,N,07125.3658,W,0.61,62.61,060624,,,A*41
If the GPS was giving direct observation numbers for knots, I would expect it to jump around a bit more, e.g. 0.23, 0.75, 0.57, 1.02, 0.13, etc. I had thought it was doing this 18 months ago when I was first working on this project but I don't have any written record of the outputs so I am not 100% sure.
And here is my code:
void feedGPS() {
while (neogps.available()) {
int c = neogps.read();
//#ifdef mydebug
Serial.write(c); // only for debugging
//#endif
if (gps.encode(c)) {
newGPSdata = true;
}
}
}
void loop() {
feedGPS();
if (newGPSdata == true) {
newGPSdata = false;
if (gps.location.isValid()) {
if (gps.speed.isUpdated()) {
if (gpsLock == 0) {
gpsLock = 1;
display.clear();
#ifdef mydebug
Serial.print("acquired GPS signal at "); Serial.println(millis());
#endif
display.showNumberDecEx(currentSpeed, 0b10000000, true, 1, 1);
}
}
}
}
}