How to read GPS information using the Arduino IDE
In this tutorial we will explore how to utilize the Spresense positioning features from the Arduino IDE in a bit more detail. The built-in Global Navigation Satellite System (GNSS) receiver is one of the main features of the Spresense board, and the Arduino support library is designed to provide easy access to the most commonly used GNSS functionality.
The first two steps of this tutorial will show how to get a very basic application for receiving GPS data up and running. Subsequent steps will expand upon this with guidelines to optimize signal coverage and decrease start-up time.
Step 1: Basic setup for GPS
Initialization of the GNSS module is done by creating an SpGnss object
and calling its begin()
method, which will power on the hardware block and prepare it for positioning. Then, for a basic example that uses GPS only, it is enough to simply call the start method without any parameter in the applications setup:
#include <GNSS.h>
static SpGnss Gnss;
void setup() {
/* Setup serial output for printing. */
Serial.begin(115200);
/* Initialize GNSS. */
Gnss.begin();
Gnss.start();
}
This will make the GNSS module start looking for satellites and, as soon as a fix is attained, produce positioning information.
Note: A “fix” or “lock” is when enough satellites have been located by the receiver to be able to determine its position.
Step 2: Receiving positioning data
To receive positioning data from the receiver in the application’s loop function it is basically just a matter of waiting for some data to be available and then get it:
void loop()
{
/* Wait for an update. */
if (Gnss.waitUpdate(-1))
{
/* Get navigation data. */
SpNavData NavData;
Gnss.getNavData(&NavData);
/* Print position and satellite count. */
Serial.print("Lat=");
Serial.print(NavData.latitude, 6);
Serial.print(", Lon=");
Serial.print(NavData.longitude, 6);
Serial.print(", Satellites=");
Serial.print(NavData.numSatellites);
Serial.println("");
}
}
The waitUpdate() method
will block the application and wait until some data has arrived. The parameter to the method is a timeout determining for how long it should wait if nothing is received, but when set to “-1” it will simply wait forever.
The SpNavData structure
does not only contain position data (latitude, longitude and altitude) but also information about all found satellites and their status. Please see the API reference for a full description.
Step 3: More about update handling
The GNSS module will update its positioning data once every second by default. This update rate can be modified during setup to receive updates more seldom:
void setup() {
Gnss.begin();
Gnss.setInterval(5); /* Update every five seconds. */
Gnss.start();
}
The lowest possible interval is 1 second. It cannot be set to 0, so if no more updates are wanted the GNSS module should be stopped instead.
Instead of blocking the application loop while waiting for an update, there is also the possibility to let the application poll for updated data whenever it needs it. This way you have full control of your application’s flow, but you might not always get the latest updated data depending on how your update interval is set:
void loop()
{
/* Check for an update. */
if (Gnss.isUpdate())
{
/* Get navigation data. */
SpNavData NavData;
Gnss.getNavData(&NavData);
}
}
Note that this is practically the same as calling the waitUpdate()
method with a timeout of 0.
Step 4: Improving coverage
The GNSS module uses GPS by default but it also supports the GLONASS and QZSS positioning with some additional satellite-based augmentation systems. The supported options are:
GPS | Global positioning system built by the United States. |
GLONASS | Global positioning system built by Russia. Slightly less accurate than GPS but can be used together with others to improve positioning data in general. |
SBAS | SBAS (Satellite-Based Augmentation System) is a generic term but in this context it refers to WAAS, a US augmentation system to GPS. It improves GPS positioning greatly but only works in the US. |
QZ_L1CA | The Japanese Quasi-Zenith Satellite System (QZSS) Michibiki transmits positioning signals compatible with GPS L1 C/A signals, which improves positioning in East Asia and Oceania. |
QZ_L1S | Improves accuracy of GPS and QZ_L1CA signals in Japan specifically. |
To, for example, add so that the application also uses GLONASS for positioning, that system has to be added in the setup using the select() method:
void setup() {
Gnss.begin();
Gnss.select(GLONASS);
Gnss.start();
}
Note that this method can be called multiple times in order to select combinations of systems and augmentations.
There is also a corresponding deselect()
method which works in the same way as select()
but stops the GNSS module from using the given option. To check if a specific system is currently selected use isSelecting()
with the given option.
Step 5: Improving startup
When the receiver is first started it will take some time until satellites are found and a position can be determined. This delay is called TTFF (Time To First Fix). By selecting a suitable start mode and supplying initial data to the GNSS module the TTFF can be greatly reduced. Available start modes in the Arduino IDE are:
COLD_START | Start positioning without any previous data. Everything needs to be downloaded from the satellites. |
WARM_START | Use current position, time and almanac. Most of the data is reused but it might take some time to get a fix. |
HOT_START | Use current position, time, almanac and ephemeris. All data is available and a fix can be attained immediately. |
The satellite data, such as position, almanac and ephemeris, are lost when the device enters deep sleep or powers off. To speed up TTFF at next start up, these data can be saved to flash by calling Gnss.saveEphemeris()
. This should only be done when positioning is deactivated. i.e. after calling Gnss.stop()
. The saved data will then be automatically read and used the next time a HOT_START
is triggered. It is recommended to only do this before entering deep sleep or powering off the device to not cause unnecessary wear on the flash memory.
If no mode is specified when calling start()
the GNSS module will try to do use HOT_START
. However, if it is not possible to reuse any data it will fall back to use COLD_START
instead. This could happen if e.g. some time has passed after the data was saved since the data received from the satellite is only valid for a limited time; 2 hours for ephemeris and 90 days for the almanac.
Current time is not included in the backup data. When the module wakes up from being inactive, e.g. from the device wakes up from deep sleep, the new GPS time is calculated using the time elapsed in the Spresense RTC. At boot however, the RTC will be set to 0 so if the approximate time and date (within 60 seconds) is known to the application then it’s good to supply them before initiating a hot start. This is done using the setTime()
method.
It might also be a good idea to set an initial position using setPosition()
if it is believed to give a better approximation than the saved data. Note that setting time and position should be done when the receiver is in idle mode, i.e. before any positioning is started.
# Note that this code is only a conceptual explanation for setting stored time and positioning values.
# The values should probably not be hardcoded.
SpGnssTime current_time;
current_time.year = 2019;
current_time.month = 6;
current_time.day = 25;
current_time.hour = 12;
current_time.minute = 00;
current_time.sec = 00;
current_time.usec = 0;
Gnss.setTime(current_time);
double lat = 55.718272;
double lon = 13.225060;
double alt = 84;
Gnss.setPosition(lat, lon, alt);
Gnss.start(HOT_MODE);
Here are some general things to be aware of when testing your GNSS application:
- The receiver needs to find at least four satellites to be able to determine its position.
- Make sure you have a clear sky. The receiver will have a hard time finding a satellite if there is something blocking the way, such as a roof.
- Try to avoid obstructions around you. Satellites may be positioned low towards the horizon and e.g. buildings with lots of concrete, metal girders etc could block them from the receiver.
- Depending on the conditions and the state of the device it might take minutes to get a fix, so please be patient.