GNSS interface
Global Navigation Satellite System (GNSS) interface in the Modem library is used to control the GNSS module. The interface configures and fetches data from the GNSS module and writes A-GNSS data to the GNSS module.
Note
You need to enable GNSS in modem system mode and activate it in modem functional mode before starting or configuring the GNSS module.
Handling events and reading data from GNSS
To handle events from the GNSS interface, the application needs to implement an event handler function. This function is then called by the interface whenever there is a new event and possibly associated data available.
static struct nrf_modem_gnss_pvt_data_frame pvt_data;
static void gnss_event_handler(int event_id)
{
int err;
/* Process event */
switch (event_id) {
case NRF_MODEM_GNSS_EVT_PVT:
/* Read PVT data */
err = nrf_modem_gnss_read(&pvt_data, sizeof(pvt_data), NRF_MODEM_GNSS_DATA_PVT);
...
}
The event handler function is set by calling the nrf_modem_gnss_event_handler_set()
function.
err = nrf_modem_gnss_event_handler_set(gnss_event_handler);
The event handler is called in interrupt service routine (ISR) context, so processing in the handler should be kept to a minimum.
Data can be read using function nrf_modem_gnss_read()
at any time after receiving the event.
Because there is no buffering for the data, it is overwritten as soon as an event with the same data type is received.
This is not an issue with PVT data, which is updated only once a second, but to receive all NMEA strings, the application needs to read the data inside the event handler.
Starting GNSS
GNSS is started by calling the nrf_modem_gnss_start()
function.
When GNSS is started, the application starts receiving events in the registered event handler function.
err = nrf_modem_gnss_start();
Stopping GNSS
GNSS is stopped by calling the nrf_modem_gnss_stop()
function.
err = nrf_modem_gnss_stop();
Deleting GNSS data stored in NV memory
When GNSS is running, it stores information into non-volatile (NV) memory. GNSS uses this information when GNSS is restarted and also when GNSS starts after a device reboot. It is possible to delete stored data to simulate for example GNSS warm or cold starts. The data to be deleted is selected using a bitmap.
uint32_t delete_mask;
delete_mask = NRF_MODEM_GNSS_DELETE_EPHEMERIDES |
NRF_MODEM_GNSS_DELETE_ALMANACS |
NRF_MODEM_GNSS_DELETE_IONO_CORRECTION_DATA |
NRF_MODEM_GNSS_DELETE_LAST_GOOD_FIX |
NRF_MODEM_GNSS_DELETE_GPS_TOW |
NRF_MODEM_GNSS_DELETE_GPS_WEEK |
NRF_MODEM_GNSS_DELETE_UTC_DATA |
NRF_MODEM_GNSS_DELETE_GPS_TOW_PRECISION;
err = nrf_modem_gnss_nv_data_delete(delete_mask);
Note
TCXO offset is a slowly changing characteristic of each device. It should typically not be deleted when simulating a cold start.
This is considered a debug feature, and is not supposed to be used in production code.
Configuring GNSS
GNSS has various parameters you can use to configure the GNSS behavior. You can only set the configuration options when GNSS is not running.
Operation mode
GNSS supports different operation modes.
The operation mode is configured using functions nrf_modem_gnss_fix_interval_set()
and nrf_modem_gnss_fix_retry_set()
.
The default operation mode is continuous navigation.
Single fix
In single fix mode, the GNSS receiver is on until it has produced a valid PVT estimate. After that, it is automatically switched off.
Even though the GNSS receiver is switched off after producing a fix, the nrf_modem_gnss_stop()
function still needs to be called before GNSS can be started again.
To enable single fix navigation, set the fix interval to 0. If the fix retry parameter is non-zero, GNSS stops after the fix retry time is up if a valid PVT estimate has not been produced. If the fix retry parameter is set to zero, GNSS is allowed to run indefinitely until a valid PVT estimate is produced.
err = nrf_modem_gnss_fix_interval_set(0);
...
err = nrf_modem_gnss_fix_retry_set(180);
System mask
System mask controls which GNSSs are enabled.
The system mask is set using the nrf_modem_gnss_system_mask_set()
function by providing a bitmap of the selected systems.
By default, all supported GNSSs are enabled.
GPS cannot be disabled and it remains enabled even if the corresponding bit is not set.
uint8_t system_mask;
system_mask = NRF_MODEM_GNSS_SYSTEM_GPS_MASK | NRF_MODEM_GNSS_SYSTEM_QZSS_MASK;
err = nrf_modem_gnss_system_mask_set(system_mask);
Satellite elevation threshold
Satellite elevation threshold controls below which elevation angle (degrees above the horizon) GNSS stops tracking a satellite.
The elevation threshold is set using the nrf_modem_gnss_elevation_threshold_set()
function.
The default value is 5 degrees.
err = nrf_modem_gnss_elevation_threshold_set(5);
Use case
The use case configuration is used to enable use case specific features.
The use case bitmask is set using the nrf_modem_gnss_use_case_set()
function.
Start mode
Currently, the only supported start mode is optimized for multiple hot starts.
This is enabled by default and does not need to be set using a function.
However, whenever the nrf_modem_gnss_use_case_set()
function is called, the bit NRF_MODEM_GNSS_USE_CASE_MULTIPLE_HOT_START
should be set.
Low accuracy mode
If low accuracy mode is enabled, GNSS demonstrates a looser acceptance criterion for a fix. The error in position calculation, when compared to the actual position, can be larger than in normal accuracy mode. In addition, GNSS might use only three satellites to determine a fix. In normal accuracy mode, four or more satellites are used.
For a possible position fix using only three satellites, GNSS must have a reference altitude that has low enough uncertainty. The reference altitude is obtained from one of the following sources:
A GNSS fix using five or more satellites.
A-GNSS assistance data - The assistance data is injected to GNSS using the
nrf_modem_gnss_agnss_data_location
A-GNSS data location struct, as shown in the following example code:struct nrf_modem_gnss_agnss_data_location location; location.latitude = latitude; /* Best estimate within maximum limit of 1800 km. */ location.longitude = longitude;/* Best estimate within maximum limit of 1800 km. */ location.altitude = altitude; /* Actual altitude of the device in meters. */ location.unc_semimajor = 127; /* Uncertainty, semi-major. Range 0...127 or 255. */ location.unc_semiminor = 127; /* Uncertainty, semi-minor. Range 0...127 or 255. */ location.orientation_major = 0; /* Set to 0 if unc_semimajor and unc_semiminor are identical values. */ location.unc_altitude = 0; /* Uncertainty, altitude. Range 0...127 or 255. */ location.confidence = 100; /* Set to 100 for maximum confidence. */ err = nrf_modem_gnss_agnss_write(&location, sizeof(location), NRF_MODEM_GNSS_AGNSS_LOCATION);
The struct contains the geodetic latitude, longitude (WGS-84 format), and altitude (in meters) parameters. The uncertainties for the latitude, longitude (unc_semimajor and unc_semiminor), and for the altitude (unc_altitude) are given as an index from
0
to127
, seenrf_modem_gnss.h
for the encoding of the uncertainty fields.The altitude uncertainty must be less than 100 meters (index less than
48
) for it to be valid as a reference altitude. The accuracy of the latitude and longitude are less important, but it must be within 1800 kilometers of the actual location if the coordinates are given. It is also possible to inject only the altitude without a known latitude and longitude. In this case, unc_semimajor and unc_semiminor are set to255
to indicate that latitude and longitude are not valid.
If both verified GNSS fix (five or more satellites used in earlier fix) and A-GNSS assistance data are available, the altitude from the verified GNSS fix is used.
Thus, if GNSS has started in the low accuracy mode, it will not be able to produce fixes using three satellites until it has a reference altitude from one of the mentioned sources. Over time, the uncertainty of the reference altitude increases unless a GNSS fix is obtained using five or more satellites, or altitude assistance is injected to GNSS. See Reference altitude expiration event for GNSS indication of reference altitude expiry.
Note
Calling the nrf_modem_gnss_nv_data_delete()
function with NRF_MODEM_GNSS_DELETE_LAST_GOOD_FIX
bit set clears the reference altitude value.
Important
The altitude must be accurate to a value within ±10 meters of the actual altitude of the device. An erroneous altitude will result in a severe error in the PVT estimation using three satellites.
If the actual altitude of the device changes with respect to the altitude stored in GNSS (for example, when the device moves around), the accuracy of the position fix using three satellites will be degraded.
All fixes, including the low accuracy fixes, are reported as 3D fixes. See the NMEA report sample and number of IDs of SVs used in the position fix to get information of the number of satellites that are used for the position fix.
The low accuracy mode can be enabled as shown in the following example:
uint8_t use_case;
use_case = NRF_MODEM_GNSS_USE_CASE_MULTIPLE_HOT_START | NRF_MODEM_GNSS_USE_CASE_LOW_ACCURACY;
err = nrf_modem_gnss_use_case_set(use_case);
Reference altitude expiration event
GNSS sends the event NRF_MODEM_GNSS_EVT_REF_ALT_EXPIRED
when the reference altitude expires.
This event can be used to trigger a reference altitude update whenever it is needed.
NMEA mask
NMEA mask is used to enable different NMEA string. Multiple NMEA strings can be enabled at the same time.
By default, all NMEA strings are disabled.
All NMEA strings can be enabled as shown in the following example:
uint16_t nmea_mask;
nmea_mask = NRF_MODEM_GNSS_NMEA_GGA_MASK |
NRF_MODEM_GNSS_NMEA_GLL_MASK |
NRF_MODEM_GNSS_NMEA_GSA_MASK |
NRF_MODEM_GNSS_NMEA_GSV_MASK |
NRF_MODEM_GNSS_NMEA_RMC_MASK;
err = nrf_modem_gnss_nmea_mask_set(nmea_mask);
Power saving mode
In continuous navigation, two different power saving modes are available to lower the power consumption. Power saving is implemented as duty-cycling. When GNSS engages duty-cycled tracking, it only tracks for 20% of time and spends the rest of the time in sleep. The different modes control how aggressively GNSS engages duty-cycled tracking, but the duty-cycling itself is the same with both modes.
In the duty-cycling performance mode, duty-cycled tracking is engaged when it can be done without significant performance degradation. In the duty-cycling power mode, duty-cycled tracking is engaged more aggressively with acceptable performance degradation.
The default value is NRF_MODEM_GNSS_PSM_DISABLED
.
err = nrf_modem_gnss_power_mode_set(NRF_MODEM_GNSS_PSM_DUTY_CYCLING_POWER);
Sleep timing source
Timing source used during GNSS sleep periods can be selected between RTC and TCXO. Using TCXO instead of RTC during GNSS sleep periods might be beneficial when used with 1PPS. When GNSS is not running all the time (periodic navigation or duty-cycling is used), 1PPS accuracy can be improved by using TCXO. It may also improve sensitivity for periodic navigation when the fix interval is short.
The default value is NRF_MODEM_GNSS_TIMING_SOURCE_RTC
.
err = nrf_modem_gnss_timing_source_set(NRF_MODEM_GNSS_TIMING_SOURCE_TCXO);
Note
Use of TCXO significantly raises the idle current consumption.
QZSS configuration
GNSS has configuration options that can be used to change the QZSS-related behavior.
NMEA mode
QZSS NMEA mode controls whether QZSS satellites are reported in NMEA strings or not. The NMEA 4.10 standard does not support QZSS satellites, so in the standard NMEA mode, QZSS satellites are not reported in GPGSA and GPGSV sentences. In custom NMEA mode, satellite IDs 193…202 are used for QZSS satellites.
The default value is NRF_MODEM_GNSS_QZSS_NMEA_MODE_STANDARD
.
err = nrf_modem_gnss_qzss_nmea_mode_set(NRF_MODEM_GNSS_QZSS_NMEA_MODE_CUSTOM);
PRN mask
QZSS satellite acquisition and tracking can be configured for each satellite using QZSS PRN mask. Bits 0…9 correspond to QZSS PRNs 193…202 respectively. When a bit is set, using the corresponding QZSS satellite is enabled. Bits 10…15 are reserved and their value is ignored.
The default PRN mask follows the anticipated development of the QZSS constellation and may differ between modem firmware versions.
QZSS PRNs 194, 195, 196 and 199 can be enabled (and others disabled) as shown in the following example:
err = nrf_modem_gnss_qzss_prn_mask_set(0x4e);
Enabling GNSS priority mode
GNSS can be given priority over LTE idle mode procedures to help getting a fix. Usually, this is not necessary when either eDRX or PSM (or both) is used, but if that is not possible, the GNSS priority mode may be used.
Priority for GNSS should be used only when a fix has been blocked by LTE idle mode operations, which can be detected by NRF_MODEM_GNSS_PVT_FLAG_NOT_ENOUGH_WINDOW_TIME
bit being set in the PVT data frame flags member.
The application should not make the decision based on a single PVT event, but should enable priority only in case this flag has been set in several consecutive PVT events.
Priority mode is disabled automatically after the first fix or after 40 seconds.
It can also be disabled by the application by calling the nrf_modem_gnss_prio_mode_disable()
function.
Note
GNSS priority may interfere with LTE operations. If possible, it would be good to time the use of priority to moments where data transfer is not anticipated. In general, eDRX cycles that are long enough, or PSM, ensure better functionality for both GNSS and LTE.
err = nrf_modem_gnss_prio_mode_enable();
Changing the dynamics mode
The dynamics mode describes the dynamics model for the receiver. General purpose mode is suitable for a wide range of applications, but using a dynamics mode tuned for a specific use case improves the positioning performance. The GNSS API lists the maximum receiver speed used for predicting satellite visibility and Doppler frequencies in each mode, and for limiting receiver movement between fixes. However, these are not hard limits and GNSS will continue working at higher speeds, but with sub-optimal predictions and sub-optimal position computation and filtering.
The dynamics mode can be changed without disruption in positioning. The selected dynamics mode is stored into the non-volatile memory.
The default value is NRF_MODEM_GNSS_DYNAMICS_GENERAL_PURPOSE
.
err = nrf_modem_gnss_dyn_mode_change(NRF_MODEM_GNSS_DYNAMICS_AUTOMOTIVE);
1PPS
GNSS can provide time synchronized electrical pulses to the COEX1 pin. The rising edge of the pulse is aligned as closely as possible to the GPS time second.
The pulse interval and width are configurable. It is also possible to configure the pulses to start at a specific date and time. Instead of repeating pulses, 1PPS can also be used in a one-time pulse mode, where only a single pulse is given at the specified time or as soon as GNSS gets a fix.
GNSS only starts giving pulses after it has got at least one fix. After this, the pulses will continue also when GNSS is no longer running, but the precision will start degrading.
In cases where GNSS is not running continuously, it may be beneficial to change the timing source used by GNSS during sleep periods, see Sleep timing source.
1PPS can be enabled or disabled only when GNSS is not running. 1PPS can be enabled with a 1 s pulse interval and 100 ms pulse width as shown in the following example:
struct nrf_modem_gnss_1pps_config config = {
.pulse_interval = 1,
.pulse_width = 100,
.apply_start_time = false
};
err = nrf_modem_gnss_1pps_enable(&config);
Note
The 1PPS feature must not be used when LTE is enabled.
Resolving the UTC time of 1PPS pulse occurrence
As the time of the pulse (aligned to the top of an UTC second) is calculated from the previous valid PVT fix, the latest PVT fix notification needs to be used when resolving the UTC time of the 1PPS pulse. While the 1PPS pulse does not have any time delay, the PVT fix notification will always have some delay, both from the PVT solution calculation (approximately 100 ms) and the notification message delivery. Therefore, the 1PPS pulse may come before the PVT notification that was used to calculate the exact pulse time.
The UTC time of the 1PPS pulse can be calculated using the following formula:
t(PVT,GPST) is the GPS time stamp in the previous PVT notification and Δt is the time difference between the 1PPS pulse and the reception of previous PVT notification:
Thus, Δt is always positive.
A-GNSS data
You can use GNSS assistance data to shorten TTFF and decrease GNSS power consumption. See nRF Cloud A-GNSS and nRF Cloud P-GPS for information how to obtain assistance data from nRF Cloud to be used with the nRF91 Series SiPs.
Determining the assistance data needed by GNSS
The GNSS interface has two methods for getting the current GNSS assistance data need.
A-GNSS data need event
GNSS requests A-GNSS data when GNSS is started for the first time or it determines that the existing data will expire soon.
Whenever A-GNSS data is needed, GNSS sends the NRF_MODEM_GNSS_EVT_AGNSS_REQ
event.
The payload for this event contains information about what kind of data is needed.
When the event is received, the associated payload can be read like this:
struct nrf_modem_gnss_agnss_data_frame agnss_data;
err = nrf_modem_gnss_read(&agnss_data, sizeof(agnss_data), NRF_MODEM_GNSS_DATA_AGNSS_REQ);
After reading the data successfully, the system
array in the struct contains bitmasks sv_mask_ephe
and sv_mask_alm
for each supported system, which indicate the need for ephemerides and almanacs for each satellite in the system.
The data_flags
member is a bitmask for other A-GNSS data.
To prevent triggering assistance data download too often, GNSS sends the NRF_MODEM_GNSS_EVT_AGNSS_REQ
event at most once an hour.
A-GNSS data expiry query
You can use the nrf_modem_gnss_agnss_expiry_get()
function to query assistance data need at any time.
The assistance data need can be read like this:
struct nrf_modem_gnss_agnss_expiry agnss_expiry;
err = nrf_modem_gnss_agnss_expiry_get(&agnss_expiry);
After reading the data successfully, the struct contains expiration times for different types of assistance data.
The sv
array contains ephemeris and almanac expiration times for each GNSS satellite.
The number of satellites in the array depends on the modem firmware.
For older modem firmwares, the array only contains GPS satellites, but from modem firmware v2.0.0 onwards, it also contains QZSS satellites.
The struct also contains expiration times, for example, for Klobuchar ionospheric corrections and satellite integrity assistance.
The data_flags
member contains a bitmask for certain data types, indicating whether the data is currently needed.
Injecting assistance data
A-GNSS data is injected into GNSS using the nrf_modem_gnss_agnss_write()
function.
Each data type has its own struct that is used when A-GNSS data is written to GNSS.
For example, GPS UTC parameters can be written to GNSS as shown in the following example:
struct nrf_modem_gnss_agnss_gps_data_utc utc_data;
/* Populate struct with data */
utc_data.a1 = ...
err = nrf_modem_gnss_agnss_write(&utc_data, sizeof(utc_data), NRF_MODEM_GNSS_AGNSS_GPS_UTC_PARAMETERS);