Asset Tracker GPS -- Your experience with getting GPS fix



I have the Particle Asset Tracker and the GPS performance seems to be terrible – Example if I leave the entire device w/ the enclosure on my dashboard I will often not get a GPS fix at all, or get odd partial fixes where my latitude is reasonable but the longitude is totally off.

My code is painfully simple–
In Setup:

  • .begin()
  • .gpsOn()

In Loop:

  • .updateGPS()
  • if .gpsFix() then print .readLatLon() to serial and delay(1000)
  • If 3600000ms has past since the last serial, print .readLatLon() even if !.gpsFix() (so I get a heart beat once an hour at least)

Today on a perfectly clear day I left the unit on the dash of my car w/ a good view of the sky and all I got were the hourly heartbeats, either with 0,0 lat/lon or and eventually an odd lat/lon combo like 42.036068, 21 or 42.014362, 0.000007 (I’m in Massachusetts so the latitude is possibly about right but the longitude is way off), this was after 6 hours of sitting stationary…

I’m trying to determine if this is just my unit, or if this is generally the experience people are having? There is no way this could operate as any sort of a tracker given how poor the in-built GPS is in my unit.

I’m waiting on an adapter to connect an external SMA GPS antenna, hopefully that will help out.

Thanks for your opinions/advice.

Getting GPS Data from AssetTracker Kit
Asset Tracker - Does not work! [SOLVED]

There is an elaborate thread about this (I’d guess) issue, an the conclusions are that the library would need some updating, but since there are other libraries already, just use them meanwhile.
Default example for Asset Tracker GPS prints erratic NMEA sentences to serial

Some of the side issues and possible solutions regarding serial buffers and such are discussed in the background already.

I’d say the bad results are not due to poor hardware but rather on the software side. Although this might sound like an easy cop-out the library was in big parts just taken from the Arduino library and adapted for Particle. But I’d guess Particle will do some improvements (or replace that lib with the already working one).


Hi ScruffR,

Thanks for link–I found that and started to look over it after my post…

One thing I take away from that is that they seem to be getting output from .preNMEA() and in my case I’m not really getting much.

For example, I’ve changed my code a bit so that I start the GPS and disable Cellular (concerned w/ interference). I think printed the preNMEA output every 2 seconds and I could see the start up output from the GPS and the cold-start commands, but then blank…

So I changed my code a bit to increase delays, now I turn off Cellular and start GPS followed by an initial wait of 10 minutes which followed by a loop of printing preNMEA output and then 5 minutes of delay. I just see blank NMEA.

My GPS is sitting on the outside window ledge with a clear view of a large portion of the sky. I have a relatively ancient Garmin 60 (circa 2003) GPS which can sit 5’ inside the building from that position and still get GPS lock.

I’ve also tried various power supply combinations (USB + LiPo, LiPo only, USB only, external 6V pack only) wondering if that might make some changes (when not using USB I wake the cellular and publish the preNMEA).

I’ve seen a few folks reference adding some caps to improve power supply quality. Is that something that has been factored into the design of the GPS shield? I looked around for a schematic for the shield but couldn’t find one.

For now I’ll assume I don’t have a hardware problem and focus on that thread you linked and see if I can start to grab more detailed GPS data using more than the Asset Tracker library.



I myself haven’t got an Asset Tracker otherwise I could probably give you better advice, but I can give you a link for the schematics

Maybe @Dave (who’s created the Fancy Asset Tracker demo) can help a bit more (once he’s back after weekend).



Thanks, greatly appreciate the schematic–wanted to verify the shield used the same caps and ferrite suggested by the module manufacturer… I assumed it did because the Adafruit break out does, but you never know.

In case @Dave is able to jump in at some point this is where I am now.

My code is very basic, just this:

#include "AssetTracker/AssetTracker.h"

AssetTracker t = AssetTracker();

void setup() {;

void loop() {

The unit is outside on a window ledge of the 2nd floor with a good view of a large part of the sky (it’s night now). It’s powered from USB only, it’s screwed into the bottom half of the enclosure, but the top is off. This is what my output looks like–

*(above repeats ~14 times, about 30 seconds)*

*(above repeats ~20 times, about 40 seconds)*

*(above repeats ~100 times about 3-1/2 minutes)*

*(above repeats 100's of times, maybe 6-7 minutes)*

*(above repeats 100's of times, left it ~10 minutes before I got tired of sitting at the window)*

As I mentioned above this unit did at one point get a fix while I was parked at work (I left it on the dash–sun was not an issue as it was overcast)… but that’s pretty much the ONLY time it has gotten a fix despite days of playing around with it. Additional tries leaving it in the car never got a fix.

I can appreciate the need for some debugging, but at this point I have to assume I’ve got a bad piece of hardware and I’m bashing my head to keep trying to make it work.

Thanks again for your responses and help,


Hello all,

I have build projects with a number of GPS modules over the years, and found the unit on the Asset Tracker does indeed have trouble getting a fix unless conditions are perfect.

My solution was to pick up an active antenna. With this antenna it now works great,

And don’t forget the u.Fl to SMA pigtail cable.


P.s. I am using the the TinyGPS library without issues.


Hi Bill,

I’ve got that antenna on hand, ordered after my first day of limited GPS, sadly I ordered an RP SMA ended adapter with it by accident–oops! Correct adapter is on its way, I’ll try it before attempting hardware return.

Still–it’s a shame this isn’t a better functioning solution. My android tablet that I use as an APRS controller can get good GPS in the car and it has no cellular or WiFi. If an active antenna is what is needed it should have been built on the tracker shield so that eveything is in the weather tight enclosure and we limit our fiddling with external bits and fragile coax :smile:



I’ve had mixed results with the built on antenna. One of my trackers couldn’t get a lock to save its life, the other one connected right up.
An external active antenna fixed the problem


i have ordered an external antenna as i cannot get a gps lock on at all. it’s slightly annoying they are selling a Asset Tracking kit that has an antenna for the GSM part but nothing for the GPS when it seems like it is really needed to get anything useful going.


Hi danr,

I’ve had similar poor results with the external antenna–it’s actually WORSE in some cases.

Since originally posting I was able to get the internal antenna working and I suspect maybe a few other code problems lead me to where I felt it wasn’t working at all when I first posted. As of now sitting on the dashboard of the car it will give me reasonably good results with internal GPS antenna, but that is only I throw out “insane” results with a custom function to discard anything that is >800km from my home operating area.

…but the external antenna is somehow worse because I’ll often get fixes that are 50-60 miles away from where I actually am, there is no good way to determine which results are good vs. bad when they are all in the same general area and the ratio of good to bad results is even enough that you can’t toss out the outlier.

As suspected in this and other threads this may be an issue w/ the Asset Tracker library and how it parses the strings from the GPS. In another Asset Tracker thread the working theory is that there may be an issue w/ the parsing of NMEA strings which results in Asset Tracker library treating bad checksum strings as valid.

Prior to getting my internal antenna working I had contacted Particle support about a possible return/exchange of my GPS shield. I heard back ~3 days later and they told me there is likely nothing wrong with the hardware and that what I have is a library issue. I had gotten my internal antenna working at that point so I tended to agree with them, but it’s a fairly unsatisfying response from Particle all the same.

My opinion is that Particle is doing itself a disservice by not handling this better and solving the Asset Tracker library issues (if they exist) or finding a better hardware offering if this module is a weak link–I say this because they are specifically selling an Asset Tracker kit; it’s not as if this is just a random combination of hardware some users are selecting that we’re asking for support with, we’re asking for support for a product combination that they are selling with a specific purpose which currently it apparently cannot reliably meet for quite a few users.


Just to share some more experience with the Asset Tracker and getting a GPS fix. I have the Asset Tracker and it gets a fix with no external antenna and no coin battery in between 5 to 10 minutes with a good view of the sky. If I walk with the unit under any roof or obstruction in which the view to the sky is even partially blocked, it immediately loses GPS fix and starts blinking red. It seems to need “good” view of the sky without an external antenna to get and maintain a fix.

In terms of accuracy, when I copy the lat/lon results returned via particle.function to the dashboard into google maps, the fix appears accurate to within about 3-4 metres/10-15 feet. ie the google map pin for that lat/lon appears very close to the actual position of the tracker.

I have ordered external antenna and will see how that goes.


I publish my position once every hour, or as fast as every two minutes if the new GPS lat/lon is more than 100m from the last one published.

You’re looking at the most recent 12 hours–the car was only moving for maybe 45 minutes, the rest of the the time it was either near my home or work which are the two circled areas…

The rest are effectively garbage as they don’t even capture the route I drive to/from work.

Also note I didn’t zoom out to show a point or two in NY and RI :smile:

The device was in my car with an external GPS antenna placed on the center of the roof.

If I use the internal antenna it’s actually much better, there are no way off values and most are accurate.

It’s weird how people seem to have such varying degrees of success or failure.


Hey everyone–sorry we’re a little late to the party here. In terms of the performance of the GPS antenna, the tricks we’ve found to be most effective are:

  • The first GPS lock takes the most time. Results are best achieved outside, under an open sky. There are some firmware library tricks that we’re experimenting with to decrease first satellite acquisition time by determining approximately where in the world it’s located based on the available satellites, but haven’t published that code yet. We’ll make that a part of the standard Asset tracker library if we determine it’s helpful. @Dave did a lot of the development here.

  • Purchasing a CR1220 coin cell to use with the Asset Tracker helps a lot–it allows the GPS module to store satellite data in memory, which can reduce the “warm start” acquisition time to less than 10s upon startup. We’re currently considering adding this part to the BOM, since it improves warm start performance of the asset tracker. Link to an Amazon Prime-able CR1220 battery set below:

  • We’re going to be investing in improved documentation for the asset tracker, since it’s turned into a popular item for us, and we recognize that performance varies based on environmental conditions and whether it is first start or not. @mohit is leading the charge here, so I’ll let him chime in if I missed something.

In summary, thanks so much for all this feedback, and apologies if the Asset Tracker wasn’t as intuitive to get going with as our other products. We’re working very hard to improve the firmware and documentation here to make sure that future users have an easier go at things.


Hey guys, thanks for all the feedback!

I agree that the out of box experience for the asset tracker shield isn’t the best right now. This is due to several reasons: lack of complete documentation, un-updated libraries and general expectations with how GPS modules work.

Here are some recommendations to improve the experience:

  1. Use a CR1220 coin cell to retain satellite data and allow warm starts. This brings it (fix) down to under 10 seconds.
  2. Avoid using a USB cable to power the shield - the cable blocks the GPS antenna and results in poor performance
  3. Make sure the battery is fully charged
  4. Use an external antenna if possible

Ideally we would want the GPS to work in tandem with the cellular location so that when it loses sight of the sky, you would still keep getting fairly reasonable location accuracy (this is still in the works). When it comes to instantaneous erroneous readings, it has to be dealt in software with appropriate filtering.

We are keeping track of potential bugs/issues in a repository here:
Please log an issue or offer suggestions. I’m working on the next iteration for the shield in addition to a complete documentation and updated libraries.



First I’d like to say thank you to @mohit, @will and @ScruffR for replying, as well other users–I really do appreciate taking the time to be in the forums and helping out.

A few things–

  • I hope if you decide to respin this shield you’ll consider altering the layout and positioning so that the GPS module isn’t partially covered by the USB connector/cable

  • For me at least, the external antenna has worse results than internal when it comes to a consistent location (not jumping by large distances). I cannot explain it, but it’s certainly true for my unit.

I’m working on some filtering now that involves comparing multiple location results against each other over short periods of time and then comparing the distances between them to decide if it should reject or accept. I’m hopeful that if it works as I expect I should still be able to update my position relatively frequently (my goal is every 2 seconds while moving) but completely eliminating the outlier points that are currently frustrating me.

Once it’s ready I’ll post that part, and the entire sketch if anyone is interested.



I’ve seen some pretty good results so far with my first stab at filtering–I no longer had lots of random hits several km out during the day when the car was parked in the same place.

I should note, I’m using the on-shield antenna as I’ve previous stated my external GPS antenna experience has been poor–possibly due to some issue w/ either the pigtail or antenna itself.

In the code below I’m building up 5 location hits with ~3s delay between each. Over ~15s we are trying to capture a picture of where the GPS is saying we are. If any of the 5 points disagrees with others by more than a certain amount (accounting for movement too) then we consider the cycle bad and don’t allow it to be used. Otherwise it’s considered good and available for use if we happen to be publishing our result on that go around in the loop.

This is built originally off the GPS_Features code found in the AssetTracker library. I’ll define the specific variables and functions I use, but I’ll assume you’ve got the ones that came w/ the AssetTracker already, like ‘t’ for the AssetTracker.

Up in the variable declaration area–

// An array to store several sets of lat/lon
float locations[5][2];

// The time since the GPS location was checked--used as a timer to prevent blocking
// the other loop code from running
unsigned long lastGPS = 0;

// Seconds between checking for GPS location data
int gpsDelay = 3000;

int locationIndex = 0;
bool goodGPS = false;
float goodLat = 0;
float goodLon = 0;

In the loop–

    // Fill the array with 5 positions once t.gpsFix() returns true
    if (t.gpsFix() && (millis() - lastGPS > gpsDelay)){
        locations[locationIndex][0] = t.readDecLat();
        locations[locationIndex][1] = t.readDecLon();
        lastGPS = millis();

    // After 5 locations are recorded, check each against each other for relative distance to decide
    // if we should keep this as a valid location, or toss it out
    if (locationIndex == 5){
        locationIndex = 0;
        goodLat = 0;
        goodLon = 0;
        // Assume goodGPS until we learn otherwise
        goodGPS = 1;
        for (int x = 0; x < 5; x++){
            for (int y = 0; y < 5; y++){
                // if any point is further than 1000m from another let's assume this is a bad
                // Note: at 100MPH you will travel roughly 672m in 15s, so this should handle 
                // most people's asset tracking needs in a moving vehicle up to about 150MPH
                if (distance(locations[x][0], locations[y][0], locations[x][1], locations[y][1]) > 1000){
                    goodGPS = 0;        
            goodLat = goodLat + locations[x][0];
            goodLon = goodLon + locations[x][1];
        // Consider our goodLat,goodLon combination to the average of the last 5 points
        goodLat = goodLat / 5;
        goodLon = goodLon / 5;

Additional functions for calculating distance between points, you need to include Math.h for these–

float distance(float lat0, float lat1, float lon0, float lon1){
    float deltaLat = fabs(lat0 - lat1) * 111194.9;
    float deltaLon = 111194.9*fabs(lon0 - lon1) * cos(radians((lat0 + lat1)/2));
    float distance = sqrt(pow(deltaLat,2) + pow(deltaLon,2));
    return distance;

float radians(float degrees){
    //return (degrees * (3.141593 / 180))
    return ((degrees * 71) / 4068);

I decided to post just these snippets because the rest of my sketch is a bit enormous–I have a ton of other code pulling together data from other sensors, some Particle functions to allow customizing my debug output remotely and changing my timers and other parameters. I also have code related to building up a GET request w/ URL parameters which I’m using with a PHP script to get the data into a MySQL database.

…But the take away is that ‘goodGPS’ indicates that your ‘goodLat’ and ‘goodLon’ values represent consistent positions for last 15 seconds which can help weed out outliers.

That said, one possible problem is that if the GPS data does not change over those 15 seconds you may still get erroneous readings. Increasing the time between checks could help this, but then it’s balancing act in terms of how accurate you want to be and how often you want to publish–you also have to account for motion of the device when collecting points. In my case I was seeing points that were within 5-10km of my actual, so if I were to increase the total time I’m collecting points I’d have to increase the range of the potential legitimate distance I’m traveling which might allow in some of those wrong points.

Some ideas for expansion of this logic:

  • Keep using the 3s timer, but do not consider a point identical to the previous point as new–this will weed out the GPS function reporting the same data multiple times

  • Use the previous goodLat and goodLon values at the start of next cycle as the initial point

  • Averaging your position over time to determine outlier values

The attached screenshot represents my travels today. The large cluster around “Newton” is where I am parked at work. It’s a bit of a jumbled mess at this zoom level but it’s reasonably accurate when zoomed. There are several other points South where I was parked for ~hour each during the day.

Prior to the filtering if I were near a building or other GPS signal blocking object I’d have way off inaccurate dots that would be several km’s off–or maybe even around the globe if the parser misses a negative sign or drops the decimal portion.

Hopefully some of my ideas help others to weed out inaccurate values.

This device is ultimately going on a sail boat that my co-worker bought. In the next few weeks several of us will be sailing it near-shore along about 600 miles of the eastern US coast and we’d like to capture our trip as well as some other data along the way. We’re grabbing water/cabin temperatures, relative humidity, some accelerometer peak values, light levels, etc. This chart above shows the position data, and each point is clickable to reveal the other data collected. I’ve also got some jChart pages to show the data/trends over time for the other values.

Our families can also check the page to see where we are as we move along. I’ve got the cellular radio of the Particle connected to an external antenna which is mounted about 10’ above deck, so it should be able to get signal in marginal conditions where our cellphones are not able.

I’m also feeding a portion of this data to a TNC and VHF transceiver for APRS broadcast to any amateur radio operators who might be receiving along the coast.


Ooh, I should note that I branched AssetTracker library to add the above functions.

The AssetTracker has a readLat and readLon function but they do not return decimal degree values they return decimal minute.

I noticed that the decimal degree values were already being created in the Arduino library so rather than add code to my sketch to convert them back from decimal-minute form I just added a couple of functions to the library to return the data that already exists.


would really like to see more of this code, Very helpful.