GPS & Watchdog not cooperating

Hi fellow Arduinoers

I have a GPS that works great, but when I try to include the watchdog timer, I find that it isn’t working as it should. Basically, I would like my GPS to print the time 10 times, and then go to sleep for 8 seconds. Instead, it just keeps printing continuously (without the 8sec delay) the following output:

Setting up…
Adafruit GPS library basic test!
Stopping now.
Going to sleep now
Hello World 1 Time: 3:59:47.0
Stopping now.
Going to sleep now
Stopping now.
Going to sleep now
Hello World 1 Time: 3:59:51.0
Stopping now.
Going to sleep now
Stopping now.
etc etc etc

Below is my code. Does anyone have any thoughts on what might be going on?

#include <avr/sleep.h>
#include <avr/wdt.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO  false

// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

int lines = 10;
int sleeping_cycles = 1; // 1 = 8sec

// watchdog interrupt
ISR (WDT_vect)
{
  wdt_disable();  // disable watchdog
}  // end of WDT_vect


void setup () {
  Serial.begin(9600);
  Serial.println("Setting up...");
  Serial.begin(9600);
  Serial.println("Adafruit GPS library basic test!");
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  GPS.sendCommand(PGCMD_ANTENNA);

  // the nice thing about this code is you can have a timer0 interrupt go off
  // every 1 millisecond, and read data from the GPS for you. that makes the
  // loop code a heck of a lot easier!
  useInterrupt(true);

  delay(1000);
}


// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
  // writing direct to UDR0 is much much faster than Serial.print 
  // but only one character can be written at a time. 
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } 
  else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();


void loop ()
{
  get_values ();   


  // Now, run the watchdog...
  // disable ADC
  ADCSRA = 0; 

  // clear various "reset" flags
  MCUSR = 0;    
  // allow changes, disable reset
  WDTCSR = bit (WDCE) | bit (WDE);
  // set interrupt mode and an interval
  WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
  wdt_reset();  // pat the dog

  set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
  sleep_enable();

  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS);
  sleep_cpu (); 

  // cancel sleep as a precaution
  sleep_disable();
} // end of loop  



void get_values ()
{
  int counter = 0;

  for (int testloop= 0; testloop < lines; testloop++)
  {
    counter = counter + 1;

    // in case you are not using the interrupt above, you'll
    // need to 'hand query' the GPS, not suggested :(
    if (! usingInterrupt) {
      // read data from the GPS in the 'main loop'
      char c = GPS.read();
      // if you want to debug, this is a good time to do it!
      if (GPSECHO)
        if (c) Serial.print(c);
    }

    // if a sentence is received, we can check the checksum, parse it...
    if (GPS.newNMEAreceived()) {
      if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
        return;  // we can fail to parse a sentence in which case we should just wait for another
    }

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

    if (millis() - timer > 2000) { 
      timer = millis(); // reset the timer

      if (GPS.fix) {
        Serial.print("Hello World ");
        Serial.print(counter); 
        delay(100);
        Serial.print("\tTime: ");
        Serial.print(GPS.hour, DEC); 
        Serial.print(':');
        Serial.print(GPS.minute, DEC); 
        Serial.print(':');
        Serial.print(GPS.seconds, DEC); 
        Serial.print('.');
        Serial.println(GPS.milliseconds);
        delay(100);        
      }
    }
  }


  Serial.println("Stopping now.");
  Serial.println("Going to sleep now");
  delay(1000);

}  // end of loop

It seems to me, that doing all that stuff in the interrupt routine is generally a poor idea.

Also, collecting and processing serial data is a relatively slow activity, and uses interrupts, so you are probably getting yourself in the situation where your interrupts are interrupting your interrupts.

If your GPS communication is at 9600 baud, for example, then it is taking around a millisecond to transfer one char/byte from the GPS to the UART on the arduino.