I've tried using the NewSoftSerial sample code which uses TinyGPS, and there's a few example programs bundled with it. One of them is "test_with_gps_device", and the programming isn't seeming to run right. I've got the EM-408 TX line plugged into pin 2 on the Arduino Mega, and it seems to pick up data properly when I use an RS-232 cable to the computer. help?
Here's the code for it:
#include <NewSoftSerial.h>
#include <TinyGPS.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;
NewSoftSerial nss(2, 3);
void gpsdump(TinyGPS &gps);
bool feedgps();
void printFloat(double f, int digits = 2);
void setup()
{
Serial.begin(115200);
nss.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 (nss.available())
{
if (gps.encode(nss.read()))
return true;
}
return false;
}
What is the exact problem?
How do you know tinyGPS is receiving data from the GPS?
The code will not output data to the PC serial port unless GPS data is received and is also valid data (meaning the GPS has a satellite fix).
I added some code to print various status in an earlier topic in this forum (previous page or two), if this might be what is happening. I was using an LCD, but my code could be modified to print status to the PC serial interface. It prints either no data or that data is not valid...
I also have the GPS hooked up through serial to my computer and can see the GPS data streaming fine. I remove the RX lead to my computer and plug in the RX lead for the Arduino, so it's gotta be getting the same exact data as the computer would. same baud and everything.
After setup and loop, the code goes to if (feedgps). If I place a Serial.print("feedgps"); above while (nss.available()) it prints, but if I place it after while (nss.available()) it doesn't. Obvious debugging leads me to believe nss.available() isn't finding any data somehow?
If your PC can read the serial output from the GPS, then it sounds like the GPS is outputting RS-232 levels (e.g., +12V to -12V). If you are plugging into pin 2 on the Mega, it's expecting TTL levels (0V to 5V).
If this is the case, it can definitely cause receive problems, and may even damage your Arduino hardware.
-Mike
I think the Arduino's expected serial TTL level is 5V.
Your GPS is using low-level TTL Output: 0V~2.85V
Something like this might help:
It is puzzling that your PC is able to read this.
Ah! I know the problem. The Mega uses a different architecture and NewSoftSerial is not compatible with it.
Since you have 4 serial ports, I advise using the one of them to talk to your EM-408. There's really not much call for software serial solutions on the Mega.
Cheers,
Mikal Hart
@mikalhart: you're totally right. I plugged it into RX2 on the board and it started streaming away...strange that NewSoftSerial doesn't play nice with the Mega.
Thanks guys!
I am just about to embark on an Arduino project with the EM-408 GPS module.
@jdumbaugh: powering the EM-408 with 3.3 V is a given, but did you have to convert the Tx and Rx logic levels up to 5 V or did they register with the Arduino anyway? Also, would you recommend tying the enable pin high or have the Arduino pull it high on each read?
Cheers,
Alex