Summary:

Create a pocketable battery-operate GPS tracker for logging the movements of interesting stuff.

Materials:

materials-2

  1. Adafruit Feather 32u4 Adalogger (SD Card)
  2. Micro SD Card (1 GB or larger)
  3. USB-mini cable
  4. Serial GPS module
  5. Breadboard Cables
  6. 3.7V LiPo Battery (>1500 mAh)
  7. Arduino IDE

Process:

Prerequisites:

Make sure the Arduino IDE is up to date, and board support for the Adafruit Adalogger 32u4 are installed. Also make sure that the TinyGPS library is installed.

Format the SD card to FAT16/FAT32.

Assembly:

Insert the Micro SD card into the Adalogger board. Connect the VCC and GND pins of the GPS board to the 3V3 and GND pins of the Adalogger. Connect the TX pin of the GPS to the Adalogger A0 pin (GPIO18). Connect the RX pin of the GPS to the Adalogger A1 pin (GPIO19). Connect the USB-Micro cable to the Adalogger and the computer.

pins

Code:

The code should accomplish two things. First, it should establish connection with a serial GPS device and parse meaningful data, such as coordinates or altitudes. Then it should write those coordinates to a file on a micro SD card, in a format that can be easily read by external tools.

Talking GPS:

First we need to talk to the serial GPS device. Thanks to the folks behind the Arduino project we can use the handy SoftwareSerial library to open a line of communication. Using the libary we can read information from the GPS device as it becomes available. But by standard the GPS spits out NMEA sentences, which aren't exactly brief or user-friendly.

nmea

This is where the TinyGPS library comes in. The library allows us to abstract the NMEA protocal and make simple calls for lat/lon or altitude. All we need to do is wait for data to parse, and then make simple library calls.

For debugging we might also want to initialize and print these values to the built-in serial port.

#include <SoftwareSerial.h>
#include <TinyGPS.h>

long counter = 0;
float lat = 0.0,lon = 0.0, alt = 0.0;
SoftwareSerial gpsSerial(18,19); // RX, TX
TinyGPS gps;

void setup() {
    Serial.begin(9600);
    while (!Serial) {
        ; // wait for serial port to connect.
        // Needed for native USB port only
    }
    
    gpsSerial.begin(9600);
}

void loop() {
    while(gpsSerial.available()) {
        // For every new available byte from the GPS
        if(gps.encode(gpsSerial.read())) {
            // Pass it to the parser. If it makes a full sentence,
            gps.f_get_position(&lat,&lon); // get the lat/lon
            alt = gps.f_altitude(); // and get altitude
        }
    }
    
    // make a string for assembling the data
    String count = String(counter++); // For recording the entry number
    String latitude = String(lat,6);
    String longitude = String(lon,6);
    String altitude = String(alt);
    String dataString = count+","+latitude+","+longitude+","+altitude;
    Serial.println(dataString);
    
    delay(30000); // Wait 30 seconds before checking again
}

Writing to an SD Card:

All that is useful if you want to walk around looking at a serial monitor, but I want to log this data so I can slip the tracker in my pocket and forget about it. To do that I'll need to log to an SD card. For this reason I chose to use an AVR 32u4 board with a built-in Micro SD slot.

Again, the Arduino folks have made using an SD card dead simple, with the SD library. All we have to do is create an SD card object. After some initialization we can open a file with write permissions. Then we can treat it much like a UNIX file pointer and print directly. Some serial prints sprinkled in can make debugging a bit easier.

#include <SD.h>

const int chipSelect = 4; // For SD card lib

void setup() {

    { ... } // GPS code

    Serial.print("Initializing SD card...");
    
    // see if the card is present and can be initialized
    if (!SD.begin(chipSelect)) {
        Serial.println("Card failed, or not present");
        // don't do anything more.
        while (1);
    }
    Serial.println("card initialized.");
}

void loop() {
    { ... } // GPS code
    
    File dataFile = SD.open("location.txt", FILE_WRITE);
    
    // if the file is available, write to it:
    if (dataFile) {
        dataFile.println(dataString);
        dataFile.close();
    }
    
    // if the file isn't open, pop up an error:
    else {
        Serial.println("error opening location.txt");
    }
}

Using the Data:

Since we decided to be nice to ourselves and store the data in CSV format, any text editor or open source toolkit can be used to process the data. All we have to do is unplug the battery, remove the micro SD card, and insert it into any computer that can read FAT16/32 disks. In the example above, location.txt might have data that looks like this:

0,29.1235,38.5678,51.113
1,29.1236,38.5678,51.618
2,29.1236,38.5678,56.847
3,29.1235,38.5680,57.926
4,29.1237,38.5676,59.121
...

The data format we defined in the code is DataNumber,Latitude,Longitude,Altitude.

Source:

Full example source for today can be found here.

Packaging:

I wanted to ruggedize this project a bit, so after testing my code I soldered the correct pins together with short wire jumpers. Then I put the whole setup including the LiPo battery into an empty mints tin. To prevent the tin shielding or otherwise hindering the GPS signals I used a hammer to add a small indent in the mint tin's lid so I could snake the antenna outside the tin. Then I stuck the antenna on with some double sided tape.

case

Discrete. You wouldn't even suspect it

Future Work:

This was intended as investigatory work for high altitude balooning projects, as a case study into reading/writing GPS logs to file for audit purposes. Any number off applications could be explored, such as mobile asset tracking - shipping an expensive package, DI-why LoJack car tracking, really obvious espionage, etc.