Track Your Treats - GPS Shield

For the GPS shield version of the project load the Track_Your_Treats sketch by clicking Download: Project Zip in the code listing below.

// SPDX-FileCopyrightText: 2019 Tony DiCola for Adafruit Industries
// SPDX-License-Identifier: MIT

// Track Your Treats - Ultimate GPS Shield Halloween Candy Route Tracker
// Author: Tony DiCola
// See the guide at:
// Released under a MIT license:
#include <SPI.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SD.h>

// Configuration (you don't normally need to change these values):

#define LED_PIN              6   // Pin connected to an LED that flashes the status of the project.

#define BUTTON_PIN           5   // Pin connected to the button.

#define LOGGING_PERIOD_SEC   15  // Seconds to wait between logging GPS locations.

#define GPS_RX_PIN           8   // GPS receiver RX (pin 8 on the shield).

#define GPS_TX_PIN           7   // GPS receiver TX (pin 7 on the shield)   

#define SD_CS_PIN            10  // Chip select pin for SD card.

// Global state (you don't need to change these values):
SoftwareSerial gpsSerial(GPS_RX_PIN, GPS_TX_PIN);  // Software serial connection to GPS receiver.
Adafruit_GPS GPS(&gpsSerial);                      // GPS class to interact with receiver.
File logfile;                                      // SD card log file.
uint32_t logCounter = 0;                           // Counter until next location log is recorded.

// Halt function called when an error occurs.  Will print an error and stop execution while
// doing a fast blink of the LED.  If the watchdog is enabled it will reset after 8 seconds.
void halt(const __FlashStringHelper *error) {
  while (1) {
    digitalWrite(LED_PIN, LOW);
    digitalWrite(LED_PIN, HIGH);

// Timer interrupt called every millisecond to check for new data from the GPS.
  // Check for new GPS data.;
  // Decrease the count since last location log.
  if (logCounter > 0) {

// Log the current GPS location with the specified note.
void logLocation(const char* note) {
  logfile.print(GPS.latitudeDegrees, 6);
  logfile.print(GPS.longitudeDegrees, 6);

void setup() {
  // Initialize serial port.
  Serial.println(F("Track your Treats - Ultimate GPS Shield"));

  // Initialize LED and button.
  pinMode(LED_PIN, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(SD_CS_PIN, OUTPUT);

  // Initialize SD card (assumes running on Uno, for Leonardo see below).
  if (!SD.begin(SD_CS_PIN)) {
  // Initialize SD card for Leonardo or other chips (using software SPI)
  //if (!SD.begin(SD_CS_PIN, 11, 12, 13)) {
    halt(F("Card init. failed!"));

  // Create the next log file on the SD card.
  char filename[15];
  strcpy(filename, "GPSLOG00.CSV");
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // Create file if it does not exist.
    if (!SD.exists(filename)) {
  Serial.print("Using log file: "); 

  // Open the log file.
  logfile =, FILE_WRITE);
  if(!logfile) {
    halt(F("Failed to open log file!"));

  // Set the first line of the log file as the column headers.

  // Connect to the GPS receiver and configure it to receive location updates once a second.
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); // Recommended minimum output only (all we need for this project).
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);     // Once a second update rate.
  GPS.sendCommand(PGCMD_NOANTENNA);              // Turn off antenna status.
  // Configure timer0 compare interrupt to run and parse GPS data every millisecond.
  // See the SIGNAL function further below for the code that is called during this interrupt.
  OCR0A = 0xAF;
  TIMSK0 |= _BV(OCIE0A);


void loop() {
  // Parse GPS messages when they are received.
  if (GPS.newNMEAreceived()) {
  // Light the LED solid if there's a GPS fix, otherwise flash it on and off once a second.
  if (GPS.fix) {
    digitalWrite(LED_PIN, HIGH);
  else {
    // No fix, blink the LED once a second and stop further processing.
    digitalWrite(LED_PIN, (millis()/1000) % 2);

  // Check if the button is pressed.
  if (digitalRead(BUTTON_PIN) == LOW) {
    // Pause a bit to debounce.
    if (digitalRead(BUTTON_PIN) == LOW) {
      // Button pressed! Log the current location as having good candy.
      logLocation("Good Candy");
      // Then flash the light 5 times to signal the location was recorded.
      for (int i=0; i<5; ++i) {
        digitalWrite(LED_PIN, HIGH);
        digitalWrite(LED_PIN, LOW);

  // Periodically log the location.
  if (logCounter == 0) {
    logCounter = LOGGING_PERIOD_SEC*1000;

Load the code into the Arduino IDE, you should see something like the following:

You don't need to change anything and are ready to load it on the hardware.  However you can skim the #define values at the top of the sketch to see values that change how the sketch works.

To load the sketch on the hardware first make sure you have a microSD card inserted in the GPS shield's microSD card holder.  The card should 'click' into place and be held firmly by the card holder.

Then connect the Arduino to your computer using a USB cable.  In the Tools -> Board menu of the Arduino IDE make sure the Arduino Uno board is selected.  In the Tools -> Port menu make sure the right serial port is selected for the Arduino (it should say Arduino Uno next to it).  Click the Sketch -> Upload command to upload the sketch to the Arduino.

Once the sketch uploads open the Tools -> Serial Monitor to see serial output from the hardware.  Make sure the baud is set to 115200 in the lower right corner.  You should see serial output similar to the following:

Track your Treats - Ultimate GPS Shield
Using log file: GPSLOG24.CSV

The log file name will automatically increment every time the hardware is powered up or reset.  Once the hardware is ready to receive GPS signals it will print Ready! and wait for a GPS location fix to be made.

While the hardware is waiting to get a GPS location fix you should see the button LED blink every second.  Once a location fix is made the LED will stay solidly lit.  You might need to move the hardware outside where it has a clear view of the sky in order for it to get a GPS fix (it can even take up to 30 minutes in some cases!).

If something goes wrong the button LED will blink quickly (around 5 times a second).  Look in the serial monitor to see if an error message is displayed, like for example if a microSD card isn't found and the log file can't be created.

Once the hardware has a GPS fix it will start periodically logging location to the file on the microSD card.  Every 15 seconds the location will be logged (but you can change this with the #defines at the top of the sketch).  

If you press the button the current location will be logged and noted to have good candy, then the LED will blink 5 times to acknowledge the button press.  Note you can't log locations with the button if the GPS doesn't have a fix (i.e. the button is blinking every second).  Wait until the GPS has a fix and the button stays lit solidly before pressing the button.

That's all there is to using the track your treats GPS shield sketch!  Walk around and press the button a few times to get sample data, then power down the Arduino and jump to the Google Maps page to learn how to view the tracker data.

This guide was first published on Oct 12, 2015. It was last updated on May 21, 2024.

This page (GPS Shield) was last updated on May 21, 2024.

Text editor powered by tinymce.