Download PDF Parts List View on YouTube Download Code

Today we are learning how to use GPS modules with both the Arduino and Raspberry Pi. We’ll also build a GPS position logger so we can plot our adventures on Google Maps.

GPS is not the only system we’ll be tapping into, as there are other satellite positioning systems that we can use to determine our coordinates. So the proper term would be GNSS, or Global Navigation Satellite System, as there are several satellite positioning systems that we can take advantage of for increased accuracy.


GPS and similar systems) really need no introduction, as they have been part of our lives for decades now. Commercial usage started in the mid-90s, and the availability of low-cost circuitry has placed GPS devices into a variety of products, including tablets and phones.

Positioning Systems

GPS modules provide an accurate measurement of several parameters, including:

  • Longitude
  • Latitude
  • Exact Time
  • Altitude

These capabilities open the window to some interesting applications and product ideas and some great experiments for us to perform!

The modules we will be using today are quite inexpensive, but you can also get more expensive GPS modules with advanced features. We will be looking at one of them a bit later. 

How Satellite Positioning Systems Work

The principles of triangulation have been known for millennia, and early surveyors used it to map out the world and navigate. 


The basics of triangulation are that you have a triangle, and the position you want to measure is at one point on this triangle.  In our example that would be person “A”.

Now if both positions “B” and “C” are at known coordinates, and we can measure the length of all our triangle sides, we can determine the exact location of person “A” based upon those measurements.


If person “A” moves into another position we can recalculate, and because the lines are of different lengths now we will be able to calculate the new position.

So part of satellite position has to do with knowing where at least two satellites are and measuring the lines between everything. The “line measurements” are the time delay it takes the radio waves to travel back to earth and our GPS receiver.

Satellite position systems are based upon, what else, satellites! Lots of satellites, whose position is very precisely maintained and updated.

These satellites all contain precision atomic time references, and they transmit timestamps and coordinate information continuously.

Now receiving a signal from just one GPS satellite won’t tell you much. You do know the satellite’s position, and you have its time reference. But that’s not enough to determine your own position, although it is enough to narrow it down to a circle.

In order to determine your position, including your altitude, you actually need a minimum of four satellites

  • Three satellites determine the X, Y, and Z coordinates.
  • The fourth one serves as a time reference.

In an open area, you’ll be getting signals from dozens of positioning satellites, although your receiver may not be capable of using all of them. Some GPS units are limited in the number of concurrent locks they can make on a group of satellites.

Most GPS modules have some built-in memory to store GPS coordinates and satellite information, so that they can reestablish a lock should the signal become temporarily interrupted, or if the GPS device is powered down for a short while. When they start up they can establish a connection quickly using a “Warm Start”, as opposed to a “Cold Start “ like they do when they first boot up, or after a long period of inactivity.

Satellite-Based Navigation Systems 

As I mentioned at the beginning of the article there are many different satellite positioning systems that we can use with our GPS modules.

In fact, the term “GPS module” is in itself inaccurate, as these modules are capable of working with other satellite positioning systems as well. However, I’ll continue to use the term “GPS module” throughout this article, as that is what they are commonly referred to.

Let’s take a look at these satellite positioning systems, starting with the one we are all most familiar with.



We’ll start with the most well-known satellite positioning system, the American Global Positioning System, GPS as we all refer to it as.

This system was an evolution of years of military satellite positioning systems, and it was opened up for non-military applications by president Ronald Regan. These were restricted to marine and aviation use initially, but by 1994 the GPS system was available for the general public at no cost, with a 3-meter accuracy limitation.

The GPS system consists of up to 32 satellites and is constantly changing and upgrading, as of this writing there are 31 satellites in use, orbiting the earth twice a day at an altitude of 20,180 Km (12,550 miles).

GLONASS (Russia)


The Russian Global Navigation Satellite System or GLONASS also began life in 1982 as a military navigation satellite program in the USSR. It was made available for commercial use in 1995, the year after GPS became available commercially.

GLONASS consists of 24 satellites orbiting 19,130 Km (11,890 miles) above us.

These satellites can be used in tandem with other positioning systems like GPS to increase accuracy. Usd with GPS, GLONASS can bring the resolution up to about 2.5 meters, as opposed to 3 meters by itself.

BeiDou (China)


The Chinese BeiDou Navigational Satellite system has undergone several iterations. The newest, BeiDou 2, just finished deployment in 2020.

This is a system that employs both medium-orbit and geostationary-orbit satellites. 

The 30 medium-orbit satellites reside 21,150 Km (13,140 miles) above the earth.  There are also 5 geostationary satellites in the BieDou system.

Galileo (Europe)


The European Space Agencies Galileo system achieved global operation in 2014.

Galileo consists of 30 satellites orbiting at a distance of 23,222 Km (14,429 miles).

The system was designed to complement the US GPS system. 

NavIC (India) & QZSS (Japan) – Regional


Both India and Japan have established regional satellite positioning systems, between them they cover the majority of Asia.

India’s Navigation with Indian Constellation or NavIC system currently consists of 7 satellites, with plans to increase this to 11. India has signaled its intentions to expand NavIC in the future to become another global satellite positioning service.

Japan’s Quasi-Zenith Satellite System, or QZSS, currently has only one operational satellite. When finished it will have seven.

Interpreting GPS Module Data

Satellites send time and position information, and the data from multiple satellites are used to determine the location in three dimensions, as well as exact time.

GPS modules do most of the “heavy lifting” for you, extracting strings of data from multiple satellites, decoding it, and formatting the results into text strings.  

The format of these messages can vary, but most modules use the NMEA 0183 standard.  This is a comma-delimited text format that consists of rows of data referred to as “sentences”.

The sentences are provided with an identifier, which itself consists of character patterns, allowing for several dozen string formats.

Here are some of the most popular ones:

  •    $GPBOD – Bearing, origin to destination
  •    $GPBWC – Bearing and distance to waypoint, great circle
  •    $GPGGA – Global Positioning System Fix Data
  •    $GPGLL – Geographic position, latitude / longitude
  •    $GPGSA – GPS DOP and active satellites 
  •    $GPGSV – GPS Satellites in view
  •    $GPHDT – Heading, True
  •    $GPR00 – List of waypoints in currently active route
  •    $GPRMA – Recommended minimum specific Loran-C data
  •    $GPRMB – Recommended minimum navigation info
  •    $GPRMC – Recommended minimum specific GPS/Transit data
  •    $GPRTE – Routes
  •    $GPTRF – Transit Fix Data
  •    $GPSTN – Multiple Data ID
  •    $GPVBW – Dual Ground / Water Speed
  •    $GPVTG – Track made good and ground speed
  •    $GPWPL – Waypoint location
  •    $GPXTE – Cross-track error, Measured
  •    $GPZDA – Date & Time

You can decode NMEA 0183 data manually if you have a lot of time on your hands, but you can also download software to do this tedious task for you.

Here are some examples of data decoded from NMEA strings:


Time – A very accurate time reference, a GPS is a good consideration for your project even if all you need is an accurate clock.



Longitude – Note the results are in degrees.decimal minute format and will probably need to be converted in order to use it. 



Latitude – Same thing as longitude, this will probably need to be converted before using it.



Satellites – The number of visible satellites.



Altitude – Measures in meters.


GPS Libraries

A much easier way to work with NMEA 0183 data is to just use a library or program built to use it. And there are many choices of libraries for the Arduino that can parse the GPS data and deliver it to you in a human-readable format.


A popular library is the TinyGPS Library. You can easily install it, along with a code sample, using the Arduino IDE Library Manager.

  • Open your Arduino IDE
  • Open the Tools menu (from the top menu bar)
  • Look for Manage Libraries on the Tools menu, and click on it
  • The Library Manager will open
  • Use the filter (search) box to look for “Tiny GPS”
  • The TinyGPS by Mikal Hart will display, along with an Install button to the height
  • Click the Install button to install the TinyGPS Library
  • You can now close the Library Manager.

tinyGPS Library for Arduino

This is a very popular library, so if you’re running GPS code samples you picked up on the Internet you’ll probably need it.


TinyGPS++ is an improved version of TinyGPS, and it comes with several code examples. Unlike TinyGPS, you need to download this library from GitHub as a ZIP file, and then install it into your Arduino IDE manually.

It’s pretty simple:

  • Go to the TinyGPSPlus page on GitHub
  • Click the green Code button’s drop-down arrow. A sub-menu will appear.
  • Click the Download Zip link and save the file somewhere that makes sense to you.
  • Now open your Arduino IDE.
  • Click on the Sketch menu at the top of the IDE
  • Choose Include Library
  • From the resulting menu select Add ZIP Library
  • Select the ZIP file you downloaded from GitHub
  • The Library will be installed

Install the tinyGPS++ ZIP library

Look over a few of the code samples included with this Library to get a feel for how easy it is to use.

Basic GPS Module Operation – Beitian 180 & 220 with Arduino

Enough theory and libraries, it’s time to actually hook up a GPS module and start getting positioning data!

We will begin with a very basic GPS module. You can use just about any GPS module that outputs serial data, in other words, any module with the following connections:

  • Transmit or TX
  • Receive or RX
  • VCC or 5-volt power supply
  • Ground

I’ll be using both the Beitian 180 and 220, which are nearly identical.

Beitian 180 & 220

These units have similar specifications, the 220 is slightly larger and also has internal flash memory, which we aren’t using in our experiments. 

The BN-220 has the following specifications (the BN-180 is nearly identical):

  • Chipset: 8030-KT
  • Receiving Format: GPS,GLONASS,Galileo,BeiDou,QZSS and SBAS
  • Frequency: GPS L1,GLONASS L1,BeiDou B1,SBAS L1,Galileo E1
  • Channels: 72 Searching Channel
  • Position Horizontal: 2.0 m CEP 2D RMS SBAS Enable (Typical Open Sky)
  • Velocity: 0.1m/sec 95% (SA off)
  • Timing: 1us synchronized to GPS time

Clearly a precision module at a very low price.

You don’t have to use one of these modules if you can’t find one, or if you already have other modules. Any GPS module with a serial data connection that is 5-volt tolerant should work.


Here is how we will hook up our GPS module. The connections are very simple.

Arduino GPS Hookup

Once we have it hooked up you’re ready to go satellite hunting! But before you take everything outside it might be a good idea to see if it all works

Second Serial Port

The GPS module has a serial interface, with Receive (RX) and Transmit (TX) connections. This allows the module to be interfaced with just about anything that also has a serial connection.

When it comes to the Arduino Uno we have a bit of a problem. The Uno has only one serial connection, on pins 0 and 1. And while this connection would work perfectly with a GPS module, we can’t use it.

This serial connection is already in use, it’s used by the USB port. So as long as we need the Serial monitor or terminal, we have to leave these pins alone.

We need a second serial connection. Fortunately, it’s pretty easy to emulate one in software.

The SoftwareSerial library is included with your Arduino IDE, so you don’t need to install anything. Simply provide it the baud rate of the serial port you want to emulate and pick two unused digital I/O pins to assign RX and TX to and you’re in business.

SoftwareSerial Test

We will be using SoftwareSerial to emulate a serial port on pins 3 and 4. Since it’s the heart of every sketch we will be using today, it’s nice to have a way to see if it is working (and to assist if it isn’t).

The following sketch is very simple, it just does one thing – it takes data from the software serial port and sends it to the hardware serial port.

The net effect is that if you run the sketch and open your Serial Monitor (be sure to set the baud rate correctly) you’ll be able to read every message delivered to the software serial port.

So if a GPS module is connected to the software serial ports, as we have on pins 3 and 4 here, we should be able to see a bunch of NMEA sentences.

Here is the SoftwareSerial test sketch:

This is a very simple sketch, but it does serve to illustrate how to set up and work with a software serial port.

We start by defining the pins we are using for our software serial port, there is nothing particularly special about the ones I chose so you can change them if you want to.  I used pins 3 & 4.

Then we set up the baud rate for the port, which will be the baud rate for the GPS unit. In this example, I used 9600, but you should check with your GPS module documentation for the correct rate.

We also set up the serial monitor baud rate at a quick 115,200, so be sure to adjust your Serial Monitor accordingly when you run the sketch.

Finally, we initialize a software serial object named GPSserial with the pins we defined earlier. We can now use this object as another serial port.

In the Setup, we start both the hardware and software serial ports. And in the Loop we pass any data from the software serial port to the hardware serial port, so we can display it on the serial monitor.

Testing the GPS Module

We can use the sketch to test our GPS module, even if we are indoors where we can’t get a good signal we can still get an output from the GPS module.

Load the sketch and run it, open the serial monitor (check that baud rate!). And observe. You should start seeing NMEA sentences.  

Even if you are indoors (as I was)  you will still see data, albeit garbage data. If you see nothing, check your wiring. A common problem is reversing the TX and RX pins from the GPS module.

Run the experiment in an area where you have a clear view of the sky. When you first start it may take a minute or two to lock into a satellite, this is a “cold start”. After that your subsequent “warm starts” should be a lot quicker.

You’ll see lines of NMEA data. If you wish you could copy some of it and decode it with a software tool.

NMEA String Test

But a much easier way of working with NMEA satellite data is to just use a library.

TinyGPS++ Demo

If you installed the TinyGPS++ Library as I suggested earlier then you may have already seen some of the example sketches that come packaged with it.

We will be running the Full Example sketch to demonstrate the TonyGPS++ libraries’ capabilities.

This is one of the sketches included with the TinyGPS++ Library. It gives a wealth of information when fed GPS data.  You can get it by going to the File menu , then into Examples, and scrolling down until you see the TinyGPS++ entry.


The sketch makes use of a number of TinyGPS++ functions to gather data and display it. The data is formatted to make it pretty to print using a number of custom “print”  functions. It’s really as simple as that.

Load up the code and take your GPS somewhere that you can receive satellites – you can always test with the previous sketch to be sure you have data coming in.


Now look at the readings as they update, they are pretty accurate. And now you know how far you are from London!

GPS & Compass – Beitian BN-880 with Arduino

The Beitian BN-880 is a very sensitive GPS that also has a built-in magnetometer, meaning that it has a compass inside it. This is very useful in model aeronautics and  boating, but it also has possibilities for our robotics projects as well.

Beitian BN-880

The Beitian BN-880 has the following specifications:

  • Receiving Format: GPS, GLONASS, Galileo, BeiDou, QZSS and SBAS
  • Receiving Channel: 72 Searching Channel
  • Output Frequency: 1Hz-10Hz,Default 1Hz
  • Support Rate:4800bps to 115200bps,Default 38400dps
  • UART Interface: UART Port: TXDA and RXDA

As you can see it’s a pretty powerful unit, and it isn’t all that expensive either.


The built-in magnetometer is an older model that still sports some impressive specifications.

The magnetometer is based upon a HMC5883L chip, which is billed as a “3-axis Compass”.  It is supposed to have a heading accuracy of 1 to 2 degrees, and can be used in conjunction with the GPS readings to tell yo9i not only where you are, but what direction you are heading in.

The HMC5883L is an I2C device, so the BN-880 has two extra connections for the SDA and SCL lines.

Beitian BN-880 Hookup

Here is the hookup for the Beitian BN-880 and an Arduino Uno.  Please don’t follow the colors of the wires, as different vendors supply different connection cables. Instead, look at the order of the connections on the BN-880 connector.

BN-880 to Arduino Hookup

You’ll note that the GPS connections for the BN-880 are identical to what they were for the other GPS modules we have already used. You can use the same code to access the GPS section of the BN-80 and it will function perfectly.

The other connections are the I2C connections. In my test, I didn’t need to use pull-up resistors, if you experience erratic readings from the magnetometer you could try using a couple of 4.7k pullups on the SDA and SCL connections.

Magnetometer Code

In order to work with the magnetometer, or compass, feature of the BN-880 we will need to add a library to work with the HMC5883L. There are several, Adafruit has a nice one.

We can install the Adafruit HMC5883L Library from the Library Manager in our Arduino IDE, in the same fashion that we installed the TinyGPS library. Just search the Library Manager for “HMC5883L”, the Adafruit library will likely be the first result. 

When you install the Adafruit library for the HMC5883L you may get prompted to install some dependent libraries. Choose to Install All of them, as this library depends upon these other libraries to function (that is actually why it’s named a “unified driver”). You can close the library manager once aloof the unified libraries install.

Once you have the HMC5883L library installed we can run some example software to demonstrate the use of the magnetometer.

Open the list of Examples and scroll down until you see Adafruit HMC5883L Unified. Select it, and select the only sketch in the resulting list – magsensor

This sketch demonstrates the use of the magnetometer by displaying the values from all three degrees of freedom on the serial monitor.

Calculating Magnetic Declination Angle

One thing you may want to note is the “Declination Angle” correction that you can add on line 91, this compensates for the difference between the true north (or south) pole and the magnetic one.  It differs depending upon where in the world you are, the value in the sketch is for New York City.

This value is in Radians, so you’ll need to do a little work to get it, as the resources that follow don’t supply a Radians value.

You can calculate your magnetic declination if you know your longitude and latitude, or just by visiting the Magnetic Declination website.

There are several other interesting resources on the Internet for this, as a Canadian may I recommend one from the Government of Canada – it’s useful for anyone, anywhere in the world, not just Canada.  And that same Canadian Government has a good article explaining what Magnetic declination actually is.

The NOAA also has a nice online utility that can accept your address and calculate Magnetic declination for you.

However you get it, you’ll need to do two things to it so it can be used in the sketch:

  • Convert it to Degrees with decimal places
  • Convert Degrees to Radians

The Radians value is what is required for the sketch.

First Convert the Degrees-Minutes-Seconds to Degrees with a decimal figure. Divide the minutes and seconds by 60 to get their decimal values, and add them up.

Then go to a Degree to Radian calculator, like the one Google has.

The resulting value is what you’ll need for your sketch, to correct for magnetic declination in your location.

Magnetometer Demo 

Load the sketch onto the Arduino and open the Serial Monitor. 

Magnetometer test

You should see the readings of the X, Y, and Z-axis. Now rotate and twist the sensor, and observe the corresponding readings.

You can experiment and follow the calibration instructions in the code sample to see how accurate a “compass” you can make!

Adafruit Ultimate GPS with Raspberry Pi

The next module we will look at is a bit different in that it uses a USB connection to supply serial data, instead of a couple of output pins.

This sort of sensor is better suited to a microcomputer, so we will be bringing a Raspberry Pi in for this one.  Although I use a Raspberry Pi 4 any Pi with internet connectivity, including the model Zero W, would work fine for this task.

Adafruit Ultimate GPS

The Adafruit Ultimate GPS is actually available in two configurations:

  • A USB one, like the one I have
  • A model with discrete output pins, similar to the other devices we have looked at today.

Both feature the same high-performance GPS sensor.

One real bonus that this module offers is the ability to use an external antenna. I took advantage of this to work on the GPS indoors, with an antenna in my backyard!

The specifications of the Adafruit Ultimate GPS are as follows:

  • Satellites: 22 tracking, 66 searching
  • Patch Antenna Size: 15mm x 15mm x 4mm
  • Update rate: 1 to 10 Hz
  • Position Accuracy: < 3 meters (all GPS technology has about 3m accuracy)
  • Velocity Accuracy: 0.1 meters/s
  • Warm/cold start: 34 seconds
  • Acquisition sensitivity: -145 dBm
  • Tracking sensitivity: -165 dBm
  • Maximum Velocity: 515m/s
  • Vin range: 3.0-5.5VDC
  • MTK3339 Operating current: 25mA tracking, 20 mA current draw during navigation
  • Output: NMEA 0183, 9600 baud default, 3V logic level out, 5V-safe input
  • DGPS/WAAS/EGNOS supported
  • FCC E911 compliance and AGPS support (Offline mode : EPO valid up to 14 days )
  • Up to 210 PRN channels
  • Jammer detection and reduction
  • Multi-path detection and compensation

You can use the Adafruit Ultimate GPS with a Windows-based utility, the MT3339 GPS Tool. It is an older utility,, but I had no problem getting it to work using Windows 10.

Today, however, we will be using Linux, specifically the Raspberry Pi Operating System.

Adafruit Ultimate GPS Connection to Raspberry Pi

The Adafruit Ultimate GPS uses its microUSB connector for both power and data transfer, so as soon as you plug it into an active USB port it starts working.

While you could certainly use any Internet-connected P{i for the job (you need the Internet to download the software for our demo) the model Zero W has only one USB port, so you would likely need a USB hub. 

As I wanted to take advantage of the external antenna jack I purchased a few other accessories.

  • An external GPS antenna, I got the Sparkfun 
  • A metal plate, to thread onto a tripod or light stand and to act as a ground plane for the GPS antenna (it’s a requirement). Your car roof is also a good surface, and the antenna is magnetic.
  • A ufl to SMA cable, to connect the tiny ufl connector in the Ultimate GPS to a standard SMA cable, used by most GPS antennas.
  • A couple of SMA male to female extension cables. In my case, I had a total of 8 meters of extension cable, and everything worked well.

GPS Remote Antenna

This allowed me the luxury of using the GPS in my office, but it didn’t quite reach the workshop. So I solved that with a 4 meter USB to microUSB cable to run the “last mile” down my hallway. The GPS module sat in the middle of the hallway, with the Raspberry Pi on my workbench, and it worked well enough to film the demo!

Displaying GPS Data on Raspberry Pi

There are a number of ways to make use of the GPS data on a Raspberry Pi. I’m going to show you a very simple one that you can install and run from the command line.

You’ll need to type six lines at the command line to install the GPSD software and run it – once it’s installed you can run it with just two lines.

I have a Cheat Sheet available, a text file with all of the commands in it. It’s in the ZIP file with all of the code, and you can download the whole package to make your GPS experimenting easier.

Here is what you’ll need to type in:

First, we will list the USB devices, just to be sure we see our Adafruit GPS. 

Next, we will install GPSD, so we can examine incoming GPS data.

You’ll be notified of the resources the software will consume and you’ll be asked if you want to proceed, naturally you do, so type “Y”.  The software will take a minute to install.

After the GPSD software is installed we need to stop a service it installs, and prevent it from running again. This is a modification required for the Raspberry Pi Operating System, and for some other versions of Linux as well,

First, we stop the service, and then we disable it so it can’t run again:

Now we can manually start the GPSD service and connect it to the GPS on USB0, which is where your Adafruit Ultimate GPS should be.

And finally, we can run the GPSD display.


Raspberry Pi CGPS Utility

The display may take a minute to lock in if you’re performing a cold start, after that it should happen pretty quickly. You’ll get your position information updated every few seconds.

Build a GPS Position Logger

We’re going to finish off with a fun experiment, one that will get you out of the worship and outside in the fresh air. At least it worked on me!

We are going to build a very simple GPS Position Logger. A device that will log our GPS position and time readings to a mMicroSD (or SD) card, so that we can view them later.

And we can actually “view” them, as the results we are returning are in a format suitable for use with Google Maps!

GPS Position Logger Operation

This is a very simple position logger, you can use it as the basis for a more advanced design.  It works as follows:

  • Starts up, checks GPS and SD card status
  • Blinks LED three times to indicate all is OK
  • Attempts to lock onto several satellites. If this is a cold start the process may take a few minutes, a warm start usually locks in a few seconds.
  • Reads and validates satellite data
  • Records latitude, longitude, and timestamp to the SD card
  • Flashes the LED to indicate a successful recording
  • Continues until powered down

The data is saved in a CSV, or Comma Separated Value, format. I’m pretty sure you’ve already encountered this standard text format, which can be opened with any spreadsheet application or text editor.

A CSV file can also be used with Google Maps to import map data, so you can get a visualization of where you have traveled to. Note that Google Maps accepts a CSV file with a maximum of 2000 entries.

To prevent “flooding” Google Maps, which I did a few times while prototyping this design, I put a counter into the program. This worked to slow down the CSV file update from several times per second to once every three seconds, which I deemed an adequate compromise and suitable for walking.

There is a variable in the code you can use to set the pace of the update, with my experiment I walked for over 25 minutes and recorded just under 400 lines of data. You may experience slightly different times, due to differences in satellite reception conditions.

GPS Position Logger Components

I just built my logger on a standard solderless breadboard. I advise that you do that before you put together a more permanent version of it. You might come up with some great modifications!

GPS Logger

To build the GPS Position Logger you will need the following parts:

  • An Arduino Uno, or other 8-bit AVR Arduino board
  • A GPS sensor like the Bietain BN-220 (any sensor with a serial output should work)
  • An SD or MicroSD card module that runs on 5-volts.  One that has a regulator and level-shifter onboard.
  • An LED and a dropping resistor, 220 ohms is what I used and I could see my LED flash in broad daylight.

You‘ll also need a way of powering up your project when you take it outside. I just used a 9-volt battery (a fresh one!) and the power jack on the Uno, which is probably the easiest way. You could also use a USB Power bank.

GPS Logger

Of course, you’ll need a breadboard or perfboard to build everything, as well as some suitable wire.

GPS Position Logger Hookup

Here is how to hook everything up, it’s essentially the same GPS hookup we have already used with the addition of the SD card module and the LED. The SD card module uses the Arduino’s SPI connection.

Arduino GPS Logger Hookup

You may want to give consideration as to where you mount the GPS module, as that will be our “reference point.  I mounted mine at the end of the solderless breadboard, with a couple of wire loops to position it and minimize its movement.

GPS Position Logger Code

Of course, the real fun is in the code, which is presented here:

As you can see the code is based upon the TinyGPS++ Library, which you need to install using a ZIP file as described earlier in this text. So if you haven’t done that yet you should do it right now!

The other three libraries are already part of your Arduino IDE, so there is nothing else to install 

  • The SoftwareSerial library, to create a software serial port for the GPS connection.
  • The SPI library, to address the MicroSD card module, as it is an SPI device,
  • The SD library, to work with files and directories on the MicroSD or SD card.

We start by defining some constants and variables, most of which are pretty obvious. The SD Card CS lead is defined as pin 5, you can move it if you want to and change the code here.

Same with the LED on pin 7.

The gpstext string holds a line of comma-delimited text to write to the SD or MicroSD card.

The two variables for the gpscount are used to “taper off” the readings, otherwise, you’ll exceed the 2000 points that Google Maps can use very quickly.

Of particular note is the variable gpsttlcount , an integer that determines how many GPS readings we “throw-away”. I have set it to 30, which means I only record one out of every 30 readings. 

I found this value suitable for walking, but you can feel free to experiment. You’ll get more readings if you reduce it, and fewer if you increase it.

In the setup, we set up our ports, start the SoftwareSerial and then attempt to initialize the SD card.  

If we fail to initialize the SD card then we don’t continue, and we print an error message to the serial monitor.

Since we plan on using this in the field, without a serial monitor, we flash the LED a few times after we successfully initialize the SD card. So if you don’t see the flashing LED a second or two after powering up, then the SD card didn’t initialize.

Before you look at the Loop take a peek further down at a function called displayInfo() . This function returns a string with one of two values:

  • A formatted line of text for the CSV file
  • The character “0”

The “0” is sent back when the GPS data for location or time isn’t valid, which will happen during a cold start. We don’t want to record those failed attempts.

The function makes extensive use of the TinyGPS++ library to get data for location and time.

Note how the longs used for latitude and longitude are converted to Strings with the String macro. This macro uses an optional parameter to determine decimal places, which in this sketch is “6”.

Also note how time and date digits less than 10 are handled, with a preceding zero inserted to make everything format correctly.

In the Loop we call this function, and if the data is valid we go through the counter. If the count has been reached then we open a file called “gpslog.csv” for writing.

If this file does not exist we will create it. If it does exist we will append data to it. This is important to note if you are using the GPS Logger and turn it off and on again.

If the file opens successfully we will write a line of text and then close the file.  We set the counter back to zero and go through it all again.

Load the sketch onto your Arduino and run it, ideally with the serial monitor at first to see if all is working correctly. The serial monitor will print a line of CSV data every time it is written to the MicroSD card.

Once you have it working with the computer you can try it stand-alone, I’d suggest a small local trip to start.  Go out and gather some data, and then we’ll see how we can display it.

Reading GPS Position Logger Results with Google Maps

After running the position logger for a while you should be ready to read the data you have gathered.

Power down the Arduino and eject the MicroSD card. Pop it into a computer with a suitable adapter.

You should see one file on your card, GPSLOG.CSV. Note that despite entering our filename in lowercase in the code the SD library has converted it all to upper case.

You might want to copy that CSV file to your local computer, to make it easier to work with.

Reading CSV File

A CSV file is just a text file with values separated by commas, so it can be read in any text editor.

Even better, this is also a format recognized by pretty well every spreadsheet application ever built. So you can open Excel, Google Sheets, or LibreOffice Calc to view the file in a more detailed fashion.

GPS Log in Spreadsheet

I opened my file in LibreOffice Calc, and it shows three columns.

  • Longitude
  • Latitude
  • Timestamp

Looking at the timestamp on my sample file I determined that I walked for about 26 minutes, during which time I collected 398 lines of data.

Displaying CSV Files on Google Maps

Of course, looking at all this data in a spreadsheet isn’t really very descriptive, unless you happen to have geographic coordinates memorized (I don’t).

There is a much better way to look at our data and see where we have been – Google Maps.

Google Maps can import data in several formats, including a CSV file with three columns, like the one we just saved. 

Here is what you need to import GPSLOG.CSV into a Google Map. 

  • Open Google Maps.
  • Click on the Menu (top left corner).
  • Click Your Places.
  • In the Your Places window click the MAPS tab.
  • At the bottom of the Maps tab click the Create Map link. You can also click See All Your Maps and use the red Create a New Map button.  Both methods will open a new map.
  • You may give your map a title and description, this is optional.
  • Click the Import link (under Untitled Layer).  The Import dialog box will open.
  • In the Import dialog box click the Select a file from your device button. 
  • Select the GPSLOG.CSV file, either from the SD card or from a local copy.
  • The import process will proceed.
  • Assign the first column to “latitude”
  • Assign the second column to “longitude”. Click to continue
  • Use the third column (timestamp) as the name for the waypoint. Click to continue.
  • Your waypoints will be imported, and Google will draw you a map of your journey.

My maps looked pretty good, I walked around a park and my trip matched the one Google laid out for me pretty closely.

GPS Log in Google Maps

In some cases, I was under a lot of trees, but it didn’t seem to affect the readings.

GPS Log in Google Maps

This simple position logger could certainly be expanded upon to make a useful tool.


I had a lot of fun playing with these GPS modules, and I was impressed with the performance of even the most inexpensive ones like the BN-180 and BN-220.

I also am doing more work with some fairly high-end GPS tools and will be showing you the fruits of my labor very soon, so stay tuned.

In the meantime why don’t you pick up a GPS module and check it out, if you need precision location or time information, or just want to see how these little wonders work.


Parts List

Here are some components that you might need to complete the experiments in this article. Please note that some of these links may be affiliate links, and the DroneBot Workshop may receive a commission on your purchases. This does not increase the cost to you and is a method of supporting this ad-free website.




Code and Cheat Sheet – All of the code for this article, plus the command-line “cheat sheet” for Raspberry Pi

TinyGPS++ Library Guide – More information about using the TinyGPS++ Library

Adafruit Ultimate GPS  Guide – Documentation for the Ultimate GPS (both interfaces) from Adafruit

Find your Magnetic Declination – Find Magnetic declination for your location or any location in the world.

Using GPS Modules with Arduino & Raspberry Pi
Using GPS Modules with Arduino and Raspberry Pi
Article Name
Using GPS Modules with Arduino and Raspberry Pi
Learn how satellite positioning systems work and how to use common GPS modules with the Arduino and Raspberry Pi. Also, build a GPS Logger.
Publisher Name
DroneBot Workshop
Publisher Logo
Notify of

Inline Feedbacks
View all comments
Dave Allen
3 years ago

Very thorough. I really enjoyed your content.

3 years ago

Hi Bill! Thanks for the amazing introduction about GPS sensors. However, I would like to suggest that the un-parsed NMEA sentences (such as GGA, GLL, RMC etc.) including sensible personal data should also be blurred. Please check your video from the time of 14:35.

3 years ago

Is there an error in the “cheat sheet” because two lines are the same.

2 years ago

You make this so informative even I can follow along! Thanks..

2 years ago

Looking forward to the RTK follow up!

2 years ago

Hi Bill, Amazing project, congratulations. I’ve got the Beitian Bn880 and came with the regular 1.25mm 6-pin cable. My question is: Did you get another cable to pin the wires in the breadboard? Like this one, 1.25mm Pitch 6-pin Cable Matching Pair – 10 cm long. Many thanks for you videos!!!

2 years ago

Can one get these to work indoors?

steven todd elliott
2 years ago

Your content is simply the BEST. I am so impressed with the amount of work and the crazy amount of thought and detail in all of you work. I am a fan forever.

2 years ago

If precise readings are required I think there is an issue with the GPS due to the limited precision of the Arduino UNO. In the Uno using double only gives the same precision as float – ie 4 bytes which from the Arduino reference is approximately 6-7 decimal digits. If the the longitude is only small there may not be any problems. However I’m at 145.073736 which is 9 digits. Using TinyGPS++ always gives a “0” in that 6th decimal place – I suspect the 5th place is also subject to some error. I’ve looked at the TinyGPS++ code and… Read more »

2 years ago

Thank you so much for your content. It is so thorough, I love it. I am referencing your examples for a project. Your resources have helped me so much.

I have everything breadboarded out in front of me right now. After I make some tweaks, Im going to 3D print the body of the thing that all this stuff is going into.

Im combining, gps(bn-220), (nema)stepper motor, motor controller (L298N), into a thing, and your videos are helping me put it all together!

Thank you again!

2 years ago

first- Thanks for the greate channel !
GPS data is showing fine when I use the basic plot of data using the softwreserial
But when trying any of the TinyGPS all I get is th Asterisk (Invalid data) any Ideas why ?
needless to say I he tried booth outdoors simultaniously

2 years ago
Reply to  chenYadid

Hi, I had the same issue. I had to change line 9 of the ‘FullExample’ sketch to a Baud rate of 9600 from the 4800 in the sketch.Oddly the software serial demo has 9600 Baud, so works. Also, my module (GY-NEO6MV2) the RX and TX pins are labelled in reverse!! So I had to swap them as Bill alluded to in the video. Now working fine. This module does not flash it’s LED until it receives a valid satellite signal, so looks dead for a few seconds (or minutes indoors). BTW, the TinyGPSPlus library is now available in the Arduino… Read more »

2 years ago
Reply to  chenYadid

ALL the example sketches in the TinyGPSPlus examples are set to GPSBaud = 4800;.
I believe 9600 is more common Baud rate for the GPS modules?

Dylan Martin
2 years ago

In the BN 880 example the connections for TX and RX are D3 and D4 which is fine for the uno but for the mega2560 those pins don’t support change interupts so they cant be used for RX. This this causes the code to get stuck on mag.getEvent(&event); at the beginning of the loop. The obvious fix being to change the TX and RX pins being used but I can’t find in the code where to do that. Any help is appreciated I am a complete newbie to all of this

Dale Young
2 years ago
Reply to  Dylan Martin

You can utilize the same code with the Mega2560.
Just change the pins to:

BN-880 => Mega2560
SDA => SDA (Pin 20)
TX => TX1 (Pin 18)
RX => RX1 (PIN 19)
VCC => 5V
SCL => SCL (Pin 21)

1 year ago

Thank you for all your great work; in going over GPS again. What I am concerned about is we have not heard from you for some time. How are you?

1 year ago

I just came across your article and it is really great. Your content will help me realize one of my projects that I have been wanting to do for far too long. Thank you for your work and the very useful information

rudranjan saha
1 year ago

How make GPS clock with wireless data streaming to display. 

                         Digital GPS Master Clock
Wireless RS communication 
                         Digital slave clock

1 year ago

hi I have been following your channel and am trying to make a poc with Lora Wifi esp32 V2 board with Oled and adding BN-220 GPS. i am stuck with an issue i am not able to figure out yet the issue Issue : i am not able to read any data from the serial pins , i get INVALID , while this happens on the GPS board the blue light is flashing I have connected RX and TXs follows static const int RXPin = 2, TXPin = 17; using TinyGPSPlus //in setup Serial2.begin(4800,SERIAL_8E1,RXPin,TXPin); // in loop while (Serial2.available() >… Read more »

Last edited 1 year ago by Ameen
1 year ago

I went and bought a BN880 and I’m wondering if it’s possible to run both the magnetometer and the gps at the same time. I’ve got a working gps sketch and I can get a magnetometer sketch working but when I put the two together the magnetometer sketch takes over. I am running this on an Arduino Uno.

Last edited 1 year ago by Witchdoc59
Dave Bailey
1 year ago

I’m trying to use the code on the tiny+ examples to read from a L76x Waveshare module but having no luck receiving any data, I’ve set the baud to 115200 and serial monitor now shows some text but its not receiving anything else it just shows no signal, even out side. Am I missing something ?

13 days ago

When i read def read_gps_data(ser):
  while True:
      if ser.in_waiting > 0:
        line = ser.readline()
          decoded_line = line.decode(‘ascii’).strip()
        except UnicodeDecodeError:
          print(f”Unable to decode line: {line}”)
I get UnicodeDecodeError , always read garbage , i tried using same baudrate on arduino works fine .

Pancham Bhatt
1 day ago

Hi Bill! Thanks for the amazing introduction about GPS sensors I’m working on a new project where I need to log temperature sensor data alongside GNSS parameters to track vehicle travel routes and GPS speed on to an SD card. The system will be used in India. Could you please recommend a GNSS module that provides the highest accuracy and refresh rate without RTK? I’ve looked into several products, such as the ublox F10N, Z F9P, NEO M9M, and MOSAIK X5, but I’m finding it difficult to decide. Please recommend a suitable GNSS module and antenna for my application Thanks and… Read more »