ULTIMATE GPS BREAKOUT non-interrupt function

Hello, I have bought this item: Adafruit Ultimate GPS Breakout - 66 channel w/10 Hz updates [PA1616S] : ID 746 : $29.95 : Adafruit Industries, Unique & fun DIY electronics and kits

As I see from the libraries it has, it uses interrupts. Is there any way to make it work without interrupts, just using the commands the library has?

360modena_cs:
As I see from the libraries it has, it uses interrupts. Is there any way to make it work without interrupts, just using the commands the library has?

I suppose you could turn the interrupt off, receive serial from the GPS by some non-interrupt method, then you can still call Adafruit_GPS::parseNMEA()

Yours,
TonyWilk

Not that the Adafruit_GPS use of interrupts is good (it's not), is there some reason you don't want to use interrupts?

Regardless, it is quite possible to handle GPS characters without using interrupts. My NeoGPS library has many examples that show how to structure your program correctly. Many people get into trouble when they modify other libraries' examples. Please review the NeoGPS Troubleshooting page for some explanations (e.g., printing too much).

Another common problem is choosing the best serial connection. Many other libraries' examples show the use of SoftwareSerial, which is the WORST software serial library. Better alternatives are listed here.

BTW, NeoGPS is smaller, faster, more accurate and more reliable than all other GPS libraries. If you'd like to try it, it's available from the Ardino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries.

Cheers,
/dev

-dev:
Not that the Adafruit_GPS use of interrupts is good (it's not), is there some reason you don't want to use interrupts?

Regardless, it is quite possible to handle GPS characters without using interrupts. My NeoGPS library has many examples that show how to structure your program correctly. Many people get into trouble when they modify other libraries' examples. Please review the NeoGPS Troubleshooting page for some explanations (e.g., printing too much).

Another common problem is choosing the best serial connection. Many other libraries' examples show the use of SoftwareSerial, which is the WORST software serial library. Better alternatives are listed here.

BTW, NeoGPS is smaller, faster, more accurate and more reliable than all other GPS libraries. If you'd like to try it, it's available from the Ardino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries.

Cheers,
/dev

Yes I want to control the frequency of when the GPS shows me location from commands through Serial, and I cannot do it because it has a fix frequency through interrupts.

I have just used Neo-GPS library but it does not work with adafruit GPS.

I have just used Neo-GPS library but it does not work with adafruit GPS.

Sure it does. Lots of people have used it for that device (an MTK chip). "Doesn't work" is a little vague...

If you read the Installation instructions, you'll see that the examples use AltSoftSerial on an UNO (by default), and the GPS must be on pins 8 & 9. If you have a Mega, Leo or Due, the examples use Serial1 by default (18/19 on a Mega & Due).

If you are using different pins, modify GPSport.h according to the instructions. All the examples will use that same configuration.

I want to control the frequency of when the GPS shows me location from commands through Serial, and I cannot do it because it has a fix frequency through interrupts.

No problem. Just constantly parse the GPS data, but only display the location when the command is received:

#include <NMEAGPS.h>
NMEAGPS gps;
gps_fix fix;

#include <NeoSWSerial.h>
NeoSWSerial gpsPort( 2, 3 );  // AltSoftSerial is better, but requires pins 8 & 9

void setup()
{
  Serial.begin( 9600 );
  gpsPort.begin( 9600 );
}

void loop()
{
  if (gps.available( gpsPort )) {
    fix = gps.read();  // get the latest and save it for later
  }

  // parse commands from Serial
  if (commandReceived()) {
    //  Display the current location
    Serial.print( fix.latitude(), 6 );
    Serial.print( ',' );
    Serial.println( fix.longitude(), 6 );
  }
}

You haven't told us very much, so I'm guessing at a lot of things.

BTW, the GPS spits out its data when it's good and ready. You can't really force it. You could turn all the automatic updates off and then ask for an update, but it won't reply immediately. It could take 2 seconds before you get a complete response. It's better to parse "in the background" so that you always have the latest info, available immediately.

There are some good tutorials to help you write the commandReceived function. Start here. More tutorials in this collection.

Stay away from the String class and delay and it will go much easier for you.

Thank you for the help, I managed to make it work. But I want to ask, is there any way to store fix.latitude() to a variable and fix.longitude() to variable? I tried the easy one:

float lat_,log_;
lat_ = fix.latitude();
log_ = fix.longitude();

Although it compiles, it gives me 0.00 and 0.00 outputs.

is there any way to store fix.latitude() to a variable and fix.longitude() to variable?

Yes, you could store the two pieces in two separate variables. It would be better to store it in a structure of type Location_t:

NeoGPS::Location_t someLocation;

   ...

void loop()
{
    ...

    someLocation = fix.location;
}

You can access the pieces of that structure to get lat and lon:

    Serial.print( someLocation.latF(), 6 );
    Serial.print( ',' );
    Serial.print( someLocation.lonF(), 6 );

Using a Location_t structure will also let you use the distance and bearing calculation functions:

    float distance = someLocation.DistanceKm( fix.location );

If you also want to store other GPS fields, you can declare another gps_fix variable:

gps_fix snapshot;

void loop()
{
    ...

    if (saveCurrent) {
      snapshot = fix; // saves everything: lat,lon,alt,speed,heading,...
    }

    if (checkRange) {
      float distance = snapshot.location.DistanceKm( fix.location );
      if (distance > MAX_RANGE)
        Serial.println( "too far!" );

it gives me 0.00 and 0.00 outputs.

Post your code in code tags: [code]--> your sketch in here --< [/code]

 so it looks
     like this.

I suspect that you are trying to use fix location before your GPS knows the location.

One thing I left out of the code above was checking for location validity:

    //  Display the current location
    if (fix.location.valid) {
      Serial.print( fix.latitude(), 6 );
      Serial.print( ',' );
      Serial.println( fix.longitude(), 6 );
    } else {
      Serial.println( '?' );
    }

Did you run the first example program, NMEA.ino? (Described here.) You will have to make GPSport.h match what your sketch is using.
NMEA.ino will output all the fields it is receiving from the GPS device:

    Status,UTC Date/Time,Lat,Lon,Hdg,Spd,Alt,Sats,Rx ok,Rx err,Rx chars,
    3,2016-05-24 01:21:29.00,472852332,85652650,,138,,,1,0,66,
    3,2016-05-24 01:21:30.00,472852311,85652653,,220,24040,7,9,0,557,
    3,2016-05-24 01:21:31.00,472852315,85652647,,449,24080,7,17,0,1048,

If you don't see lat/lon values in each line, you do not have good satellite reception. Move closer to a window or go outside. The first fix could take 15 minutes or more.

Notice that the first field on each line is a "status". It should start at 0 and eventually get to 3 when it has a location fix. If the status stays at 0, the GPS device is not receiving a clear satellite signal.

Also notice the "Sats" field. That will tell you how many satellites it can "see". In the above example, it can see 7 satellites. The GPS device cannot provide a location until it sees at least 3 satellites.

Cheers,
/dev

Hello!Thank you. The code worked. I use:

 ....

lat_ = fix.latitude();
log_ = fix.longitude();
Serial.print(lat_);
Serial.print( ',' );
Serial.println(log_);

....

But it prints me number with 2 decimal digits, for example: 99.77, I want to print it with 4 or 6 decimal digits... I am looking it. Also I tried NMEA.ino by modified the RX,TX pins in GPSport.h, according to the Arduino I use, but I get:

NMEA.INO: started
  fix object size = 31
  gps object size = 84
Looking for GPS device on Serial1

GPS quiet time is assumed to begin after a RMC sentence is received.
  You should confirm this with NMEAorder.ino

Status,UTC Date/Time,Lat,Lon,Hdg,Spd,Alt,Sats,Rx ok,Rx err,Rx chars,

I keep guessing at solutions for you because

  • I don't know what Arduino you are using
  • I don't know how everything is connected
  • I can't see your sketch.

You should read How to use this forum.

Also I tried NMEA.ino by modified the RX,TX pins

The sketch in Reply #4 shows how to use NeoSWSerial to listen to the GPS on pins 2 & 3 (for an UNO).
The output from NMEA.ino says that it is trying to use Serial1. This implies that you have a Mega, Leo or Due:

  • You can't use NeoSWSerial on pins 2 & 3 of a Mega or Due.
  • You shouldn't use AltSoftSerial, NeoSWSerial or SoftwareSerial on Arduinos that have Serial1.
  • Serial1 would be much better, but you have to connect the GPS to different pins (depends on the Arduino).

Without seeing your sketch and GPSport.h, and knowing what Arduino you have, I can't make a suggestion.

I want to print it with 4 or 6 decimal digits.

I showed you how to print 6 digits after the decimal point in Reply #6.

Thank you...

  1. Is there a way to transform the time I get from GPS to an epoch?
  2. Can I get something less than seconds from GPS, miliseconds for example?
  1. Is there a way to transform the time I get from GPS to an epoch?

Yes. The fix structure contains a nested date/time object (of type NeoGPS::time_t, see NeoTime.h). You can convert this structure to a seconds-from-epoch like this:

    if (fix.valid.date && fix.valid.time) {
      NeoGPS::clock_t seconds = fix.dateTime; // convert structure to seconds offset from epoch

This actually calls a function to "cast" the structure into the seconds type (see [

time_t::operator clock_t()

](NeoGPS/src/NeoTime.cpp at master · SlashDevin/NeoGPS · GitHub)). It will use the epoch selected in NeoTime.h, line 285:

    static const uint16_t s_epoch_year    = Y2K_EPOCH_YEAR;
    static const uint8_t  s_pivot_year    = s_epoch_year % 100;
    static const uint8_t  s_epoch_offset  = s_pivot_year;
    static const uint8_t  s_epoch_weekday = Y2K_EPOCH_WEEKDAY;

As you can see, the default epoch is 2000-01-01 (midnight). If you want a different epoch (e.g., UNIX/POSIX), you can either:

* modify NeoTime.h to use different EPOCH_YEAR/WEEKDAY constants (defined at the top, lines 61-71), or

* use the default NeoTime.h and offset the Y2K seconds by the difference to the other epoch. For example, the offset from POSIX to Y2K is 946,684,800 seconds. Simply add that number from the default Y2K seconds to get a POSIX timestamp:

    if (fix.valid.date && fix.valid.time) {
      NeoGPS::clock_t Y2Kseconds  = fix.dateTime;
      NeoGPS::clock_t UNIXseconds = Y2Kseconds + 946684800UL; // more seconds to older epoch

You can use the inverse functions to set the structure pieces from a UNIX timestamp. If you use the default Y2K epoch:

    NeoGPS::clock_t Y2Kseconds = UNIXtimestamp - 946684800UL; // 
    NeoGPS::time_t  pieces     = Y2Kseconds;

Or, if you modify NeoTime.h to use the POSIX epoch:

    NeoGPS::time_t pieces = UNIXtimestamp;
  1. Can I get something less than seconds from GPS, miliseconds for example?

Yes, if you Enable/disable UTC sub-second resolution. There are two ways that NeoGPS can know the sub-second start of each 1-second interval:

* when characters begin arriving (least accurate), and

* when the PPS pin on the GPS device goes HIGH (most accurate, requires another wire connection between the GPS device and the Arduino, and code to detect the signal).

Then you can either:

* Ask when the current GPS seconds started: gps.UTCsecondStart() (this is relative to the micros() time base), or

* Ask for the current UTC millisecond or microsecond: gps.UTCms() or gps.UTCus().

Thank you. I tried

msec_ = fix.dateTime.UTCms;

but I get:

msec_ = fix.dateTime.UTCms;

^

exit status 1
'struct NeoGPS::time_t' has no member named 'UTCms'

I tried:

msec_ = gps.UTCms;

but i get:

msec_ = gps.UTCms;

^

exit status 1
'class NMEAGPS' has no member named 'UTCms'

So after reading this NeoGPS/Data Model.md at master · SlashDevin/NeoGPS · GitHub

I use:

fix.dateTime_ms(), for milliseconds
fix.dateTime_us(), for microseconds

but when I try to print either msec or usec I get 0. Has anything to do that I have no signal on the GPS yet? But the epoch is printed correctly...

I tried ...

... several things, but not what I suggested in reply #10. Please read it carefully.