Introduction: Solar Powered GPS Hiking Logger
The concept here is simple, I want to be able to log where I go on my walks so that after my walk I can see where I have been. In the past I have used GPS on my phone, but when going on an all day (8 hour) hike, by the end of the day my phone is flat and I cannot even make phone calls.
I have been given a neat 5W 5V (so 1A) solar panels, so I was thinking that I could power a little Arduino with a standard GPS module.
Step 1: The Arduino and Code
I have a CAN-BUS shield (from when my car was having engine problems and I tried to do my own diagnostics) and noticed it has a EM-406 socket to plug in a standard GPS module. I ordered a GPS module from ebay (all GPS modules EM-406 socket seem to be the same) and plugged in a micro SD card into the SD socket on the shield.
To make the GPS logging easy I found a most excellent library called TinyGPS++ which means I don't need to spend my time understanding the packets sent from the GPS module!
Using linux tools such as GPS babel or online tools such as GPS Visualizer the data can be converted between most standard formats, so I thought I would stick with CSV so that I could open it up excel or matlab, but can still easy convert to kml to view in Google Earth.
I have included the source code I used below, I have left the serial dumping stuff in for debugging purposes (so you can see your location from your laptop immediately).
The LED's built into the shield are used to indicate when the board is logging, and the other for when the GPS is locked.
#include <SPI.h> #include <SD.h> #include <TinyGPS++.h> #include <SoftwareSerial.h> const int LED1 = 7; const int LED2 = 8; const int chipSelect = 9; const int RXPin = 4; const int TXPin = 5; int GPSBaud = 4800; TinyGPSPlus gps; SoftwareSerial gpsSerial(RXPin, TXPin); void setup() { Serial.begin(9600); gpsSerial.begin(GPSBaud); pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(chipSelect, OUTPUT); if (!SD.begin(chipSelect)) digitalWrite(LED1, LOW); else { Serial.println("SD Card Setup"); digitalWrite(LED1, HIGH); } } void loop() { while (gpsSerial.available() > 0) { if (gps.encode(gpsSerial.read())) { if (gps.location.isValid() && gps.time.isValid() && gps.date.isValid()) digitalWrite(LED2, HIGH); else digitalWrite(LED2, LOW); logInfo(); displayInfo(); } } } void logInfo() { if (gps.location.isValid() && gps.time.isValid() && gps.date.isValid()) { File dataFile = SD.open("gpslog.txt", FILE_WRITE); if (dataFile) { digitalWrite(LED1, HIGH); dataFile.print(gps.date.day()); dataFile.print(F("/")); dataFile.print(gps.date.month()); dataFile.print(F("/")); dataFile.print(gps.date.year()); dataFile.print(F(",")); if (gps.time.hour() < 10) dataFile.print(F("0")); dataFile.print(gps.time.hour()); dataFile.print(F(":")); if (gps.time.minute() < 10) dataFile.print(F("0")); dataFile.print(gps.time.minute()); dataFile.print(F(":")); if (gps.time.second() < 10) dataFile.print(F("0")); dataFile.print(gps.time.second()); dataFile.print(F(".")); if (gps.time.centisecond() < 10) dataFile.print(F("0")); dataFile.print(gps.time.centisecond()); dataFile.print(F(",")); dataFile.print(gps.location.lat(), 6); dataFile.print(F(",")); dataFile.print(gps.location.lng(), 6); dataFile.println(); dataFile.close(); } // if the file isn't open, pop up an error: else { digitalWrite(LED1, HIGH); Serial.println("error opening datalog.txt"); } } } void displayInfo() { Serial.print(F("Location: ")); if (gps.location.isValid()) { Serial.print(gps.location.lat(), 6); Serial.print(F(",")); Serial.print(gps.location.lng(), 6); } else { Serial.print(F("INVALID")); } Serial.print(F(" Date/Time: ")); if (gps.date.isValid()) { Serial.print(gps.date.day()); Serial.print(F("/")); Serial.print(gps.date.month()); Serial.print(F("/")); Serial.print(gps.date.year()); } else { Serial.print(F("INVALID")); } Serial.print(F(" ")); if (gps.time.isValid()) { if (gps.time.hour() < 10) Serial.print(F("0")); Serial.print(gps.time.hour()); Serial.print(F(":")); if (gps.time.minute() < 10) Serial.print(F("0")); Serial.print(gps.time.minute()); Serial.print(F(":")); if (gps.time.second() < 10) Serial.print(F("0")); Serial.print(gps.time.second()); Serial.print(F(".")); if (gps.time.centisecond() < 10) Serial.print(F("0")); Serial.print(gps.time.centisecond()); } else { Serial.print(F("INVALID")); } Serial.println(); }
Step 2: Testing
Now, because I am a bit of a night owl, there is not much daylight in my hackspace, so for testing I connected the solar panel up using a standard USB connector and held a light over the panel so that I can at least power up the Arduino. It just about worked but would probably be best during daylight hours.
Step 3: Mounting to the Bag
I have a 5.11 tactical Rush 24 rucksack that I use typically when I am going on my hikes, and fortunately it has a mounting standard called MOLLE for attaching their pouches. Essentially this means the backpack is covered in 1 inch loops which you can thread things through without damaging the bag. So, to attach the solar panel I used some cable ties which means they are semi permanently attached without damaging my bag.
Step 4: Hiding the Electronics
The bag has a camera pouch as the top next to the handle, which has a nice felt lining to protect the camera, so it would work well to protect the Arduino electronics. I mounted the USB connector towards the top of the bag so that the cable run was very short and neat (no cables to tidy away).
Step 5: The Finished Bag
So, here it is, only a small blue USB cable which can be plugged in and unplugged whenever it is needed or not needed. The panel is very secure, and I have even tweeked it some more with a set of reusable/resealable cable ties so that I can take the whole panel on/off when I don't need to log.

Participated in the
Explore Science Contest
7 Comments
8 years ago on Introduction
Nice 5.11 bag.
I'm also glad you like your solar panel! (We do have many still at BrownDogGadgets.com!)
Reply 8 years ago on Introduction
thanks, the solar panel works great! :)
6 years ago
Excuse my amateur question, I see that you describe the functional part of this project, however I am confused as to where the GPS data is logged to. Where can you see where you are? If you are hiking, will you need a laptop with internet connection to see where you are on google earth?
Reply 6 years ago
The GPS time and location data are saved onto the SD card which is integrated on the shield connected to the Arduino. With this configuration it is currently not possible to view the GPS information at the same time as logging, but in theory you could get a laptop and use serial (or another communications method) to obtain the GPS locations with minor changes to my Arduino code.
To view it currently on Google Earth you just need to power down the Arduino and read in the SD card on your laptop. You don't need internet if you have viewed that Area in Google Earth before (it is good at caching) and I use GPS bable to translate the CSV generated on the SD card to KML readable by Google Earth.
8 years ago
Wouldn't be a small battery or a small capacitor bank in between the PV and the arduino an improvement? I mean, if the sun goes away for any reason (even walking against the sun puts the PV in a shadowy area) the arduino would lack energy... in that way you can prevent this from happening giving some minutes of buffer energy...
Reply 8 years ago
Yes, definitely. You can even buy a USB based battery charger meant for charging your phone, so essentially that can be plugged into the solar panel and the charger output in the Arduino (essentially turning it into a UPS).
With the amount of data it is logging (I.e. whenever data is available) I found that short black outs do kill the GPS module, but it usually only takes about 20s to get a lock, so as I am only walking, it only looses a Max of 50yrds of data. If I was going faster, say on a bike, then I would certainly put a battery pack in.
8 years ago on Introduction
This is awesome! Thank you for taking the time to write a detailed instructable.