GPS Receiver

A GPS receiver can be used to determine a device's location and velocity, as well as the date and time.

There are numerous GPS satellites in orbit around Earth. Each satellite broadcasts one-way radio signals that contain precise satellite location data and time data.

A GPS receiver uses the signals from at least 4 different satellites to calculate its own precise location (latitude and longitude, plus altitude). The GPS receiver can track changes in its location over time to calculate its velocity (speed and direction of motion). It can also verify the precise time and date using the satellite data.

Location data from GPS receivers are not perfectly accurate. Under ideal conditions, a GPS receiver's location data will be accurate to within about 15 feet of the actual location. The GPS accuracy can be affected by factors such as blocked signals, reflected signals, etc. For example, a GPS location is less accurate inside buildings and other structures (and GPS signals might even be blocked). Even outdoors, being near tall structures (buildings, trees, etc.) can reduce GPS accuracy.

The GP-20U7 GPS receiver has a built-in 3-wire female JST connector. If necessary, attach a male JST connector, and plug it into different numbered rows on a breadboard. Then use jumper wires to connect the rows to the Photon. To make it easier to remember which wire is which, use corresponding red, black, and white jumper wires to match the GPS receiver wires.

GPS Receiver

Photon Pin

VCC (Red) - Power

3.3V

GND (Black) - Ground

GND

TX (White) - Data

RX

The GPS receiver will send the GPS data to the Photon board over a serial data connection using the Photon RX pin.

NOTE: For serial data connections, the RX pin of one device connects to the TX pin of the other device. (RX = receive, TX = transmit)

Code for GPS Receiver

#Include Library

Your Photon app must include a code library with special functions that will allow you to use the GPS receiver. There are several possible libraries, but you're going to use one called TinyGPS++:

  1. In Particle Build, click on the bookmark icon to open the Libraries sidebar.

  2. Type "gps" into the search field. Select the result called: TINYGPS++

  3. Click the button to "Include in Project"

  4. Select the name of your Photon app, and then click the "Confirm" button

  5. Particle Build will automatically insert an #include statement at the top of your app code

// This #include statement was automatically added by the Particle IDE.
#include <TinyGPS++.h>

This code library contains special functions that allow you to interact with the GPS receiver.

Global Variables

In your global variables, you need to declare a TinyGPSPlus object variable that you will use to run the special functions in the library. The example below declares an object variable called "gps" (but you could use a different variable name).

// declare TinyGPSPlus object variable called "gps"
TinyGPSPlus gps;

You may also want to declare global variables for the data from the GPS receiver. You only need to include variables for the types of data that your Photon app will actually use. If you want, use can use different names for these variables.

// variables for location data
double latitude, longitude;

// variable for elevation (altitude)
double elevation;

// variables for velocity data
double speed, direction;

setup( ) function

You need to include a statement within the setup() function to start a serial data connection (which will activate both the RX and TX pins on the Photon). This will allow the Photon to receive data from the RFID reader. The GPS receiver communicates at a baud rate of 9600 bps.

Serial1.begin(9600);

Read GPS Measurements

Code for reading GPS measurements should probably be placed within its own custom function, which can then be called within the loop() function.

Before reading new GPS measurements, you must first complete several checks: (1) check to see if new serial data is available, (2) if so, check to see if the serial data can be encoded by the GPS receiver, and (3) if so, does the GPS receiver have valid location data. If all these checks are okay, then the GPS measurements can be read.

The code below shows a custom function called checkGPS() that performs these checks and then reads GPS data (including latitude, longitude, elevation, speed, and direction). The code can be modified to remove any GPS measurements that are not necessary for your Photon app.

void loop() {
    checkGPS();
    // add code to do something with GPS data
}

void checkGPS() {
    while (Serial1.available() > 0) {
        if (gps.encode(Serial1.read())) {
            if (gps.location.isValid()) {
                latitude = gps.location.lat();
                longitude = gps.location.lng();
                elevation = gps.altitude.feet();
                speed = gps.speed.mph();
                direction = gps.course.deg();
            }
        }
    }
}

Inside the loop() function, you will have to insert additional code to do something with the GPS data after it has been read (such as display it on an OLED screen, send the data to your web app, etc.).

TIP: You can use the Google Maps JavaScript API to display a map in your web app using latitude and longitude data. W3Schools has a Google Maps JavaScript API tutorial.

NOTE: When you power on your GPS receiver, it may take a few minutes to establish a valid location, especially if the GPS receiver has traveled some distance or a long time has elapsed since its last use. Also remember that GPS signals can be scattered (or even blocked) inside buildings and other structures. However, under regular usage (and especially if outdoors), the GPS receiver will quickly establish a valid location.

LATITUDE and LONGITUDE

Latitude measures position as an angle (0°-90°) north or south relative to the Equator, which is 0° latitude. The North Pole is 90° N latitude, and the South Pole is 90° S latitude. The GPS receiver will report latitudes north of the Equator as positive numbers, while positions south of the Equator are reported as negative numbers.

Longitude measures position as angle (0°-180°) east or west relative to the Prime Meridian (which was designated as running north-south through Greenwich, England). The GPS receiver will report latitudes east of the Prime Meridian as positive numbers, while positions west of the Prime Meridan are reported as negative numbers.

Locations in the United States will have a positive latitude (north of Equator) and negative longitude (west of Prime Meridian).

TIP: If you want to know the latitude and longitude of a location (so you can compare it to the readings from your GPS receiver), you can enter a specific address at this NASA website to obtain the precise latitude and longitude of that address.

ELEVATION (ALTITUDE)

Elevation (or altitude) measures distance above mean sea level.

The TinyGPS++ library offers the ability to read the elevation (altitude) in feet, miles, meters, or kilometers.

SPEED and DIRECTION

The GPS receiver can determine its speed and direction of travel by tracking changes in its location over time. If the location changes over time, it can determine the distance traveled and then calculate the speed as distance divided by time.

The TinyGPS++ library offers the ability to read the speed in miles per hour, meters per second, kilometers per hour, or knots (nautical miles per hour).

The GPS receiver can also determine the direction of travel (also called "course"). The direction is reported as an angle (0°-360°) measured clockwise relative to true north. For example, a direction of due north is 0°, a direction of due east is 90°, a direction of due south is 180°, a direction of due west is 270°, etc.

NOTE: Even a stationary GPS receiver will report a non-zero speed (usually less than 1 mph). Remember that the GPS receiver's location data is only accurate to within about 15 feet of the actual location. Each new GPS reading will be slightly different even if the GPS receiver is stationary. Because the location readings are "different", the GPS receiver acts as if it were "moving" (which means it has a non-zero speed). This is also why the GPS receiver will report a direction (course), even if it is actually stationary. So just keep in mind that speed calculations will have a small margin of error.

Calculate Distance Between Two Locations

The distance between two GPS locations can be calculated using a haversine formula (used for calculating distance between two points on a sphere).

The example code below introduces a new custom function called getDistance() that calculate the distance (in miles) between the current GPS location and another GPS location. Your code needs to provide the latitude and longitude of the other location.

TIP: For your other location, you can enter a specific address at this NASA website to obtain its precise latitude and longitude.

// global variables for current location
double latitude, longitude;

// global variables for other location
// Example: Indiana University School of Informatics and Computing at IUPUI
double otherLatitude = 39.773931;
double otherLongitude = -86.167524;
double distance;

void loop() {
    checkGPS();
    getDistance();
    // add code to do something with distance
}

void getDistance() {
    // haversine formula for distance between two points on sphere
    float dlat = radians(otherLatitude - latitude);
    float dlon = radians(otherLongitude - longitude);
    float a = sq(sin(dlat/2)) + cos(latitude) * cos(otherLatitude) * sq(sin(dlon/2));
    float c = 2 * atan2(sqrt(a), sqrt(1-a));
    int R = 3959; // mean radius of Earth in miles
    distance = R * c;
}

void checkGPS() {
    while (Serial1.available() > 0) {
        if (gps.encode(Serial1.read())) {
            if (gps.location.isValid()) {
                latitude = gps.location.lat();
                longitude = gps.location.lng();
            }
        }
    }
}

NOTE: The TinyGPS++ library does have a built-in function to calculate the distance (in kilometers) between two GPS locations. However, this library function does not return accurate values due to a mistake in its formula. Instead, use the custom function provided above.

Get Current Date and Time (UTC)

GPS satellites broadcast date and time information in Coordinated Universal Time (abbreviated as UTC). If a device knows its local time zone (which you could figure out using your GPS location), then the UTC data could be converted into a precise local date and time. For example, Eastern Standard Time is 5 hours behind UTC (but Eastern Daylight Time is only 4 hours behind UTC).

If you need date and time information from the GPS receiver, you can declare additional global variables, as shown below.

// variables for date
byte month, day;
int year;

// variables for time
byte hour, minutes, seconds;

Then, within the checkGPS() custom function, you would add the following code to get the UTC date and time.

month = gps.date.month();
day = gps.date.day();
year = gps.date.year();

hour = gps.time.hour();
minutes = gps.time.minute();
seconds = gps.time.second();

NOTE: The Particle firmware on your Photon device already has built-in functions to set the local time zone of your device and get the current date and time. It may be somewhat simpler to use those functions rather than converting the GPS data from UTC into local time.

Last updated