I have a Duemilanove with a Sparkfun GPS shield and a 406A GPS hooked up to it.
I have made some modifications to a sample program that makes a simple UART throughput on the serial line so that it only puts out the RMC sentences. For many applications (ex. logging, datalink) the navigation data in the RMC sentences (time, postition. speed and track) is enough. Make sure the shield's switch is set to UART and not DLINE (for uploading of the code switch needs to be on DLINE).
/*
Example 17.1 UART ONLY - MODIFIED
Display any data coming out of the GPS receiver in the serial monitor box
tronixstuff.com/tutorials > Chapter 17
*/
// as the GPS module sends data out serially, we just pick it up character by
// character and repeat it to the serial output
//Modified bij Robert M. Jaarsma to send only RMC sentences over the serial port.
//May also be used to extract different NMEA sentences.
byte gpsin;
void setup()
{
Serial.begin(4800); // the 406A GPS module runs at 4800 bps
}
void loop()
{
if (Serial.available()>0) // if there is data coming into the serial line
{
gpsin = Serial.read(); // get the byte( or char) of data
}
if (gpsin == 82) //ascii code R(mc)
{
Serial.print("R"); // as R is dropped to get next byte it is printed anyway
while (gpsin != 42) //ascii code *, end of sentence
{
if (Serial.available()>0)
{
gpsin = Serial.read(); // get the byte( or char) of data
Serial.print(gpsin, BYTE); // send it to the serial monitor
}
}
Serial.println("");
}
}
Ammended to reconstruct complete RMC sentence (inclusief checksum) and put it on serial line.
I wanted to see the serial output on Google Earth. This didn't work without the RMC sentence to be complete (maybe GE needs to see the checksum too). Before I had used the * character to note the end of an RMC sentence, later it dawned on me I should let it look for a 'return' (ascii 13) and voila:
GE seems to accept just a RMC sentence. That is already more efficient then receiving and sifting through many more sentences the GPS puts out.
Changed in red:
Serial.print("$GPR"); // as $GPR is dropped to get next byte it is printed anyway
while (gpsin != 13) //ascii code 'return', end of sentence
/*
Example 17.1 UART ONLY - MODIFIED
Display any data coming out of the GPS receiver in the serial monitor box
tronixstuff.com/tutorials > Chapter 17
*/
// as the GPS module sends data out serially, we just pick it up character by
// character and repeat it to the serial output
//Modified bij Robert M. Jaarsma to send only RMC sentences over the serial port.
//Maybe also be used to extract different NMEA sentences.
byte gpsin;
void setup()
{
Serial.begin(4800); // the 406A GPS module runs at 4800 bps
}
void loop()
{
if (Serial.available()>0) // if there is data coming into the serial line
{
gpsin = Serial.read(); // get the byte( or char) of data
}
if (gpsin == 82) //ascii code R(mc)
{
Serial.print("$GPR"); // as $GPR is dropped to get next byte it is printed anyway
while (gpsin != 13) //ascii code 'return', end of sentence
{
if (Serial.available()>0)
{
gpsin = Serial.read(); // get the byte( or char) of data
Serial.print(gpsin, BYTE); // send it to the serial monitor
}
}
Serial.println("");
}
}
Coded to collect all the bytes of one RMC sentence and put them in one string to be send out via serial.
This way (easier) string manipulation can be used on the serial data out and/or have the Arduino act upon extracted data from the string.
/*
Example 17.1 UART ONLY - MODIFIED
Display any data coming out of the GPS receiver in the serial monitor box
tronixstuff.com/tutorials > Chapter 17
*/
// as the GPS module sends data out serially, we just pick it up character by
// character and repeat it to the serial output
//Modified bij Robert M. Jaarsma to send only the $GPRMC sentences as a string over the serial port.
//Could also be modified to extract different NMEA sentences.
byte gpsin;
String stringgps = "$GPR";// as the code looks for the 'R'(RMC)
// the 1st 3 bytes need to be written
// to the string manually to get the $GPRMC sentence header
//complete again
void setup()
{
Serial.begin(4800); // the 406A GPS module runs at 4800 bps
}
void loop()
{
if (Serial.available()>0) // if there is data coming into the serial line
{
gpsin = Serial.read(); // get a byte of data
}
if (gpsin == 82) //ascii code R(mc)
{
while (gpsin != 13) //ascii code 'return', end of sentence
{
if (Serial.available()>0) // if there is data coming into the serial line
{
gpsin = Serial.read(); // get next the byte of data while gpsin != 13
stringgps += gpsin, BYTE;
}
}
Serial.println (stringgps); // when gpsin != 13 NOT true (gpsin == 13) string to serial
stringgps = "$GPR"; //empty string for next sentence
}
}
stringgps += gpsin, BYTE;
Appends the value 'gpsin' to the existing string 'stringgps' as a 'byte' (e.a appending the ascii character code as a character).
If I understand it correctly.. The reason I used it is because it is also in the 'serial.print' command the original example:
byte aa;
aa = Serial.read(); // get the byte of data
Serial.print(aa, BYTE); // send it to the serial monitor
So I figured it is the way to serial.print a byte (ascii code) as a character and then it can also be used to append a character to a string.
Coded to choose which sentence is required to be send over the serial line:
String sentence1 = "$GPRMC"; // enter the sentence identifier that you want to send over serial here
// enter "$" for all sentences over serial
entire program:
/*
Example 17.1 UART ONLY - MODIFIED
Display any data coming out of the GPS receiver in the serial monitor box
tronixstuff.com/tutorials > Chapter 17
*/
// as the GPS module sends data out serially, we just pick it up character by
// character and repeat it to the serial output
//Modified bij Robert M. Jaarsma to send only the $GPRMC sentences as a string over the serial port.
//Could also be modified to extract different NMEA sentences.
byte gpsin;
String stringgps = "$"; // as the code looks for the '
it needs to be added manually again in the string
String sentence1 = "$GPRMC"; // enter the sentence identifier that you want to send over serial here
// enter "$" for all sentences over serial
//String sentence2 = "$GPGGA";
void setup()
{
Serial.begin(4800); // the 406A GPS module runs at 4800 bps
}
void loop()
{
if (Serial.available()>0) // if there is data coming into the serial line
{
gpsin = Serial.read(); // get a byte of data
}
if (gpsin == 36) // ascii code $
{
while (gpsin != 13) //ascii code 'return', end of sentence
{
if (Serial.available()>0) // if there is data coming into the serial line
{
gpsin = Serial.read(); // get the next byte of data while gpsin != 13
stringgps += gpsin, BYTE; // add the latest byte to the string
}
}
if (stringgps.startsWith(sentence1)) // look for $GPRMC (or other sentence entered above)
{
Serial.println (stringgps); // when gpsin != 13 NOT true (gpsin == 13) string to serial
}
stringgps = "$"; //empty string for next sentence, '
stringgps += gpsin, BYTE;
Appends the value 'gpsin' to the existing string 'stringgps' as a 'byte' (e.a appending the ascii character code as a character).
Perhaps you ought to have a look at the comma operator in C. Anyway, the ,BYTE part of that statement isn't doing diddly. The fact that Serial.print(gpsin, BYTE); needs (potentially) the ,BYTE part does not mean that it is useful when appending a character (which is not the same as a byte) to a string. You really should lose the ,BYTE stuff.
Hi Paul, thanks for your feedback. I will read up on the comma operator in C.
In the meanwhile I changed the code to:
stringgps += gpsin;
And it seems to run fine like that.
It looks like the declaration of gpsin can be either char gpsin; or byte gpsin;
full code:
/*
Example 17.1 UART ONLY - MODIFIED
Display any data coming out of the GPS receiver in the serial monitor box
tronixstuff.com/tutorials > Chapter 17
*/
/*
Modified by Robert M. Jaarsma
sends only desired sentences as a string over the serial port.
String can be inspected and/or manipulated before sending it to serial.
Could be usefull for long range (low baudrate) RF modems or with power limited applications.
Can extract different NMEA sentences by entering different sentence identifiers ar begin of the code
at String sentence1 = "$GPRMC";
MAKE SURE SHIELD SWITCH IS SET TO UART, code will not work when DLINE is selected.
However, DLINE does need to be selected when code is uploaded to the board.
After uploading the code to the board set shield to UART and reset de board (reset button on shield).
Without resetting after code upload the UART serial communications to the PC will not work (unless
you reconnect the USB cable).
Revision: 12 jun 2011 13:08 GMT
*/
char gpsin;
String stringgps = "$"; // as the code looks for the '
it needs
// to be added manually again in the string
// SET DESIRED SENTENCE IDENTIFIER HERE, set "$" only for all sentences
String sentence1 = "$GPRMC";
void setup()
{
Serial.begin(4800); // the 406A GPS module puts out serial at 4800 bps
}
void loop()
{
if (Serial.available()>0) // if there is data coming into the serial line
{
gpsin = Serial.read(); // get a byte of data
}
if (gpsin == 36) // ascii code '
{
while (gpsin != 13) // ascii code 'return', end of sentence
{
if (Serial.available()>0) // if there is data coming into the serial line
{
gpsin = Serial.read(); // get the next byte of data while gpsin != 13
stringgps += gpsin; // add the latest byte to the string
}
}
if (stringgps.startsWith(sentence1))// look if string starts with ex. '$GPRMC'
{
Serial.println (stringgps); // when gpsin != 13 NOT true (gpsin == 13)
// send string with complete sentence to serial
}
stringgps = "$"; // empty string for next sentence,
// '
is already added to the string manually here.
//delay (100);
}
}
It looks like the declaration of gpsin can be either
char gpsin;
byte gpsin;
The range of values that can be stored in a char is from -127 to 127. The range of values that can be stored in a byte is 0 to 255. Since the range of values output by the GPS is from 0 to 127, either can be used. This is not always the case, though.
If you need ASCII values greater than 127, for instance, you need to use unsigned char or byte (which have the same range).