I'm happy to announce my new Arduino GPS library TinyGPS. You feed serial data from your GPS device into it like this:
TinyGPS gps;
while (softserial.available())
{
int c = softserial.read();
gps.encode(c);
}
Then, when you want to check your position, say, you do something like this:
long lat, long;
gps.get_position(&lat, &long, NULL);
TinyGPS makes it easy to check speed, time, date, and course, and also has a statistics reporting function. I'd be much obliged if anyone wanted to try it out.
When you look up a variable in the table of variables, you use the name of the variable to get the address of the variables place in system memory, right?
So.. when you look up "lat" you get the address of the place in memory where the value of the variable "lat" can be found.
But, when you then put an & in front of the name "lat", youre asking the microcontroller to deliver the address of the thing right after the &
That is youre asking it to deliver the address of the .... address..?
That doesn't make much sense
Now I've got it all hooked up, but mine keeps claiming my latitude and longitude are both 123456789 ... Is that a default value when the GPS can't get a lock? (me and my GPS are buried in a huge concrete building)
#include "TinyGPS.h"
TinyGPS gps;
void setup() {
Serial.begin(4800);
}
void loop() {
while (Serial.available()) {
int c = Serial.read();
gps.encode(c);
Serial.println("oh no, I'm never gonna exit this while loop");
}
long latitude, longitude;
gps.get_position(&latitude, &longitude, NULL);
Serial.print("Latitude: "); Serial.println(latitude);
Serial.print("Longitude: "); Serial.println(longitude);
}
Now I've got it all hooked up, but mine keeps claiming my latitude and longitude are both 123456789 ... Is that a default value when the GPS can't get a lock? (me and my GPS are buried in a huge concrete building)
Your code looks valid, although be advised that most GPS units take several seconds up to 2-3 minutes to "lock in" for the first time. Until then, lat/long will be returned as TinyGPS::GPS_INVALID_ANGLE, which is currently defined for readability as 123456789 (although this may change).
If you are "buried" in a concrete building, my guess is that your GPS isn't getting a fix.
Running your example project unmodified, I receive this on the Serial monitor:
Testing TinyGPS library v. 6
by Mikal Hart
Sizeof(gpsobject) = 103
This is regardless of whether I plug in the pins before or after uploading your example to my Arduino.
I plug the pin delivering the NMEA-sentences into port 2 on the arduino (not the analog pin2 ;)) and the RX-pin from my GPS into port 3.
Sounds like the connection to the unit is fine, but be aware that the unit will send a nice stream of NMEA sentences even when it doesn't have a fix. One thing you might do is periodically call TinyGPS::stats like this:
unsigned long chars;
unsigned short sentences, failed_checksum;
gps.stats(&chars, &sentences, &failed_checksum);
This will return
chars - the number of characters fed to the object
sentences - the number of valid $GPGGA and $GPRMC sentences processed
failed_checksum - the number of sentences that failed the checksum test
This will tell you what's wrong.
Edit: If you have hooked up your GPS to the hardware serial port -- and it looks as if you have -- just modify the test_gps2 sample accordingly.
Edit2: The "sizeof" message is just showing how much RAM the TinyGPS object is consuming.
Edit3: If you are getting a "nice stream" of NMEA characters, but still no fix from TinyGPS, send me a sample of the stream and I can take a look.
Moving the GPS unit to the window pane made your script work.
Mine still doesn't work. When I upload it it starts printing 123456789 for lat and long continiously, and when i then plug in the TX line from the GPS, it says: "In the while loop. Oh no, I'm never gonna exit this while loop" continiously:
#include "TinyGPS.h"
TinyGPS gps;
void setup() {
Serial.begin(4800);
}
void loop() {
while (Serial.available()) {
Serial.print("In the while-loop. ");
int c = Serial.read();
gps.encode(c);
Serial.println("Oh no, I'm never gonna exit this while loop");
}
long latitude, longitude;
gps.get_position(&latitude, &longitude, NULL);
Serial.print("Latitude: "); Serial.println(latitude);
Serial.print("Longitude: "); Serial.println(longitude);
unsigned long chars;
unsigned short sentences, failed_checksum;
gps.stats(&chars, &sentences, &failed_checksum);
}
The code is more or less a copy of the short example you gave in the first posting in this thread, so I don't really know whats wrong.
I ofcourse use pin0 for my script and pin2 for your script.
The GPS has had a fixation. I can deduce that from the position your script outputted.
The problem is your case is that you never exit the "while (Serial.available())" loop. It takes a LONG time to print "Oh no. I'm never gonna exit this while loop", and that becomes a self-fulfilling prophecy. By the time you finish printing, another bunch of characters have arrived, making Serial.available() nonzero.
Remove the 2 calls to Serial.print() and Serial.println() from your inner loop.
Do you also have an explanation for the question I raised in reply #4 in this thread?
Sure... In C it's pretty common practice to write information-gathering functions this way, especially if the function is returning more than one value. Functions like get_position(), which returns a "latitude", a "longitude" and a "fix_age", must know where to store the results, and that's why you have to pass the address of the variables and not just the variables themselves. Since C functions are "call by value", calling gps.get_position(latitude, longitude, fix_age) would tell the gps object what the current values for these variables are, but not give it a way to modify them. That's why you prefix them with the & ("address of") operator.
EDIT: Let's do an example. Let's say your latitude is 490000 (49 degrees) and it's stored in a variable in RAM with address 226. If you wrote gps.get_position(latitude, ...) the compiler would send 490000 to the gps object. This isn't useful, because gps wants to know where to store the new latitude. But if you write gps.get_position(&latitude, ...), the compiler sends 226, which is exactly what gps needs.
And if it realises that the checksum for a particular observation has failed, will it skip that observation?
Yes, it's completely discarded. I don't want you angry with me when your Arduino helicopter crashes into the Kremlin because of bad data.
That makes perfect sense.
So, this is my interpretation of variable-fetching:
When using a variable, the computer looks up the variable name in the symbol table, thereby getting the address in memory where the value of this variable can be found. Then it looks up this address in memory and fetches the value found there. Then it returns this value.
When using a variable, AND, an & is put in front of the name, the computer looks up the variable name in the symbol table, thereby getting the address in memory where the value of this variable can be found. This address is then returned directly, without looking anything up in system memory (the stack? the heap? ..where is values of variables stored?).
Where a variable lives depends on how you declared it. If it's outside of a function, it's in global/static memory. If it's inside a function it's on the stack. If you used malloc or new to dynamically allocate it, it's on the heap.
Would it be possible to embed the following code in a function that were only called when data actually were available at the serial port, using interrrupts? Else I would have to call the function rather often, just to see if new data is available.
while (softserial.available())
{
int c = softserial.read();
gps.encode(c);
}
My application is embedding waypoint navigation in a rc boat, so that's why the time-perspective is important here.
Under normal conditions the GPS will constantly be sending data, so you would be getting interrupts much more frequently than you actually need.
If you are using the interrupt driven soft serial library then you only need to read data out of the buffer a few times a second depending on how many sentences are sent by your gps. The actual rate is dependent on the number of characters in the sentences you receive every second and the size of the buffer (its 64 byte by default in afSoftSerial).
If you look at the tinyGPS example sketch you can see how to use the gps.states function to get the number of sentences and number of stats. If you run the sketch over a known number of seconds you can figure out how quickly you need to read the data to prevent the 64 byte buffer overflowing.
You could of course increase the buffer size, or use the hardware serial if that is not being used for something else.
Can you structure your code so that you can process gps data a few times a second in your main loop? If you need help doing this, perhaps start a discussion in new thread, this one was a general announcement on the availability of the tinyGPS library.