I don't know anything about the TinyGPS++ library, but at a guess I'd say you're seeing interrupt reentrance.
Your interrupt handler contains a loop, but doesn't have any limits to ensure the loop will terminate in less than 1ms, and also doesn't block interrupt processing while the loop is running. If a second interrupt comes along while you're still running the loop for the first one, the program's behavior will be undefined.
As a rule, interrupt handlers want to execute as quickly as possible. Set a flag in the interrupt handler if it needs to trigger a long operation, then do the actual processing in the main loop, shutting the interrupts off if possible:
Code: Select all
boolean AVAILABLE = false;
SIGNAL(TIMER0_COMPA_vect) {
if (ss.available() > 0) {
AVAILABLE = true;
}
}
void loop() {
if (AVAILABLE) {
TIMSK0 &= ~_BV(OCIE0A); // shut off interrupts while we're working
while (ss.available() > 0) {
gps.encode(ss.read());
}
Serial.println(gps.location.lat()); // print the results
AVAILABLE = false; // clear the flag
TIMSK0 |= _BV(OCIE0A); // re-enable interrupts
}
}
Even that isn't strictly perfect.. it's possible for an interrupt to arrive between the if() in the main loop and the next line which shuts the interrupts off. That won't cause problems in this specific case because the extra interrupt will just write the same value to the boolean AVAILABLE again. The state of the program will be the same whether the spurious interrupt happens or not, so allowing it to happen is acceptable, but it imposes subtle restrictions on the order of operations.
Writing that section this way would be flat-out wrong, for instance:
Code: Select all
if (AVAILABLE) {
AVAILABLE = false; // clear the flag
TIMSK0 &= ~_BV(OCIE0A); // shut off interrupts while we're working
while (ss.available() > 0) {
gps.encode(ss.read());
}
Serial.println(gps.location.lat()); // print the results
TIMSK0 |= _BV(OCIE0A); // re-enable interrupts
}
A pessimally-timed interrupt could set AVAILABLE back to true before the interrupts get shut off.
Subtleties like that are generally bad, but the art of managing locks to prevent code reentrance is inherently subtle and full of ways to make unexpected mistakes.