IoT at the Edge, GNSS Programming

Getting under the hood of GPS

There’s a lot more to GPS than you think

For a start, the correct term is GNSS, Global Navigation Satellite System, GPS is used to refer to the US system, which is actually called NAVSTAR. There are five other GNSS nation operated systems:

  • GLONASS (Russia)
  • Galileo (European Union)
  • BeiDou (China)
  • NavIC (India)
  • QZSS (Japan)

The NavIC and QZSS systems from India and Japan do not have global coverage. Almost all GNSS chipsets used today are capable of receiving data from all these systems. Therefore, depending where you are in the world, your phone or SatNav may be using one more more of these GNSS systems. I suspect a lot of phone and SatNav users probably do not realise this. In reality, Governments often restrict which systems are allowed in each country. For example, in the US, unsuprisingly, NAVSTAR is the only permitted licensed system for phone and SatNavs sold. Though at the time of writing, the EU is currently lobbying the US to permit the use of Galileo.

Each of these systems run in different classes of orbit and numbers of satellites. The figure below attempts to illustrate the different system orbits.

The Wio LTE IoT board I’m using for my project has a Quectel EC21 combined LTE GNSS modem connected to the STM32 via Serial UART. What’s great about having this Wio LTE is that you have full access to all the features of the Quectel EC21, this includes all six GNSS environments with no restrictions. There are advantages to being able to connect to one or more of the GNSS environment to improve your position accuracy.

So how do you talk to different GNSS systems?

Well luckily, there is an international messaging standard for GNSS called NMEA - the National Marine Electronics Association. Marine electronics you say? This association was established in 1957 to set standards for marine navigation equipment. One of the standards they established was a standard message for location. Believe it or not, this standard was developed before the first GNSS!

So what do these NMEA messages look like? Well here’s an example from where I’m located.

$GPGGA,191402.00,5340.131944,N,00246.509477,W,1,07,0.9,22.8,M,47.0,M,,*44

As you can see, the message is an ASCII comma-seperated format. The properties are outlined below:

$GP - first two letters represent the GNSS system you’re connected to. These include GL (GLONASS), GA (Galileo), BD (Beidou), GI (India), QZ (Japan) GN (GPS + GLONASS). It is also possible to request multiple combinations of readings from all six systems.

GGA - next three characters state the class of NMEA message or sentence type. GGA (Global Position System Fix Data) is the most common sentence type. Other common sentence types include RMC (Recommended Minimum Navigation Information), GSA (Show Active Satellites), GSV (Satellites in View) and VTG (Track Made Good and Ground Speed). This field dictates the structure of the remaining ASCII string. We’ll just outline the GGA sentence for now.

191402.00 - Time (from the satellite) format HHMMSS.ss.

5340.131944 - Latitude in the DDMM.MMMMM format. Decimal places are variable.

N - denotes North Latitude.

00246.509477 - Longitude is the DDDMM.MMMMM format. Decimal places are variable.

W - denotes West Longitude.

1 - denotes Quality Indicator: 1 Uncorrected coordinate.2 Differentially correct coordinate.(e.g. WAAS, DGPS), 4 RTK Fix coordinate (centimeter precision), 5 RTK Float (decimeter precision.

07 - Number of satellites used.

0.9 - Horizontal dilution of precision.

22.8 - Altitude.

M - Unit of measure of Altitude (Meters).

47.0 - denotes the geoidal separation (subtract this from the altitude of the antenna to arrive at the Height Above Ellipsoid (HAE).

M - Unit of geoidal separation.

Null - denotes the age of the correction (if any).

*44 - denotes the checksum.

So how do you talk to the Quectel EC21?

As mentioned previously, the EC21 is connected to the STM32 via the Serial UART. The EC21 has a AT style modem command mode. For example to run a GGA command to the US GPS network you run:

AT+QGPSCFG=“gpsnmeatype”,1

For the Russian GLONASS system it’s:

AT+QGPSCFG=“glonassnmeatype”,2

Pretty straightforward. Here’s an snippet of C code to get Longitude and Latitude as doubles.

bool WioLTE::GetLocation(double* longitude, double* latitude)
{
	std::string response;
	ArgumentParser parser;

	if (!_AtSerial.WriteCommandAndReadResponse("AT+QLOCCFG=\"contextid\",1", "^OK$", 500, NULL)) return RET_ERR(false, E_UNKNOWN);

	_AtSerial.WriteCommand("AT+QCELLLOC");
	if (!_AtSerial.ReadResponse("^(\\+QCELLLOC: .*|\\+CME ERROR: .*)$", 60000, &response)) return RET_ERR(false, E_UNKNOWN);
	if (strncmp(response.c_str(), "+QCELLLOC: ", 11) != 0) return RET_ERR(false, E_UNKNOWN);

	parser.Parse(&response.c_str()[11]);
	if (parser.Size() != 2) return RET_ERR(false, E_UNKNOWN);
	*longitude = atof(parser[0]);
	*latitude = atof(parser[1]);
	if (!_AtSerial.ReadResponse("^OK$", 500, NULL)) return RET_ERR(false, E_UNKNOWN);

	return RET_OK(true);
}

Hopefully you get the picture

So there you are, a bit of a “taster” on GNSS and NMEA programming via a Quectel EC21. Hope you found this useful.