Interfacing GPS with Arduino Board

Hello all. I am having some problems interfacing a GPS with an Arduino Board and was looking for some help.

Hardware

Arduino Board: Uno
GPS: Garmin 18x PC
RS232 Shield

So far what I have done is:

  1. Upload code to Arduino board.
  2. Place RS232 Shield on top of Arduino board.
  3. Connect Garmin 18x PC to serial port on RS232 Shield.
  4. Open Serial terminal.

I downloaded the TinyGPS library and used the example code that was on there with a few changes (which I highlighted):

#include <TinyGPS.h>
#include <NewSoftSerial.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of NewSoftSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 2(rx) and 3(tx).
*/

TinyGPS gps;
[glow]NewSoftSerial mySerial = NewSoftSerial(0,1);[/glow]

void gpsdump(TinyGPS &gps);
bool feedgps();
void printFloat(double f, int digits = 2);

void setup()
{
  Serial.begin(4800);
  mySerial.begin(4800);
  
  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS));
  Serial.println();
}

void loop()
{
  bool newdata = false;
  unsigned long start = millis();
  
  // Every 5 seconds we print an update
  while (millis() - start < 5000)
  {
    if (feedgps())
      newdata = true;
  }
  
  if (newdata)
  {
    Serial.println("Acquired Data");
    Serial.println("-------------");
    gpsdump(gps);
    Serial.println("-------------");
    Serial.println();
  }
}

void printFloat(double number, int digits)
{
  // Handle negative numbers
  if (number < 0.0)
  {
     Serial.print('-');
     number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;
  
  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  Serial.print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0)
    Serial.print("."); 

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    Serial.print(toPrint);
    remainder -= toPrint; 
  } 
}

void gpsdump(TinyGPS &gps)
{
  long lat, lon;
  float flat, flon;
  unsigned long age, date, time, chars;
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned short sentences, failed;

  gps.get_position(&lat, &lon, &age);
  Serial.print("Lat/Long(10^-5 deg): "); Serial.print(lat); Serial.print(", "); Serial.print(lon); 
  Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");
  
  feedgps(); // If we don't feed the gps during this long routine, we may drop characters and get checksum errors

  gps.f_get_position(&flat, &flon, &age);
  Serial.print("Lat/Long(float): "); printFloat(flat, 5); Serial.print(", "); printFloat(flon, 5);
  Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");

  feedgps();

  gps.get_datetime(&date, &time, &age);
  Serial.print("Date(ddmmyy): "); Serial.print(date); Serial.print(" Time(hhmmsscc): "); Serial.print(time);
  Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");

  feedgps();

  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  Serial.print("Date: "); Serial.print(static_cast<int>(month)); Serial.print("/"); Serial.print(static_cast<int>(day)); Serial.print("/"); Serial.print(year);
  Serial.print("  Time: "); Serial.print(static_cast<int>(hour)); Serial.print(":"); Serial.print(static_cast<int>(minute)); Serial.print(":"); Serial.print(static_cast<int>(second)); Serial.print("."); Serial.print(static_cast<int>(hundredths));
  Serial.print("  Fix age: ");  Serial.print(age); Serial.println("ms.");
  
  feedgps();

  Serial.print("Alt(cm): "); Serial.print(gps.altitude()); Serial.print(" Course(10^-2 deg): "); Serial.print(gps.course()); Serial.print(" Speed(10^-2 knots): "); Serial.println(gps.speed());
  Serial.print("Alt(float): "); printFloat(gps.f_altitude()); Serial.print(" Course(float): "); printFloat(gps.f_course()); Serial.println();
  Serial.print("Speed(knots): "); printFloat(gps.f_speed_knots()); Serial.print(" (mph): ");  printFloat(gps.f_speed_mph());
  Serial.print(" (mps): "); printFloat(gps.f_speed_mps()); Serial.print(" (kmph): "); printFloat(gps.f_speed_kmph()); Serial.println();

  feedgps();

  gps.stats(&chars, &sentences, &failed);
  Serial.print("Stats: characters: "); Serial.print(chars); Serial.print(" sentences: "); Serial.print(sentences); Serial.print(" failed checksum: "); Serial.println(failed);
}
  
bool feedgps()
{  
  while (mySerial.available())
  {
    char serialchar = mySerial.read();
    [glow]Serial.print(serialchar, BYTE);[/glow]
    if (gps.encode(serialchar))
      return true;
  }
  
[glow]float flat, flon;
unsigned long fix_age;

// returns +- latitude/longitude in degrees
gps.f_get_position(&flat, &flon, &fix_age);

if (fix_age == TinyGPS::GPS_INVALID_AGE)
  Serial.println("No fix detected");
else if (fix_age > 5000)
  Serial.println("Warning: possible stale data!");
else
  Serial.println("Data is current.");[/glow]
  
  return false;
}

The output I get is:

Testing TinyGPS library v. 9
by Mikal Hart

Sizeof(gpsobject) = 103

No fix detected
No fix detected
No fix detected
No fix detected
No fix detected
No fix detected
No fix detected

As a side note, I noticed when I started to remove the shield to the point where the Analog In and Power Pins were not connected I got garbage, yet still no fix.

ÿ¿ïÿÿÿNo fix detected
ÿÿùÿÿÿÿNo fix detected
¿ÿÿNo fix detected
þÿ
ÿÿïÿÿNo fix detected
ÿþÿÿÿNo fix detected
ÿÿþþÿÿÿÿNo fix detected
ÿü
ÿÿ¿No fix detected
ÿöÿÿ·÷¿ÿÿþüNo fix detected
ßø÷ÿÿþÿNo fix detected
ÿÿÿÿóúÿßÿÿÿßÿþþÿÿNo fix detected
ÿúÿ
ÿøÿßÿÿÿßÿþþþNo fix detected
ÿúÿ
ÿúÿßÿÿÿßÿþþNo fix detected

Any help to let me know if I am headed in the right direction or if I'm doing something wrong is greatly appreciated.

NewSoftSerial mySerial = NewSoftSerial(0,1);

Pins 0 and 1 are the hardware serial pins. You can't use them for software serial pins.

As a side note, I noticed when I started to remove the shield to the point where the Analog In and Power Pins were not connected I got garbage, yet still no fix.

I sincerely hope you're not stating that you are removing and replacing parts (or wires, or components, or anything else) connected to the Arduino without removing -all- sources of power...?

:-?

If you are: STOP.

Before you do anything with -any- circuit (Arduino controlled or not) - YOU MUST REMOVE ALL SOURCES OF POWER. This is not only to protect the circuit, but to protect yourself as well. Yes, I know at the voltages we are talking about with an Arduino, there isn't much danger. The idea is to get yourself habituated to this, so that in the future, should you find yourself working with circuits and/or voltages that could have lethal consequences by not following the above rule, you will have it ingrained so that it is second nature (saving yourself and/or your family a lot of pain and grief).

:slight_smile:

So would NewSoftSerial not be needed at all then?

I assumed the GPS was transmitting data through pins 0,1 to the Arduino board on the RS232 shield (by looking at connections on the shield). Through which pins would the GPS communicate with the board when using the RS232 shield?

Pins 0 and 1 are the hardware serial pins. You can't use them for software serial pins.

This is not correct. You can use 0 and 1 as software serial, though the use cases are rare. I do this when I'm analyzing timings on the serial port.

Truce, without knowing exactly which shield you are using it's hard to be definitive, but if the data is indeed arriving on 0 and 1 it would be easier to use Serial.

Mikal