Brisbane Australia
Offline
Newbie
Karma: 0
Posts: 30
|
 |
« on: January 25, 2013, 06:52:26 pm » |
G'day all,
I'm sure I don't need to tell you I'm a "Newb" because I'm here asking a question!
I've been trying to parse GPS data from a 3G phone module but only when called. The output from the module is formatted as GPSACP and not the generic GPRMC sentence as would be the case with dedicated free running GPS. I have no trouble getting the data from the module as required but without re-inventing the wheel and writing the parsing code myself I can't figure out how to use for example Tiny GPS to simplify the task. Is there a way to get this Library to recognise the GPSACP: sentence from the 3G module? The code below is based on the work of others so I'm confident that with a valid GPRMC sentence output it would work fine.
Any assitance would be greatly appreciated.
Cheers Greg.
// In order for this sketch to work, you will need to download //TinyGPS libraries from arduiniana.org and put them // into the hardware->libraries folder in your ardiuno directory. // Here are the lines of code that point to those libraries.
#include <TinyGPS.h>
TinyGPS gps;
//void getgps(TinyGPS &gps);
void setup() { // This is the serial rate for your terminal program. It must be this // fast because we need to print everything before a new sentence // comes in. If you slow it down, the messages might not be valid and // you will likely get checksum errors. Serial.begin(115200);
Serial.println(""); Serial.println("GPS Test Example Sketch"); Serial.println(""); Serial.println("ATE0"); //turn echo off delay(5000); //wait for 3G module Serial.println("AT$GPSP=1"); delay(5000); //wait for 3G module }
// This is the main loop of the code. All it does is check for data on // the RX pin of the ardiuno, makes sure the data is valid NMEA sentences, // then jumps to the getgps() function. void loop() { Serial.println ("AT$GPSACP"); // Call for GPS data while(Serial.available()) // While there is data on the RX pin... { int c = Serial.read(); // load the data into a variable... if(gps.encode(c)) // if there is a new valid sentence... { getgps(gps); // then grab the data. } } delay(10000); //delay before next loop }
// The getgps function will get and print the values we want.
void getgps(TinyGPS &gps)
{ // To get all of the data into varialbes that you can use in your code, // all you need to do is define variables and query the object for the // data. To see the complete list of functions see keywords.txt file in // the TinyGPS and NewSoftSerial libs. // Define the variables that will be used float latitude, longitude; // Then call this function gps.f_get_position(&latitude, &longitude); // You can now print variables latitude and longitude Serial.print("Lat/Long: "); Serial.print(latitude,5); Serial.print(", "); Serial.println(longitude,5); // Same goes for date and time /*int year; byte month, day, hour, minute, second, hundredths; gps.crack_datetime(&year,&month,&day,&hour,&minute,&second,&hundredths); // Print data and time Serial.print("Date: "); Serial.print(month, DEC); Serial.print("/"); Serial.print(day, DEC); Serial.print("/"); Serial.print(year); Serial.print(" Time: "); Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.print(second, DEC); Serial.print("."); Serial.println(hundredths, DEC); //Since month, day, hour, minute, second, and hundr */ // Here you can print the altitude and course values directly since // there is only one value for the function //Serial.print("Altitude (meters): "); Serial.println(gps.f_altitude()); // Same goes for course Serial.print("Course (degrees): "); Serial.println(gps.f_course()); // And same goes for speed Serial.print("Speed(knots): "); Serial.println(gps.f_speed_knots()); Serial.println(); // Here you can print statistics on the sentences. //unsigned long chars; //unsigned short sentences, failed_checksum; //gps.stats(&chars, &sentences, &failed_checksum); //Serial.print("Failed Checksums: ");Serial.print(failed_checksum); //Serial.println(); Serial.println(); }
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 50
Posts: 6546
Arduino rocks
|
 |
« Reply #1 on: January 25, 2013, 07:03:37 pm » |
Do you have a sample string sent from the device?
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 312
Posts: 35483
Seattle, WA USA
|
 |
« Reply #2 on: January 25, 2013, 07:04:58 pm » |
I have no trouble getting the data from the module as required but without re-inventing the wheel and writing the parsing code myself I can't figure out how to use for example Tiny GPS to simplify the task. You can't. TinyGPS doesn't know about GPSACP mode. Is there a way to get this Library to recognise the GPSACP: sentence Yes. You can add code to TinyGPS to make it parse GPSACP sentences, IF you know what all the values mean.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 9
Posts: 836
|
 |
« Reply #3 on: January 26, 2013, 02:17:04 am » |
If it is a text string in the same manner as the other NMEA GPS sentences, then there isn't much difficulty in adding it as a type of sentence to be processed by the parser.
You basically count the commas, and identify what is between each pair of commas as an integer or floating point number or character code or whatever it is.
On the other hand, it might be something completely different. I don't know.
|
|
|
|
|
Logged
|
|
|
|
|
Brisbane Australia
Offline
Newbie
Karma: 0
Posts: 30
|
 |
« Reply #4 on: January 28, 2013, 06:27:19 pm » |
Gents,
Below is the response from the GPS Module. The string contents are as follows:-
UTC Time , Latitude, Longitude, HDOP, Altitude, Fix, COG, Speed(Km), Speed (Knots), Date, NSAT
I'm interested to know if the changes to Tiny GPS would need to be made in the .h file, or the .cpp file... Or both? (Never edited a library before)... Also, I would expect that simply adding the string definition to those that already exist in the Library would be the best option.
Again, any help greatly appreciated.
Cheers Greg.
$GPSACP:012647.000,2728.3033S,15302.3369E,1.50,-52.0,3,156.66,0.00,0.00,240113,04
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 312
Posts: 35483
Seattle, WA USA
|
 |
« Reply #5 on: January 28, 2013, 06:51:18 pm » |
I'm interested to know if the changes to Tiny GPS would need to be made in the .h file, or the .cpp file... Or both? The source (cpp) file. Look at the source code. It should be fairly simple (and obvious) how to parse a different kind of record.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 50
Posts: 6546
Arduino rocks
|
 |
« Reply #6 on: January 28, 2013, 07:06:10 pm » |
In what form do you want the data and what do you plan to do with it? As a simple parsing start, load the below code into the arduino, copy the sample string you posted, paste the string in the serial monitor (ctrl-v), then send it to the arduino. //zoomkat 3-5-12 simple delimited ',' string parce //from serial port input (via serial monitor) //and print result out serial port // CR/LF could also be a delimiter
String readString;
void setup() { Serial.begin(9600); Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded }
void loop() {
//expect a string like wer,qwe rty,123 456,hyre kjhg, //or like hello world,who are you?,bye!, if (Serial.available()) { char c = Serial.read(); //gets one byte from serial buffer if (c == ',') { //do stuff Serial.println(readString); //prints string to serial port out readString=""; //clears variable for new input } else { readString += c; //makes the string readString } } }
|
|
|
|
|
Logged
|
|
|
|
|
Offline
God Member
Karma: 12
Posts: 898
|
 |
« Reply #7 on: January 28, 2013, 09:16:44 pm » |
|
|
|
|
|
Logged
|
|
|
|
|
Brisbane Australia
Offline
Newbie
Karma: 0
Posts: 30
|
 |
« Reply #8 on: March 18, 2013, 07:24:49 pm » |
Hi all, Sorry for the delay in getting back to this... after studying all your input I've been trying different solutions and have come up with one that seems quite elegant at first glance... Trouble is once incorporated into my complete code it doesn't work. Everything appears fine but in the "real world" situation the variables areeither not being populated, or the results are not being printed to the serial bus. For bothe the simulator and serial monitor run I manually enter the GPS response ($GPSACP: 234423.31,2728.3913S,15302.3418E,1.00,38.81,3,0,00,0.01,0.02,180313,07) into the serial monitor input and the correctly formatted output appears on the output. The Parsing/printing code which works both on an arduino using the serial monitor, and in the simulator is here. #include <avr/pgmspace.h> #define maxLength 80 // Set incoming string max length
String readString; String Lat; String Lon; String COG; String Speed; int ComCount = 0; void setup() { Serial.begin(9600); delay (5000); Serial.println("GPS Test"); Serial.println ("AT$GPSACP"); delay(1000); }
void loop() {
if (Serial.available()) { char c = Serial.read(); //gets one byte from serial buffer if (c ==':') { readString=""; } //delay(1000); if (c == ',') { ComCount++;
if (ComCount == 1) { readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 2) { Lat = readString; readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 3) { Lon = readString; readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 4) { readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 5) { readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 6) { /*if (c += '1') { Fix = 0; } else Fix = 1; */ readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 7) { COG = readString; readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 8) { readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 9) { Speed = readString; readString=""; //clears variable for new input } //delay(1000);
if (ComCount == 10) { readString=""; //clears variable for new input Serial.println ("Lat " + Lat); Serial.println ("Lon " + Lon); Serial.println ("Speed " + Speed + " Knots"); Serial.println ("COG " + COG); ComCount = 0; }
} else { readString += c; //makes the string readString } }
}
----------------------------------------------------------------------------------------------------------- The subroutines I'm actually calling are here... (first section calls the GPS subroutine then should print the data stored in the appropriate variables???) if (inString.indexOf("Locate") >=0) { // look for a command in the string
inString = ""; // Clear the string GPS();
Serial.println ("AT+CMGS=0430340511"); //Send SMS to this number showString(PSTR("Current Location, Course, & Speed\r\n")); Serial.println(""); Serial.println ("Lat " + Lat); Serial.println ("Lon " + Lon); Serial.println ("COG " + COG); Serial.println ("Speed " + Speed + " Knots"); Serial.println ("\x1A"); //Delay to accomodate message send. delay(2000); //Delay to accomodate message send.
inString = ""; // Clear the string
} ------------------------------------------------------------------------------------------------ void GPS() {
delay(1000); Serial.println ("AT$GPSACP"); delay(2000); if (Serial.available()) { char c = Serial.read(); //gets one byte from serial buffer if (c ==':') { readString=""; ComCount = 0; } if (c == ',') { ComCount++;
if (ComCount == 1) { readString=""; //clears variable for new input }
if (ComCount == 2) { Lat = readString; readString=""; //clears variable for new input }
if (ComCount == 3) { Lon = readString; readString=""; //clears variable for new input }
if (ComCount == 4) { readString=""; //clears variable for new input }
if (ComCount == 5) { readString=""; //clears variable for new input }
if (ComCount == 6) { readString=""; //clears variable for new input }
if (ComCount == 7) { COG = readString; readString=""; //clears variable for new input }
if (ComCount == 8) { readString=""; //clears variable for new input }
if (ComCount == 9) { Speed = readString; readString=""; //clears variable for new input }
if (ComCount == 10) { readString=""; //clears variable for new input ComCount = 0; } } else { readString += c; //makes the string readString delay(1000); } } } ---------------------------------------------------------------------- The delays are simply for stability. The GPS/3G module responses are fairly quick but I want reliability over absolute speed. It seems to me that from my testing with the first block of code I've included that perhaps the issue is with the response from the GPS not actually being available on the serial bus??? Other comands that come in via text message are recognised, and in fact the entire sequence is called in this manner. I can also confirm that watching the serial data output from both the arduino and the GPS/3G module the correct calls and responses are present. Cheers Greg.
|
|
|
|
« Last Edit: March 18, 2013, 07:58:37 pm by gregcan »
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 50
Posts: 6546
Arduino rocks
|
 |
« Reply #9 on: March 18, 2013, 07:33:13 pm » |
|
|
|
|
|
Logged
|
|
|
|
|
Brisbane Australia
Offline
Newbie
Karma: 0
Posts: 30
|
 |
« Reply #10 on: March 18, 2013, 08:00:13 pm » |
Thanks for the tip... modified post as suggested.
Cheers Greg
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 312
Posts: 35483
Seattle, WA USA
|
 |
« Reply #11 on: March 19, 2013, 04:55:45 am » |
There is the TinyGPS library that handles parsing GPS data without using crutches (otherwise known as the String class). Why not use it?
Or, at least refer to it to see how parsing is done.
|
|
|
|
|
Logged
|
|
|
|
|
Brisbane Australia
Offline
Newbie
Karma: 0
Posts: 30
|
 |
« Reply #12 on: March 19, 2013, 06:50:18 am » |
Thanks PaulS,
This was discussed at the beginning of the topic. TinyGPS doesn't recognise or handle GPSACP strings natively and I figured it was just as easy (and far more educational) to attack the problem head on.
Cheers Greg.
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 312
Posts: 35483
Seattle, WA USA
|
 |
« Reply #13 on: March 19, 2013, 07:00:14 am » |
I figured it was just as easy (and far more educational) to attack the problem head on. But, at least the TinyGPS library provides a skeleton. Why not add the ability to parse GPSACP sentences to that library? All those Strings coming and going are trashing the limited memory that you have.
|
|
|
|
|
Logged
|
|
|
|
|
Brisbane Australia
Offline
Newbie
Karma: 0
Posts: 30
|
 |
« Reply #14 on: March 19, 2013, 07:13:33 am » |
Thanks PaulS,
So you think the issue could be related to memory?... OK, I'll relook at TinyGPS and see if I can figure out how to add a sentence type to it...
Cheers Greg
|
|
|
|
|
Logged
|
|
|
|
|
|