Teensy3.6 with TinyGPS, Interrupts

Status
Not open for further replies.

Don Kelly

Well-known member
I have the Ultimate GPS board successfully running on a Teensy3.6 using the tinyGPS (and tinyGPSPlus) library. I'd like to be able to read and parse the lat/long/alt when the PPS signal occurs. Is there a way to do this? The tinyGPS example sketches seem to be polling the chip nearly continuously with this block of code:

start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis()-start<1000);

I'd like the PPS to tell me when the start of a new GPS second is, then I'll read the GPS chip to get lat/long/alt, then I can go off and do other things (like use a Kalman to integrate accel measurements) until the next PPS signal.

Any suggestions or thoughts? Thanks!
 
Was looking this week and I saw this device on Adafruit ? To confirm if you embedded links to the Product / Tutorial and the tinyGPS[+] on Github it would help satisfy the need to:

Always post complete source code & details to reproduce any issue!

AFAIK - the tinyGPS code parses the strings from the GPS and it should have access methods to that parsed data into the desired values.

With usable links a couple of clicks a reader of this thread could confirm that and perhaps find the missing info - or how to get it.
 
I'm getting it to parse just fine. My question is if there is a way to not continually have to poll the GPS to get the GPS data. Can I use the GPS chip's PPS signal as an interrupt to then go and quickly grab the NMEA data. I want to build an integrated INS/GPS, but can't do that if the main loop has to continuously listen for the next GPS NMEA message.
 
That clarifies the OP question ... re post #2 - without links the reader knows less that the poster unless they by some odd chance have worked with this particular setup in this situation, or do some searching to ideally find the actual 'referenced' hardware and software.
 
Good point... I'm using a Teensy 3.6, MPU9250, and the Adafruit Ultimate GPS. I've got the example sketches for the Ultimate GPS (adafruit and tinygps libraries) running just fine, but both seem to require continuous polling of the GPS chip in order to grab the NMEA message. Seems like there should be a way to just grab the NMEA message from the GPS when I want it, like from an interrupt triggered from the GPS's PPS.
 
Rather than waiting 1 second, you could exit the loop when gps.encode() returns true, meaning it has decoded the data.
 
So it is the AdaFruit - does this unit return at 1 Hz or 10 Hz? Still no links. PPS would represent a 1 second PING - may or may not be associated with new data at that instant?
 
That's a good idea, Paul. I might be able to do it that way.

The challenge, I'm thinking, is how do I get very accurate time-stamping for my IMU accel measurements? The accel values will be feeding the Kalman at a fast rate (maybe 50Hz or better) whereas the GPS updates arrive slower (1Hz initially, maybe up to 10Hz). So my thought was to drive the main loop very accurately off of the PPS signal. So when a PPS arrives, I quickly grab accel values and time-stamp them, and then grab the GPS data. Then I can use a 20 millis() loop to keep grabbing 49 more accel values until I get back around to the next PPS signal and start the main loop again.

Guessing there's a smarter way...
 
defragster,
yes the PPS is 1 sec, but should be super accurate sync to GPS time. The Ultimate will supposedly run up to 10Hz, but I'll start at 1Hz until I make sure I get the accel values integrated in correctly (I'll need to get both GPS and accel in a common reference, NED, and then make sure the accel values look right).
 
AFAIK : Installed device firmware determines baud rate and the data return rate. Not seeing the link it isn't clear what the device does when not polled. Though the PPS as a clock will likely be independent of when newest data is returned by the GPS. It seems the string is 56 bytes - again from memory not a link - so that data fits in a Serial port buffer and at 115Kbps can transfer ~200 times per second through the FIFO with no real overhead - so data at 10 Hz parsing if fast would be easy to pull to keep it fresh? An elapsedMillis value with an if() could be used instead of a while().
 
Linked! ... Indeed that is what I was looking at - Now in stock since look in past days. I have a $22 eBay version in my cart.

Odd their page of details doesn't link to TinyGPS.

Would be nice if library asked GPS to transmit serial data - then returned the 4-5ms while the bytes come in over Serial to then be read from buffer.
 
defragster, totally agree. The tinyGPS library seems to do things a bit smarter with his "smartDelay" routine in the sketch examples, but even he still seems to just continuously poll until he gets the data, and then sits there until the 1000ms is up (unless I'm not seeing it correctly).

My strength is more in programming algorithms, so trying to do this timing and interrupt stuff is tough for me! I'm kind of surprised I can't seem to find pretty straight-forward examples or discussions for using GPS (PPS or whatever) to really-accurately time-tag accel values from an IMU and to snag the current GPS NMEA (in the same loop). If I can figure this out, I have all the other pieces of the integrated INS/GPS ready to go (getting raw IMU data, Mahony flter to get PRY, coordinate transformations to NED, Kalman filter, etc).
 
Here are the links for tinygps and tinygpsplus. Both worked fine, i just had to replace softserial with serial3.

tinygpsplus: https://github.com/mikalhart/TinyGPSPlus
tinygps: https://github.com/mikalhart/TinyGPS

My application is the creation of an integrated INS-GPS system. I'll be using a Kalman filter to estimate position and velocity in NED (North East Down) coordinates. The inputs to the Kalman will be accel readings from the MPU9250 and GPS position readings from the Ultimate GPS. At first attempt I'd like to run the Kalman at 10HZ (with accel readings coming in at 10Hz and GPS at 1HZ). If this works, I would step it up to running Kalman at maybe 50Hz (with accel readings at 50Hz and GPS at 5Hz). A key trick is getting very accurate time-tags on the accel measurements (i.e., using GPS).

This is my current thinking on the main loop steps (but there may be a better/easier way!).
1. Use the PPS signal to start the main loop
2. Immediately read accel values (x,y,z) and assign a timetag of xxx.0 seconds (it's xxx.0 because the PPS just occurred). Convert the accel from body to NED coordinates.
3. Read the GPS lat, long, alt values and time. This time value will tell us the "xxx" part for the xxx.0 timetag. Convert lat,long,alt to NED coordinates.
4. Run the Kalman filter with the time-tagged NED accel and GPS inputs to get updated position and velocity.
5. Store to SD card or memory.
6. At even increments of 100ms, repeat steps 2, 4, 5. (i.e., using only accel measurements).
7. End of main loop.

The pieces I haven't figured out is really step 3... how to read the current GPS without constant polling. Step 1 I think I can do with a signal from PPS using while or something similar, step 2 is just a read to the MPU9250, step 4 is a subroutine call, step 5 is using elapsedMillis (I think), and step 6 is a write to SD.

It's a complex challenge, but an interesting one!
 
Good to see the TinyGPS lib used - I'll have to look later.

Serial 1 or 2 is better than #3 as it is backed by the FIFO noted above to minimize xfer overhead.

*trivial - but listed steps mis-ref'd for #5 and #6 ?

Merging the GPS and IMU data stream seems interesting. I just saw the Extended Kalman Filter posting that seems to rely on and relate to GPS data: forum.pjrc.com/threads/48450-uNav-AHRS. I noted this as I was looking at the same GPS - but not parsed any of it yet.

That poster brtaylor has shown what should be a good MPU9250 library as well : forum.pjrc. MPU-9250-Teensy-Library
 
Yes, sorry, I should have said:

"The pieces I haven't figured out is really step 3... how to read the current GPS without constant polling. Step 1 I think I can do with a signal from PPS using while or something similar, step 2 is just a read to the MPU9250, step 4 is a subroutine call, step 5 is a write to SD, and step 6 is using elapsedMillis (I think)."

I'll check out these other references. Thanks. I'm very familiar with EKF techniques, but I'm keeping this simpler with a distributed approach that uses just a standard KF. I think I have a pretty cool approach, so am anxious to get it working in the next month or so.

By the way, this timing issue may be a bit above my head. If I can't figure it out soon, would you perhaps be interested in doing a bit of paid consulting to help me get it going? I think the key to this puzzle (i.e., my confusion) is being able to quickly read the GPS NMEA value when I want to read it, rather than the continuous polling that adafruit_gps and tinygps libraries seem to do (if that's what they're doing, I may have it wrong there). I want to read the accel values as close to the xxx.1 increments so don't want polling going on if it'll interfere with getting the accurate time tags.
 
The challenge, I'm thinking, is how do I get very accurate time-stamping for my IMU accel measurements?

Ah, now that's a very different question!

I'd start by using attachInterrupt for the PPS signal. In the interrupt function, I would limit the code to only reading the mircos() count to a 32 bit integer, and setting a bool to know it's been updated. Of course both of those need to be volatile variables.

Then in the main program, I'd check the bool and when it shows the interrupt has acquired a new microsecond timestamp, I'd use it do update some sort of time post processing calculation done with the rest of the incoming data which arrives much faster than 1 Hz. What exactly that post processing would look like, I'm not sure. But I'm pretty sure limiting the PPS interrupt to just storing micros() and setting a flag is the place to start.

Maybe make that interrupt higher priority at some point, though the default should get you within a few microseconds unless you've got really heavy use of interrupts by some other library.
 
Paul, great thoughts, thx. Do you think using the Time library might work? For example, using GPS to sync the RTC (like in the TimeGPS and TimeTeensy3 examples) and then using the RTC to tell me when to grab the IMU measurements (50 Hz) and the GPS measurement (1Hz)? I haven't tried the RTC, but after reading about it I was thinking it might be an approach that's cleaner than using PPS / interrupts.
 
Status
Not open for further replies.
Back
Top