MAX GPS Speed

Hi, I'm busy with creating a Speed GPS. I'm using the Ultimate GPS from Adafruit. I want to show to Current Speed, and the MAX Speed. But MAX speed is not working.

Here is the code for the MAX speed.

What is wrong?

  if (GPS.speed > SpeedMax){
    SpeedMax = GPS.speed;
  }
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <U8glib.h>

int SpeedMax;

U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);   

Adafruit_GPS GPS(&Serial);
HardwareSerial mySerial = Serial;


#define GPSECHO  true

boolean usingInterrupt = false;
void useInterrupt(boolean); 

void draw(void) {

  u8g.setFont(u8g_font_unifont);

  if (GPS.fix) {
    u8g.setPrintPos(0, 10); 
    u8g.print("AVG");

    u8g.setPrintPos(0, 22); 
    u8g.print("Max");

    u8g.setPrintPos(0, 34); 
    u8g.print("Speed");

    u8g.setPrintPos(65, 10); 
    u8g.print("XXX");

    u8g.setPrintPos(65, 22); 
    u8g.print(SpeedMax);

    u8g.setPrintPos(65, 34); 
    u8g.print(GPS.speed);
  }

  else{ 
    u8g.setPrintPos(00, 34);
    u8g.print("NO FIX");
  }
}
void setup()  
{

  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");

  GPS.begin(9600);

  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);

  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);  

  GPS.sendCommand(PGCMD_ANTENNA);

  useInterrupt(true);

  delay(1000);

  mySerial.println(PMTK_Q_RELEASE);
}



SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();

#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } 
  else {
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();
void loop()                  
{

  if (GPS.speed > SpeedMax){
    SpeedMax = GPS.speed;
  }

  if (! usingInterrupt) {
    char c = GPS.read();
    if (GPSECHO)
      if (c) Serial.print(c);
  }


  if (GPS.newNMEAreceived()) {

    if (!GPS.parse(GPS.lastNMEA()))  
      return;
  }

  if (timer > millis())  timer = millis();

  if (millis() - timer > 2000) { 
    timer = millis(); 

    if (GPS.fix) {
      Serial.print("Speed (knots): "); 
      Serial.println(GPS.speed);
    }
    u8g.firstPage();  
    do {
      draw();
    } 
    while( u8g.nextPage() );

    delay(500);

  }
}

What does it display?

One thing I noticed: you don't initialize SpeedMax. Personally, I prefer explicit initialization values like this:

int SpeedMax = 0;

Also, I would move the max checking to where a new sentence has been parsed:

  if (GPS.newNMEAreceived()) {

    if (!GPS.parse(GPS.lastNMEA()))
      return;
    // else Good sentence received!
    if (SpeedMax < GPS.speed){  // reordered to match next line...
      SpeedMax = GPS.speed;
    }
  }

Then it won't check on every loop.

Cheers,
/dev

Changed it. But it still isn't working. GPS.speed is displayed as x.xx (2 decimals behind point). But SpeedMax keeps changing and won't display the max. Also is SpeedMax displayed as x (1 decimal).

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <U8glib.h>

int SpeedMax = 0;

U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);	

Adafruit_GPS GPS(&Serial);
HardwareSerial mySerial = Serial;


#define GPSECHO  true

boolean usingInterrupt = false;
void useInterrupt(boolean); 

void draw(void) {

  u8g.setFont(u8g_font_unifont);

  if (GPS.fix) {
    u8g.setPrintPos(0, 10); 
    u8g.print("AVG");

    u8g.setPrintPos(0, 22); 
    u8g.print("Max");

    u8g.setPrintPos(0, 34); 
    u8g.print("Speed");

    u8g.setPrintPos(65, 10); 
    u8g.print("XXX");

    u8g.setPrintPos(65, 22); 
    u8g.print(SpeedMax);

    u8g.setPrintPos(65, 34); 
    u8g.print(GPS.speed);
  }

  else{ 
    u8g.setPrintPos(00, 34);
    u8g.print("NO FIX");
  }
}
void setup()  
{

  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");

  GPS.begin(9600);

  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);

  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);  

  GPS.sendCommand(PGCMD_ANTENNA);

  useInterrupt(true);

  delay(1000);

  mySerial.println(PMTK_Q_RELEASE);
}



SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();

#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } 
  else {
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();
void loop()                  
{

  SpeedMax = 0;

  if (GPS.speed > SpeedMax){
    SpeedMax = GPS.speed;
  }

  if (! usingInterrupt) {
    char c = GPS.read();
    if (GPSECHO)
      if (c) Serial.print(c);
  }


  if (GPS.newNMEAreceived()) {

    if (!GPS.parse(GPS.lastNMEA()))
      return;
    // else Good sentence received!
    if (SpeedMax < GPS.speed){  // reordered to match next line...
      SpeedMax = GPS.speed;
    }
  }


  if (timer > millis())  timer = millis();

  if (millis() - timer > 2000) { 
    timer = millis(); 

    if (GPS.fix) {
      Serial.print("Speed (knots): "); 
      Serial.println(GPS.speed);
    }
    u8g.firstPage();  
    do {
      draw();
    } 
    while( u8g.nextPage() );

    delay(500);

  }
}

You're still setting SpeedMax every time loop is called. And now you're setting it to zero every time, too. Delete lines 96-101:

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <U8glib.h>

int SpeedMax = 0;

U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);	

Adafruit_GPS GPS(&Serial);
HardwareSerial mySerial = Serial;


#define GPSECHO  true

boolean usingInterrupt = false;
void useInterrupt(boolean); 

void draw(void) {

  u8g.setFont(u8g_font_unifont);

  if (GPS.fix) {
    u8g.setPrintPos(0, 10); 
    u8g.print("AVG");

    u8g.setPrintPos(0, 22); 
    u8g.print("Max");

    u8g.setPrintPos(0, 34); 
    u8g.print("Speed");

    u8g.setPrintPos(65, 10); 
    u8g.print("XXX");

    u8g.setPrintPos(65, 22); 
    u8g.print(SpeedMax);

    u8g.setPrintPos(65, 34); 
    u8g.print(GPS.speed);
  }

  else{ 
    u8g.setPrintPos(00, 34);
    u8g.print("NO FIX");
  }
}
void setup()  
{

  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");

  GPS.begin(9600);

  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);

  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);  

  GPS.sendCommand(PGCMD_ANTENNA);

  useInterrupt(true);

  delay(1000);

  mySerial.println(PMTK_Q_RELEASE);
}



SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();

#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } 
  else {
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();
void loop()                  
{

  if (! usingInterrupt) {
    char c = GPS.read();
    if (GPSECHO)
      if (c) Serial.print(c);
  }


  if (GPS.newNMEAreceived()) {

    if (!GPS.parse(GPS.lastNMEA()))
      return;
    // else Good sentence received!
    if (SpeedMax < GPS.speed){  // reordered to match next line...
      SpeedMax = GPS.speed;
    }
  }


  if (timer > millis())  timer = millis();

  if (millis() - timer > 2000) { 
    timer = millis(); 

    if (GPS.fix) {
      Serial.print("Speed (knots): "); 
      Serial.println(GPS.speed);
    }
    u8g.firstPage();  
    do {
      draw();
    } 
    while( u8g.nextPage() );

    delay(500);

  }
}

The reason why SpeedMax displays as "x" is because you declared it as an int. If you want the fractional part, declare it as a float like this:

float SpeedMax = 0.0;

You can see the same declaration of speed in Adafruit_GPS.h. That's where GPS.speed comes from.

Cheers,
/dev

Great, it worked!! With the average. Is it possible with to dmake an average every 10 sec? Then I know how to display the best 10sec average every time.

cekstuffertz:
Is it possible to make an average every 10 sec? Then I know how to display the best 10sec average every time.

I'm not sure what the "best 10sec average" is, but I think what you want is a Moving Average. Then SpeedMax could remember the highest average instead of the highest GPS.speed.

The Simple Moving Average requires you to remember the last 10 speeds. This would require an array of speeds and an index to remember the oldest speed. The index would roll over using modulo arithmetic.

The Cumulative Moving Average is easier to implement because you don't have to remember the last 10 speeds.

The Modified or Running Moving Average is very simple, and very common.

Translating a concept like this into code is a great skill to have, and gets easier as you implement more of them. Let us know if you have any questions.

Cheers,
/dev

I want an average from the lest 10 sec. A 10sec AVG. I tried my best yesterday but it didnt work. So the average would be from the readings from the last 10 sec. This means it changes every 10 sec. But thats what I want. Can you help me? Is there a existing library for something like that?

So every 10s, the average speed updates? Ok, the basic idea is to have a counter that goes from 0 to 9 (we start at zero around here :slight_smile: ), incrementing once for each new speed reading. This means you will do that inside this if statement:

if (GPS.newNMEAreceived()) {

At that time, add the new speed to an accumulator, and increment your counter:

  AccSpeed = AccSpeed + GPS.speed;
  Readings = Readings + 1;

When the Readings counter finally gets to 10, reset the counter, divide your accumulator by 10 to get the average, and reset the accumulator:

  if (Readings == 10) {
    Readings = 0;
    AvgSpeed = AccSpeed / 10.0;
    AccSpeed = 0.0;
  }

Remember to declare the integer Readings and floating-point AccSpeed and AvgSpeed variables somewhere up above, and print the AvgSpeed in your draw routine.

Cheers,
/dev