[solved] Adafruit GPS on Mega crashes due to one line.

[solution in the last post]

Hey! :slight_smile:

I want to use the Adafruit Ultimate GPS Breakout v3 with the Adafruit_GPS library.
I’vve connected an Arduino Mega2560.

I’m using the Hardwareserial due to an overlapping on some vector data storage adress things with the pin_change_int library, which i use for some interrupts on a few analog pins.
Link to an forum post where they discuss this problem.

I tested the module with Softwareserial and everythings worked. But when i switched to Hardwareserial, one line of code made it to crash.

GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);

I tried to test it with the parse.pde example and again, same line caused the crash.

So i think i have three options:

  • Either i use an other library for the interrupts (i cant use the default ones on the mega, because i use them for other sensors like an Adafruit_BNO055).
  • Or we find the solution to the problem with this misterious line.
  • Or I remove the line. Do i really need that line by the way?

Here is the entire code i used to find the line causing the crash. When i comment the line out, everything works just fine.

#include <Adafruit_GPS.h>

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

void setup()
{
  Serial.begin(115200);
  Serial.println("setup");
  
  GPS.begin(9600);
  
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // this line here causes the crash!

  // interrupt things
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);
  
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
}

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

uint32_t timer = millis();

void loop()
{
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA()))
      return;
  }
  
  if (timer > millis())  timer = millis();
  
  if (millis() - timer > 2000)
  { 
    timer = millis();

    // print some data
    Serial.print("\nTime: ");
    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);
  }
}

Thank you for reading all this text!

Do i really need that line by the way?

What is the default update rate? Is that good enough? If so, then, no you don’t need the line.

You would never use SoftwareSerial on a Mega, so you should not have any PinChange interrupt conflicts.

You should use Serial1, not a copy of Serial1. And let’s give it a good name, while we’re at it. Instead of this:

    HardwareSerial mySerial = Serial1;  // a copy!

… use this:

#define gpsPort Serial1

    ...

void setup()
{
    ...

    gpsPort.begin( 9600 );

There are other problems with that library, so I would like to suggest using my NeoGPS. It is smaller, faster and more accurate than all other libraries. Look how short your program can be with NeoGPS:

#include <NMEAGPS.h>

NMEAGPS GPS;
gps_fix fix;
#define gpsPort Serial1

void setup()
{
  Serial.begin(115200);
  Serial.println( F("setup") );
  
  gpsPort.begin(9600);
  
  GPS.send_P( &gpsPort, F("PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0") ); // RMC only
  GPS.send_P( &gpsPort, F("PMTK220,1000") ); // 1HZ

  delay(1000);
}

void loop()
{
  if (GPS.available( gpsPort )) {
    fix = GPS.read();

    // print some data
    Serial.print( F("\nTime: ") );
    if (fix.valid.time) {
      Serial.print  (fix.dateTime.hours  ); Serial.print(':');
      Serial.print  (fix.dateTime.minutes); Serial.print(':');
      Serial.print  (fix.dateTime.seconds); Serial.print('.');
      Serial.println(fix.dateTime_ms()   );
    }
  }
}

Other notes:

* If you only need GPS time, you only need the RMC sentence. See this table to determine what sentences you really need. In this case, GLL would be even better, because it is a shorter sentence (less characters for the Arduino to process).

* The GPS device may not know the time (or location, or altitude…), so you need to make sure that the time is valid before using it. NeoGPS has a flag for each piece of information in a “fix”. The above code checks the fix.valid.time flag before printing the time information.

* You may want to print leading zeroes for some of the pieces:

    if (fix.dateTime.minutes < 10)
      Serial.print( '0' );
    Serial.print(fix.dateTime.minutes);

* It uses the F macro around double-quoted strings to save RAM. (Not the [u]S[/u]tring class! Don’t use String™.)

* You can configure NeoGPS to parse and store only the pieces you really use:

Your original sketch uses 10246 bytes of program space and 1117 bytes of RAM (and a TIMER).
The NeoGPS version uses 4652 bytes of program space and 384 bytes of RAM.

The NeoGPS version uses less than half the program space and one third the RAM, a significant savings.

* Here is a lengthy post about logging GPS, BNO055, wheel speed sensors and steering angle to an SD card at 100Hz. That link is the most recent version of his sketch. If you read through the whole thing, you’ll see that the BNO055 can do 100Hz, but it has some timing issue that we can’t pin down. If you’re using a lower sampling rate, you’ll be fine.

* Unlike other libraries’ examples, the NeoGPS examples programs are structured to take advantage of the GPS quiet time. Many GPS sketches fail because they try to do too much while the GPS is still sending data.

* If you are using other libraries that take a long time to execute, you might lose GPS data while they’re working. The solution is to parse GPS data during the RX character interrupt (see NMEA_isr.ino).

If you want to try the sketch, NeoGPS is available from the Arduino IDE Library Manager, under the menu Sketch → Include Library → Manage Libraries. Even if you don’t try it, be sure to read the Troubleshooting page for other tips for GPS sketches.

Cheers,
/dev

Wow, thank you very much for so much infos!

I accidentally found a simple solution too. As -dev said, i made a copy of Serial1 instead of using Serial1. If i just type in...

Adafruit_GPS GPS(&Serial1);

...instead of...

HardwareSerial mySerial = Serial1;

Adafruit_GPS GPS(&mySerial);

...everything works just fine! I even got a fix inside my house! And it's only off by a few meters!

So thank you for your answers!

bdw: @PaulS i have no idea on what rate its set for default. :/