DIY Wireless GPS Datalogger for Wildlife

Dear all,

We have developed a wireless GPS datalogger for use on wildlife. Several prototypes have been built, tested and even successfully deployed. Please see Wireless GPS Datalogger and Wireless GPS Datalogger - YouTube for details of construction.

The processor is a 3.3v Arduino Pro Mini mounted on a Fritzing PCB, a solid state relay turns the power ON/OFF for the GPS module, Xbee and the micro SD card.

Power is supplied by a 3.7v 400mAh lipo. Logging a location once every 15 mins and sleeping between will allow the datalogger to function for almost one week.

Once the datalogger gets a location it writes it to the micro SD card and the Xbee transmits the datalog wirelessly. A similar datalogger, loaded with the receiving code, listens for Xbee transmissions and writes them down to its own micro SD card. You can have one receiver listening for multiple dataloggers!

A 1mW Xbee provides a wireless range of about one hundred metres and the 60mW Xbee just over 1km but at the expense of battery life (only 2 days).

My problem is this: if the GPS doesn't get a location soon after it is turned on it keeps looking and drains the battery fast!

This seems to be more of a problem when deploying in the field, due to harsh environmental conditions. When tested under clear sky they work just fine.

Can any interested person please assist me by looking at the code and suggesting improvements, I would like the code to spend an small amount of time attempting to get a location (say no more than 30 secs). If the GPS can't get a location it transmits the existing datalog from the micro SD card, then sleeps for 15 mins. If the GPS can get a location it adds that location to the datalog on the micro SD card, transmits the datalog wirelessly and then sleeps for a period of 15 mins.

The code can already do most of this, it just needs improving.

Our goal is to have an open source DIY wireless GPS datalogger for use on wildlife. If your able to provide substantial assistance I could possibly provide you with one of our prototypes for your testing.

Thanks...

// Wireless GPS Datalogger, written using examples from the following libraries by smithcs

// Load the libraries
#include <LowPower.h> // http://www.rocketscream.com/blog/2011/07/04/lightweight-low-power-arduino-library/
#include <SdFat.h> // http://code.google.com/p/sdfatlib/
#include <SoftwareSerial.h> // http://arduino.cc/en/Reference/SoftwareSerial
#include <TinyGPS.h> // http://arduiniana.org/libraries/tinygps/

// Declare variables and objects
SdFat sd;
SdFile myFile;
SoftwareSerial SS_gps(8, 9); // Declare SoftwareSerial connection for GPS
SoftwareSerial SS_xbee(2, 3); // Declare SoftwareSerial connection for Xbee
TinyGPS gps;
void getgps(TinyGPS &gps); // Write the GPS message to the datalog
void slp(); // Loop sleep for 8S
void tx_datalog(); // Send the datalog wirelessly

void setup() 
{
  // Turn the relay ON
  pinMode(7, OUTPUT);
  digitalWrite(7, HIGH);
  
  // Turn the Xbee ON
  pinMode(2, INPUT);
  pinMode(3, OUTPUT);
  SS_xbee.begin(9600);
  delay(500);
  SS_xbee.println(" ");
  
  // Send a message wirelessly
  SS_xbee.println("Wireless GPS Datalogger 10.");
  SS_xbee.println("Initializing SD card...");
  
  // Initialize SdFat or print a detailed error message and halt
  // Use half speed like the native library
  // Change to SPI_FULL_SPEED for more performance
  if (!sd.begin(10, SPI_HALF_SPEED)) sd.initErrorHalt();
  
  // Open the datalog and write at end like the Native SD library
  if (!myFile.open("Log_10.txt", O_RDWR | O_CREAT | O_AT_END))
  {
    sd.errorHalt();
  }
 
  // Create the datalog header
  myFile.println("Datalogger,Date,Time,Latitude,Longitude");
  
  // Close the datalog
  myFile.close();
  myFile.sync();
  
  // Send a message wirelessly
  SS_xbee.println("Card initialized.");
  SS_xbee.println("Waiting for GPS lock...");
  
  //Turn the GPS ON
  SS_gps.begin(9600);
  
  // Turn the Xbee OFF
  delay(500);
  SS_xbee.end();
  pinMode(2, INPUT);
  pinMode(3, INPUT);
}

void loop()
{
  // Turn the relay ON
  digitalWrite(7, HIGH);
  
  //Turn the GPS ON
  SS_gps.begin(9600);
  
  // Wait until the GPS sends a message
  while(SS_gps.available())
  {
    // Read the GPS message
    int c = SS_gps.read();
    if(gps.encode(c))
    {
      // Write the GPS message to the datalog
      getgps(gps);
      
      // Send the datalog wirelessly
      tx_datalog();
      
      // Turn the GPS OFF
      SS_gps.end();
      
      // Turn the relay OFF
      digitalWrite(7, LOW);
      
      // Loop sleep for 8S
      slp();
    }
  }
}

// Write the GPS message to the datalog
void getgps(TinyGPS &gps)
{
  //Declare variables and objects
  float latitude, longitude;
  char lat[12];
  char lon[12];
  
  // Get latitude and longitude from GPS message
  gps.f_get_position(&latitude, &longitude);
  
  // Convert longitude and latitude floats to lat and lon characters as floats cannot be added to a string
  dtostrf(latitude,1,5,lat);
  dtostrf(longitude,1,5,lon);
  
  // Declare variables and objects
  int year;
  byte month, day, hour, minute, second;
  
  // Get year, month, day, hour, minute and second from GPS message
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second);
  
  // Declare variables and objects
  String dataString = "";
  
  // Add GPS message to the datastring
  dataString += "10,";
  dataString += String(day, DEC) + "/" + String(month, DEC) + "/" + year + ",";
  dataString += String(hour, DEC) + ":" + String(minute, DEC) + ":" + String(second, DEC) + ",";
  dataString += String(lat) + "," + String(lon);

  // Open the datalog and write at end like the Native SD library
  if (!myFile.open("Log_10.txt", O_RDWR | O_AT_END))
  {
    sd.errorHalt();
  }
  
  // Add the dataString to the datalog
  myFile.println(dataString);
  
  // Close the datalog
  myFile.close();
  myFile.sync();
}

// Loop sleep for 8S
void slp()
{
  int var = 0;
  while(var < 112)
  {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
    var++;
  }
}

// Send the datalog wirelessly
void tx_datalog()
{ 

  // Turn the Xbee ON
  pinMode(2, INPUT);
  pinMode(3, OUTPUT);
  SS_xbee.begin(9600);
  delay(500);
  SS_xbee.println(" ");
  delay(500);
  SS_xbee.println(" ");
  
  // Send a messeage wirelessly
  SS_xbee.println("Begin transmission of Log_10.txt");

  // Open the datalog for reading
  if (!myFile.open("Log_10.txt", O_READ))
  {
    sd.errorHalt();
  }
  
  // Read and send the datalog wirelessly
  char data;
  while ((data = myFile.read()) >= 0)
  {
    SS_xbee.write(data);
    delay(4);
  }
  
  // Send a messeage wirelessly
  SS_xbee.println("End transmission of Log_10.txt");
  
  // Close the datalog
  myFile.close();
  myFile.sync();
  
  //Turn the Xbee OFF
  delay(500);
  SS_xbee.end();
  pinMode(2, INPUT);
  pinMode(3, INPUT);
}

If you expect a GPS to get a reading in 30 seconds, you are bound to be disappointed. All of mine take at least 2 or
3 minutes outdoors and often 10 to 15 minutes indoors. Your mileage may vary. Some have a method of backing
up some of their internal state information, so if you turn them on within a certain time, they can re-use the
information about the satellite orbits that they already had before.

Dear michinyon,

You are correct, a cold start requires at least one minute in ideal conditions using the chosen antenna http://www.glynstore.com/fastrax-up501-gps-antenna-module/

However, by using an internal battery (model UP501B) or by supplying an external power source to the GPS memory (as I do using the UP501) you retain the satellites almanac and a hot start can provide you with a location in around 7 secs.

My problem is, when you don't have ideal conditions for the GPS (because your wildlife is underground or beneath dense trees) it can't get a location but keeps looking and drains the battery. I thought someone may be able to provide me with advice on how to limit the amount of time spent looking for a location and generally want to participate in improving the code.

Thanks for your input.

Hi,

This looks like an interesting project.
We have been developing low power, 3.3V Arduino solutions along the same lines as you do, but using the Fio and Stalker boards.
We however have been using the mobile phone network (GPRS) for data transfer. This gives of course a much greater coverage.

For this purpose we have developed a GPRS module that fits in a bee slot.

See: http://www.gprsbee.com

Would you be interested to try one on your board?

reading your code it seems that your GPS unit don't send anything to the serial port until it get a position.

If I am right I believe that you have to wait for a message from GPS only for 30 seconds.

Smithcs: Great Stuff! mind to provide some details about the XBee programming? (how you configured each unit) im also using S1 Pro on a data logger but im having some Xbee issues

Thanks in advance!

Femur

Is this Project still 'live'? I guess not. Did it work ok?

I notice that some vital connections are not made in the circuit diagram when I loaded it into Fritzing.

Is there a newer Circuit?
Cheers,

Watch a video