Ultimate GPS Parsing with Mega

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
davegun
 
Posts: 89
Joined: Sun Sep 08, 2013 11:00 pm

Ultimate GPS Parsing with Mega

Post by davegun »

I am trying to get the Ultimate GPS to work with the Mega. It works fine with an Uno and not with the Mega. I am using the parsing example (Latest library). I have commented, and uncommented the two lines to use Mega Serial1 and RX1(Pin 19)/TX1(Pin 18).

To troubleshoot this problem, I loaded the blank example and the GPS is working through the Mega serial as it should. I loaded the parsing example (unmodified) on both Uno and Mega and wired the GPS the same to both. I get good serial output from the Uno, but not the Mega. I have two Megas, they both produce the same results.

I expect the first question you have is to see a picture so you can check my soldering and wiring. The problem is I have the GPS installed in a custom 3D printed mini shield made for the Mega so the wiring is not easy to get pictures of. I removed the shield and plugged it into two breadboards to access the pins for the GPS. From the troubleshooting listed above, I found the shield is properly wired and soldering is good because I can make it work with the Uno. The only changes I made between tests are the connection to the Arduinos. I have attached pictures of my testing and the results from the serial monitor.

Any ideas why the GPS is not working with the Mega?

Thanks,
Dave
Attachments
Uno Test Setup and Results
Uno Test Setup and Results
UnoTest_Result.jpg (150 KiB) Viewed 1305 times
Mega Test Setup & Results
Mega Test Setup & Results
MegaTest_Result.jpg (148.21 KiB) Viewed 1305 times
Project Configuration
Project Configuration
Project+.jpg (117.98 KiB) Viewed 1305 times

User avatar
davegun
 
Posts: 89
Joined: Sun Sep 08, 2013 11:00 pm

Re: Ultimate GPS Parsing with Mega

Post by davegun »

I new it had to be something simple. I have used the Ultimate GPS with the Flora and Micro so I looked at my old code and got it to work. Here is my changes to the "Parsing" example to make it work using the Mega Serial1.

Code: Select all

// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver
//
// This code shows how to listen to the GPS module in an interrupt
// which allows the program to have more 'freedom' - just parse
// when a new NMEA sentence is available! Then access data when
// desired.
//
// Tested and works great with the Adafruit Ultimate GPS module
// using MTK33x9 chipset
//    ------> http://www.adafruit.com/products/746
// Pick one up today at the Adafruit electronics shop 
// and help support open source hardware & software! -ada

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

// DAVES MOD - Start //

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

// DAVES MOD - END //



// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences. 
#define GPSECHO  true

// 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

void setup()  
{
    
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");

  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet
  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);
  // Ask for firmware version
  mySerial.println(PMTK_Q_RELEASE);
}


// 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()                     // run over and over again
{
  // 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()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
  
    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 millis() or timer wraps around, we'll just reset it
  if (timer > millis())  timer = millis();

  // approximately every 2 seconds or so, print out the current stats
  if (millis() - timer > 2000) { 
    timer = millis(); // reset the timer
    
    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);
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality); 
    if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", "); 
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
      Serial.print("Location (in degrees, works with Google Maps): ");
      Serial.print(GPS.latitudeDegrees, 6);
      Serial.print(", "); 
      Serial.println(GPS.longitudeDegrees, 6);
      
      Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
    }
  }
}


I still don't know why Software Serial didn't work with the Mega, but I have what I need for my project to work.

Dave

User avatar
Riley_Hosman
 
Posts: 2
Joined: Sat Jul 12, 2014 11:00 am

Re: Ultimate GPS Parsing with Mega

Post by Riley_Hosman »

I spent three days trying to figure this out with my ultimate gps sheild and my mega- Thanks Dave!!! :)

I put a print statement after every command in the in setup().. From those I saw it always fail after one of the GPS.sendCommand() functions, secifically GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); .

Putting in Dave's code fixed this :)

Change:

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

To:

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

I'm not too sharp on C++ classes, but maybe the problem can also be fixed in the adafruit_gps.h file? Maybe something with the #ifdef statements.. Here is the Adaftuit_GPS class the adafruit_gps.h:

Code: Select all

class Adafruit_GPS {
 public:
  void begin(uint16_t baud); 

#ifdef __AVR__
  #if ARDUINO >= 100 
    Adafruit_GPS(SoftwareSerial *ser); // Constructor when using SoftwareSerial
  #else
    Adafruit_GPS(NewSoftSerial  *ser); // Constructor when using NewSoftSerial
  #endif
#endif
  Adafruit_GPS(HardwareSerial *ser); // Constructor when using HardwareSerial

  char *lastNMEA(void);
  boolean newNMEAreceived();
  void common_init(void);

  void sendCommand(const char *);
  
  void pause(boolean b);

  boolean parseNMEA(char *response);
  uint8_t parseHex(char c);

  char read(void);
  boolean parse(char *);
  void interruptReads(boolean r);

  boolean wakeup(void);
  boolean standby(void);

  uint8_t hour, minute, seconds, year, month, day;
  uint16_t milliseconds;
  // Floating point latitude and longitude value in degrees.
  float latitude, longitude;
  // Fixed point latitude and longitude value with degrees stored in units of 1/100000 degrees,
  // and minutes stored in units of 1/100000 degrees.  See pull #13 for more details:
  //   https://github.com/adafruit/Adafruit-GPS-Library/pull/13
  int32_t latitude_fixed, longitude_fixed;
  float latitudeDegrees, longitudeDegrees;
  float geoidheight, altitude;
  float speed, angle, magvariation, HDOP;
  char lat, lon, mag;
  boolean fix;
  uint8_t fixquality, satellites;

  boolean waitForSentence(const char *wait, uint8_t max = MAXWAITSENTENCE);
  boolean LOCUS_StartLogger(void);
  boolean LOCUS_StopLogger(void);
  boolean LOCUS_ReadStatus(void);

  uint16_t LOCUS_serial, LOCUS_records;
  uint8_t LOCUS_type, LOCUS_mode, LOCUS_config, LOCUS_interval, LOCUS_distance, LOCUS_speed, LOCUS_status, LOCUS_percent;
 private:
  boolean paused;
  
  uint8_t parseResponse(char *response);
#ifdef __AVR__
  #if ARDUINO >= 100
    SoftwareSerial *gpsSwSerial;
  #else
    NewSoftSerial  *gpsSwSerial;
  #endif
#endif
  HardwareSerial *gpsHwSerial;
};l
Also I notice the switch needs to be on Soft Serial for it to work. Once it gets started, you can switch it back to direct, however. I'll need to figure this out for my project.

Thanks for the fix Dave.

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”