Need help with Adafruit Ultimate GPS Shield Code

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Savannalife
 
Posts: 10
Joined: Sun Mar 16, 2014 4:45 pm

Need help with Adafruit Ultimate GPS Shield Code

Post by Savannalife »

Hi

I am very new to programming and micro controllers. As part of my degree I would like to track buffalo. Due to the cost of commercially available gps tracking units I decided to attempt building my own. To start with I have an Arduino Uno R3 with a Adafruit Ultimate GPS shield.

I would like to log one gps location every hour, save it to the sd card, and power everything down to conserve as much power as possible. My power source will be 2 parallel AA NiMD (6 in series giving 9v at a stated 2700mAh). I can change batteries every 70 days.

I have found the following code (see below). The code seems to have been written for a previous version of the gps shield. It compiles and loads to the Arduino Uno R3 and then only gives the following in the serial monitor GPSlogger, Writing to GPSLOG12.TXT, Ready!, and does not continue with obtaining gps sentences or the sleep procedure.

I would really appreciate it someone could have a look at the code for me to tell me where I am going wrong. I have spent days trying to find a solution, but my programming knowledge is preventing me from finding a solution.

Thanks a lot.

Code: Select all

    // Ladyada's logger modified by Bill Greiman to use the SdFat library

    // this is a generic logger that does checksum testing so the data written should be always good
    // Assumes a sirf III chipset logger attached to pin 2 and 3

    #include <SD.h>
    #include <avr/sleep.h>
    #include "GPSconfig.h"
    #include <SPI.h>
    #include <Adafruit_GPS.h>
    #include <SoftwareSerial.h>
    

    // If using Arduino IDE prior to 1.0,
    // make sure to install newsoftserial from Mikal Hart
    // http://arduiniana.org/libraries/NewSoftSerial/
    #if ARDUINO >= 100
     #include <SoftwareSerial.h>
    #else
     #include <NewSoftSerial.h>
    #endif

    // power saving modes
    #define SLEEPDELAY 10
    #define TURNOFFGPS 1
    #define LOG_RMC_FIXONLY 1

    // what to log
    #define LOG_RMC 1 // RMC-Recommended Minimum Specific GNSS Data, message 103,04
    #define LOG_GGA 0 // GGA-Global Positioning System Fixed Data, message 103,00
    #define LOG_GLL 0 // GLL-Geographic Position-Latitude/Longitude, message 103,01
    #define LOG_GSA 0 // GSA-GNSS DOP and Active Satellites, message 103,02
    #define LOG_GSV 0 // GSV-GNSS Satellites in View, message 103,03
    #define LOG_VTG 0 // VTG-Course Over Ground and Ground Speed, message 103,05

//   //Set GPS Echo
//   #define GOSECHO true
//   //Set log only if gps fix
//   #define LOG_FIXONLY true

   // Use pins 8 and 7 to talk to the GPS. 8 is the TX pin, 7 is the RX pin
   SoftwareSerial gpsSerial =  SoftwareSerial(8, 7);
   #define GPSRATE 115200 //115200 works

    // Set the pins used
    #define powerPin 4
    //#define led1Pin 5
    //#define led2Pin 6
    #define ledPin 13
    #define chipSelect 10

    #define BUFFSIZE 90
    char buffer[BUFFSIZE];
    uint8_t bufferidx = 0;
    bool fix = false; // current fix data
    bool gotGPRMC;    //true if current data is a GPRMC strinng
    uint8_t i;
    File logfile;

    // read a Hex value and return the decimal equivalent
    uint8_t parseHex(char c) {
      if (c < '0')
        return 0;
      if (c <= '9')
        return c - '0';
      if (c < 'A')
        return 0;
      if (c <= 'F')
        return (c - 'A')+10;
    }

    // blink out an error code
    void error(uint8_t errno) {
    /*
      if (SD.errorCode()) {
        putstring("SD error: ");
        Serial.print(card.errorCode(), HEX);
        Serial.print(',');
        Serial.println(card.errorData(), HEX);
      }
      */
      while(1) {
        for (i=0; i<errno; i++) {
          digitalWrite(ledPin, HIGH);
          //digitalWrite(led2Pin, HIGH);
          delay(100);
          digitalWrite(ledPin, LOW);
          //digitalWrite(led2Pin, LOW);
          delay(100);
        }
        for (; i<10; i++) {
          delay(200);
        }
      }
    }

    void setup() {
      WDTCSR |= (1 << WDCE) | (1 << WDE);
      WDTCSR = 0;
      Serial.begin(115200);
      Serial.println("\r\nGPSlogger");
      pinMode(ledPin, OUTPUT);
      //pinMode(led2Pin, OUTPUT);
      pinMode(powerPin, OUTPUT);
      digitalWrite(powerPin, LOW);

      // make sure that the default chip select pin is set to
      // output, even if you don't use it:
      pinMode(10, OUTPUT);
     
      // see if the card is present and can be initialized:
      if (!SD.begin(chipSelect)) {
        Serial.println("Card init. failed!");
        error(1);
      }

      strcpy(buffer, "GPSLOG00.TXT");
      for (i = 0; i < 100; i++) {
        buffer[6] = '0' + i/10;
        buffer[7] = '0' + i%10;
        // create if does not exist, do not open existing, write, sync after write
        if (! SD.exists(buffer)) {
          break;
        }
      }

      logfile = SD.open(buffer, FILE_WRITE);
      if( ! logfile ) {
        Serial.print("Couldnt create "); Serial.println(buffer);
        error(3);
      }
      Serial.print("Writing to "); Serial.println(buffer);
     
      // connect to the GPS at the desired rate
      gpsSerial.begin(GPSRATE);
     
      Serial.println("Ready!");
     
      gpsSerial.print(SERIAL_SET);
      delay(250);

    #if (LOG_DDM == 1)
         gpsSerial.print(DDM_ON);
    #else
         gpsSerial.print(DDM_OFF);
    #endif
      delay(250);
    #if (LOG_GGA == 1)
        gpsSerial.print(GGA_ON);
    #else
        gpsSerial.print(GGA_OFF);
    #endif
      delay(250);
    #if (LOG_GLL == 1)
        gpsSerial.print(GLL_ON);
    #else
        gpsSerial.print(GLL_OFF);
    #endif
      delay(250);
    #if (LOG_GSA == 1)
        gpsSerial.print(GSA_ON);
    #else
        gpsSerial.print(GSA_OFF);
    #endif
      delay(250);
    #if (LOG_GSV == 1)
        gpsSerial.print(GSV_ON);
    #else
        gpsSerial.print(GSV_OFF);
    #endif
      delay(250);
    #if (LOG_RMC == 1)
        gpsSerial.print(RMC_ON);
    #else
        gpsSerial.print(RMC_OFF);
    #endif
      delay(250);

    #if (LOG_VTG == 1)
        gpsSerial.print(VTG_ON);
    #else
        gpsSerial.print(VTG_OFF);
    #endif
      delay(250);

    #if (USE_WAAS == 1)
        gpsSerial.print(WAAS_ON);
    #else
        gpsSerial.print(WAAS_OFF);
    #endif
    }

    void loop() {
      //Serial.println(Serial.available(), DEC);
      char c;
      uint8_t sum;

      // read one 'line'
      if (gpsSerial.available()) {
        c = gpsSerial.read();
    #if ARDUINO >= 100
        Serial.write(c);
    #else
        Serial.print(c, BYTE);
    #endif
        if (bufferidx == 0) {
          while (c != '$')
            c = gpsSerial.read(); // wait till we get a $
        }
        buffer[bufferidx] = c;

    #if ARDUINO >= 100
        Serial.write(c);
    #else
        Serial.print(c, BYTE);
    #endif
        if (c == '\n') {
          //putstring_nl("EOL");
          //Serial.print(buffer);
          buffer[bufferidx+1] = 0; // terminate it

          if (buffer[bufferidx-4] != '*') {
            // no checksum?
            Serial.print('*');
            bufferidx = 0;
            return;
          }
          // get checksum
          sum = parseHex(buffer[bufferidx-3]) * 16;
          sum += parseHex(buffer[bufferidx-2]);

          // check checksum
          for (i=1; i < (bufferidx-4); i++) {
            sum ^= buffer[i];
          }
          if (sum != 0) {
            //putstring_nl("Cxsum mismatch");
            Serial.print('~');
            bufferidx = 0;
            return;
          }
          // got good data!

          gotGPRMC = strstr(buffer, "GPRMC");
          if (gotGPRMC) {
            // find out if we got a fix
            char *p = buffer;
            p = strchr(p, ',')+1;
            p = strchr(p, ',')+1;       // skip to 3rd item
           
            if (p[0] == 'V') {
              digitalWrite(ledPin, LOW);
              fix = false;
            } else {
              digitalWrite(ledPin, HIGH);
              fix = true;
            }
          }
          if (LOG_RMC_FIXONLY) {
            if (!fix) {
              Serial.print('_');
              bufferidx = 0;
              return;
            }
          }
          // rad. lets log it!
         
          Serial.print(buffer);    //first, write it to the serial monitor
          Serial.print('#');
         
          if (gotGPRMC)      //If we have a GPRMC string
          {
            // Bill Greiman - need to write bufferidx + 1 bytes to getCR/LF
            bufferidx++;

            digitalWrite(ledPin, HIGH);      // Turn on LED 2 (indicates write to SD)

            logfile.write((uint8_t *) buffer, bufferidx);    //write the string to the SD file
            logfile.flush();
            /*
            if( != bufferidx) {
               putstring_nl("can't write!");
               error(4);
            }
            */

            digitalWrite(ledPin, LOW);    //turn off LED2

            bufferidx = 0;    //reset buffer pointer

            if ((fix) && (TURNOFFGPS)) {      // turn off GPS module? (don't turn off if thre's no fix)
             
              digitalWrite(powerPin, HIGH);  //turn off GPS


              delay(100);  //wait for serial write to finish
              sleep_sec(SLEEPDELAY);  //turn off CPU

              digitalWrite(powerPin, LOW);  //turn on GPS
            } //if ((fix) && (TURNOFFGPS))
            return;
          }//if (gotGPRMC)
        }
        bufferidx++;
        if (bufferidx == BUFFSIZE-1) {
           Serial.print('!');
           bufferidx = 0;
        }
      } else {

      }

    }

    void sleep_sec(uint8_t x) {
      while (x--) {
         // set the WDT to wake us up!
        WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
        WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1);
        WDTCSR |= (1<< WDIE);
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
     //   sleep_enable();
        sleep_mode();
    //    sleep_disable();
      }
    }

    SIGNAL(WDT_vect) {
      WDTCSR |= (1 << WDCE) | (1 << WDE);
      WDTCSR = 0;
    }

    /* End code */

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by adafruit_support_rick »

That code is for an earlier GPS module which we no longer sell. You want to use this library and the associated example code:
https://github.com/adafruit/Adafruit-GPS-Library

The new examples don't include the sleep code, but the sleep code from the older example can be adapted to work. I suggest getting your Ultimate GPS working first, and then we can worry about sleeping.

Savannalife
 
Posts: 10
Joined: Sun Mar 16, 2014 4:45 pm

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by Savannalife »

Thanks for the reply rick,

My applogies, I neglected to mention that I did get everything working using the new updated code as mentioned in your post. The uno connects to the shield and logs to the SD card at about 4 second intervals using the code below.

I would like to adapt the previous code to the new board as you mentioned with the power down integrated. The led and power pins seems to be completely changed, and I cant seem to find the relevant information. Some assistance in this regard would be greatly appreciated. If we can get this working I am thinking of buying a more basic micro controller and breakout sdlogger and gps to make the system more power efficient. Ultimately I would want to make about 50 units.

I would first have to demonstrate the feasibility of my current setup to my study leaders as they were very skeptic of the idea.

Thanks for your help.

Code: Select all

#include <SPI.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include <avr/sleep.h>

// Ladyada's logger modified by Bill Greiman to use the SdFat library
//
// This code shows how to listen to the GPS module in an interrupt
// which allows the program to have more 'freedom' - just parse
// when a new NMEA sentence is available! Then access data when
// desired.
//
// Tested and works great with the Adafruit Ultimate GPS Shield
// using MTK33x9 chipset
//    ------> http://www.adafruit.com/products/
// Pick one up today at the Adafruit electronics shop 
// and help support open source hardware & software! -ada

SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO  true
/* set to true to only log to SD when GPS has a fix, for debugging, keep it false */
#define LOG_FIXONLY false  

// Set the pins used
#define chipSelect 10
#define ledPin 13

File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// blink out an error code
void error(uint8_t errno) {
/*
  if (SD.errorCode()) {
    putstring("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  */
  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

void setup() {
  // for Leonardos, if you want to debug SD issues, uncomment this line
  // to see serial output
  //while (!Serial);
  
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
  Serial.println("\r\nUltimate GPSlogger Shield");
  pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  //if (!SD.begin(chipSelect, 11, 12, 13)) {
  if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println("Card init. failed!");
    error(2);
  }
  char filename[15];
  strcpy(filename, "GPSLOG00.TXT");
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }

  logfile = SD.open(filename, FILE_WRITE);
  if( ! logfile ) {
    Serial.print("Couldnt create "); Serial.println(filename);
    error(3);
  }
  Serial.print("Writing to "); Serial.println(filename);
  
  // connect to the GPS at the desired rate
  GPS.begin(9600);

  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For logging data, we don't suggest using anything but either RMC only or RMC+GGA
  // to keep the log files at a reasonable size
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 or 5 Hz update rate

  // Turn off updates on antenna status, if the firmware permits it
  GPS.sendCommand(PGCMD_NOANTENNA);
  
  Serial.println("Ready!");
}

void loop() {
  char c = GPS.read();
  if (GPSECHO)
     if (c)   Serial.print(c);

  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trying to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
        
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
    
    // Sentence parsed! 
    Serial.println("OK");
    if (LOG_FIXONLY && !GPS.fix) {
        Serial.print("No Fix");
        return;
    }

    // Rad. lets log it!
    Serial.println("Log");
    
    char *stringptr = GPS.lastNMEA();
    uint8_t stringsize = strlen(stringptr);
    if (stringsize != logfile.write((uint8_t *)stringptr, stringsize))    //write the string to the SD file
      error(4);
    if (strstr(stringptr, "RMC"))   logfile.flush();
    Serial.println();
  }
}



/* End code */

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by adafruit_support_rick »

OK. The first thing you want to do is determine whether or not you can run the GPS Shield from a digital I/O pin. You'll have to cut the trace between the 5V pin and the associated solder hole, then jumper a digital pin over to the 5V solder hole.

In the code, set the digital pin HIGH to power the GPS shield. GPIO pins can source 40mA. The GPS module itself takes 20mA. Not sure how much the SD card takes. It may be necessary to unsolder the FIX and PWR LEDs to save a little bit of juice.

Savannalife
 
Posts: 10
Joined: Sun Mar 16, 2014 4:45 pm

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by Savannalife »

I have now removed the pin from the 5v input and soldered a jumper wire from the digital pin 6 to the 5v power solder hole.

I adapted my code (see below) by defining pin six and setting it as HIGH. This successfully powered the shield with the SD. I also modified the code to allow it to shut the shield off for 30 seconds. This works for one round, switches off for 30 seconds after fix, switches back on but then does not switch back off after fix. It simply keeps logging at about 4 second intervals.

I would appreciate some help to sort out the problem with the shield power down after the first loop. I also would appreciate some advice on how to use the "set_sleep_mode(SLEEP_MODE_PWR_DOWN)" to power down the micro controller as well. Ultimately I would like to power everything down at 3600 second intervals. I would also like to know how to make the digits on the file name longer (6 digits).

Thanks for the help up to this point, I have made huge progress.

Code: Select all

#include <SPI.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include <avr/sleep.h>

//power savings modes
#define SLEEPDELAY 30  // How log should unit sleep in seconds
#define TURNOFFGPS 1   // GPS on or off
//#define LOG_RMC_FIXONLY 1

// Ladyada's logger modified by Bill Greiman to use the SdFat library
//
// This code shows how to listen to the GPS module in an interrupt
// which allows the program to have more 'freedom' - just parse
// when a new NMEA sentence is available! Then access data when
// desired.
//
// Tested and works great with the Adafruit Ultimate GPS Shield
// using MTK33x9 chipset
//    ------> http://www.adafruit.com/products/
// Pick one up today at the Adafruit electronics shop 
// and help support open source hardware & software! -ada

SoftwareSerial mySerial(8, 7);  //tx rx on pin 8 and 7
Adafruit_GPS GPS(&mySerial);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO  true
/* set to true to only log to SD when GPS has a fix, for debugging, keep it false */
#define LOG_FIXONLY true  

// Set the pins used
#define chipSelect 10 //default chip select
#define ledPin 13     //led is on pin 13
#define powerPin 6    //powerPin to switch the gps shield on and off

//#define BIFFSIZE 90
//char buffer[BUFFSIZE];
// uint8_t bufferidx = 0;
// bool fix = false; // current fix data
// bool gotGPRMC;    //true if current data is a GPRMC strinng
// uint8_t i;
File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// blink out an error code
void error(uint8_t errno) {
/*
  if (SD.errorCode()) {
    putstring("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  */
  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

void setup() {
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  
  WDTCSR |= (1 << WDCE) | (1 << WDE);
      WDTCSR = 0;
      Serial.begin(115200);
      Serial.println("\r\nBuffaloFMD_GPSlogger");
      pinMode(ledPin, OUTPUT);        //setup led pin as output voltage
      pinMode(powerPin, OUTPUT);     //setup power pin as output voltage
      digitalWrite(powerPin, HIGH);   //power on on shield

  //from previous onoff code
  //pinMode(powerPin, OUTPUT);      // sets the digital pin as output
  //digitalWrite(powerPin, HIGH);   // sets the digital pin as active 5v
  //Serial.begin(115200);
  //Serial.println("\r\nUltimate GPSlogger Shield");
  //pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect, 11, 12, 13)) {
  //if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println("Card init. failed!");
    error(1);
  }
  
  char filename[15]; 
  strcpy(filename, "GPSLOG00.TXT");  //the digists needs to be more 000000
  //strcpy(buffer, "GPSLOG00.TXT");
  for (uint8_t i = 0; i < 100; i++) {
  //for (i = 0; i < 100; i++){ 
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
    //if (! SD.exists(buffer)) {
      break;
    }
  }

  logfile = SD.open(filename, FILE_WRITE);
  //logfile = SD.open(buffer, FILE_WRITE);
  if( ! logfile ) {
    Serial.print("Couldnt create "); Serial.println(filename);
    //Serial.print("Couldnt create "); Serial.println(buffer);
    error(3);
  }
  Serial.print("Writing to "); Serial.println(filename);
  //Serial.print("Writing to "); Serial.println(buffer);
  
  // connect to the GPS at the desired rate
  GPS.begin(9600);

  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For logging data, we don't suggest using anything but either RMC only or RMC+GGA
  // to keep the log files at a reasonable size
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 or 5 Hz update rate

  // Turn off updates on antenna status, if the firmware permits it
  GPS.sendCommand(PGCMD_NOANTENNA);
  
  Serial.println("Ready!");
}

void loop() {
  char c = GPS.read();
  if (GPSECHO)
     if (c)   Serial.print(c);

  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trying to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
        
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
    
    // Sentence parsed! 
    Serial.println("OK");
    if (LOG_FIXONLY && !GPS.fix) {
        Serial.print("No Fix");
        return;
    }

    // Rad. lets log it!
    Serial.println("Log");
    
    char *stringptr = GPS.lastNMEA();
    uint8_t stringsize = strlen(stringptr);
    if (stringsize != logfile.write((uint8_t *)stringptr, stringsize))    //write the string to the SD file
      error(4);
    if (strstr(stringptr, "RMC"))   logfile.flush();
    Serial.println();
    
    if ((GPS.fix) && (TURNOFFGPS)){  //turn off GPS shield (don't turn off if no fix)
      digitalWrite(powerPin, LOW);  //turn off gps
      delay(100); //wait for serial write to finish
      sleep_sec(SLEEPDELAY); //turn off CPU
      digitalWrite(powerPin, HIGH); //turn on GPS
    }
    return;
  }
}
//void sleep_sec(uint8_t x) {
//      while (x--) {
//         // set the WDT to wake us up!
//        WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
//        WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1);
//        WDTCSR |= (1<< WDIE);
//        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
//        //sleep_enable();
//        sleep_mode();
//        //sleep_disable();
//      }
//    }
//
//    SIGNAL(WDT_vect) {
//      WDTCSR |= (1 << WDCE) | (1 << WDE);
//      WDTCSR = 0;
//    }

/* End code */

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by adafruit_support_rick »

Calling sleep_sec(3600) is all you need to do to power down the whole shebang for an hour. Note that there's no way to totally power it down and have it wake up after an hour. The processor will be in a low-power mode which shuts off just about everything but keeps the watchdog timer awake. Also, the watchdog will wake the processor up completely once per second, just for long enough to check whether or not the sleep delay period has expired.On the whole, the processor will wake up for a few microseconds once each second.

Now the code you posted can't be the code that doesn't work, as it doesn't compile (that's because sleep_sec is commented out).

Can you post the code that turns off the GPS for 30 seconds, and then fails to turn it off again?

Savannalife
 
Posts: 10
Joined: Sun Mar 16, 2014 4:45 pm

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by Savannalife »

sorry, I though that part of the code did not do anything. See attached for code that compiles.

Ok, then I need advice on:

- how to tell the unit to go to sleep on the second cycle? It appears that it does not execute that part of the code again.
- how to set more digits in the file name ?

Thanks

Code: Select all

#include <SPI.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include <avr/sleep.h>

//power savings modes
#define SLEEPDELAY 10  // How long should unit sleep in seconds
#define TURNOFFGPS 1   // GPS on or off
//#define LOG_RMC_FIXONLY 1

// Ladyada's logger modified by Bill Greiman to use the SdFat library
//
// This code shows how to listen to the GPS module in an interrupt
// which allows the program to have more 'freedom' - just parse
// when a new NMEA sentence is available! Then access data when
// desired.
//
// Tested and works great with the Adafruit Ultimate GPS Shield
// using MTK33x9 chipset
//    ------> http://www.adafruit.com/products/
// Pick one up today at the Adafruit electronics shop 
// and help support open source hardware & software! -ada

SoftwareSerial mySerial(8, 7);  //tx rx on pin 8 and 7
Adafruit_GPS GPS(&mySerial);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO  true
/* set to true to only log to SD when GPS has a fix, for debugging, keep it false */
#define LOG_FIXONLY true  

// Set the pins used
#define chipSelect 10 //default chip select
#define ledPin 13     //led is on pin 13
#define powerPin 6    //powerPin to switch the gps shield on and off

//#define BIFFSIZE 90
//char buffer[BUFFSIZE];
// uint8_t bufferidx = 0;
// bool fix = false; // current fix data
// bool gotGPRMC;    //true if current data is a GPRMC strinng
// uint8_t i;
File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// blink out an error code
void error(uint8_t errno) {
/*
  if (SD.errorCode()) {
    putstring("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  */
  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(100);
      digitalWrite(ledPin, LOW);
      delay(100);
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

void setup() {
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  
  WDTCSR |= (1 << WDCE) | (1 << WDE);
      WDTCSR = 0;
      Serial.begin(115200);
      Serial.println("\r\nBuffaloFMD_GPSlogger");
      pinMode(ledPin, OUTPUT);        //setup led pin as output voltage
      pinMode(powerPin, OUTPUT);     //setup power pin as output voltage
      digitalWrite(powerPin, HIGH);   //power on on shield

  //from previous onoff code
  //pinMode(powerPin, OUTPUT);      // sets the digital pin as output
  //digitalWrite(powerPin, HIGH);   // sets the digital pin as active 5v
  //Serial.begin(115200);
  //Serial.println("\r\nUltimate GPSlogger Shield");
  //pinMode(ledPin, OUTPUT);

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect, 11, 12, 13)) {
  //if (!SD.begin(chipSelect)) {      // if you're using an UNO, you can use this line instead
    Serial.println("Card init. failed!");
    error(1);
  }
  
  char filename[15]; 
  strcpy(filename, "GPSLOG00.TXT");  //the digists needs to be more 000000
  //strcpy(buffer, "GPSLOG00.TXT");
  for (uint8_t i = 0; i < 100; i++) {
  //for (i = 0; i < 100; i++){ 
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
    //if (! SD.exists(buffer)) {
      break;
    }
  }

  logfile = SD.open(filename, FILE_WRITE);
  //logfile = SD.open(buffer, FILE_WRITE);
  if( ! logfile ) {
    Serial.print("Couldnt create "); Serial.println(filename);
    //Serial.print("Couldnt create "); Serial.println(buffer);
    error(3);
  }
  Serial.print("Writing to "); Serial.println(filename);
  //Serial.print("Writing to "); Serial.println(buffer);
  
  // connect to the GPS at the desired rate
  GPS.begin(9600);

  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For logging data, we don't suggest using anything but either RMC only or RMC+GGA
  // to keep the log files at a reasonable size
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 or 5 Hz update rate

  // Turn off updates on antenna status, if the firmware permits it
  GPS.sendCommand(PGCMD_NOANTENNA);
  
  Serial.println("Ready!");
}

void loop() {
  char c = GPS.read();
  if (GPSECHO)
     if (c)   Serial.print(c);

  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trying to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
        
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
    
    // Sentence parsed! 
    Serial.println("OK");
    if (LOG_FIXONLY && !GPS.fix) {
        Serial.print("No Fix");
        return;
    }

    // Rad. lets log it!
    Serial.println("Log");
    
    char *stringptr = GPS.lastNMEA();
    uint8_t stringsize = strlen(stringptr);
    if (stringsize != logfile.write((uint8_t *)stringptr, stringsize))    //write the string to the SD file
      error(4);
    if (strstr(stringptr, "RMC"))   logfile.flush();
    Serial.println();
    
    if ((GPS.fix) && (TURNOFFGPS)){  //turn off GPS shield (don't turn off if no fix)
      digitalWrite(powerPin, LOW);  //turn off gps
      delay(100); //wait for serial write to finish
      sleep_sec(SLEEPDELAY); //turn off CPU
      digitalWrite(powerPin, HIGH); //turn on GPS
    }
    return;
  }
}
void sleep_sec(uint8_t x) {
      while (x--) {
         // set the WDT to wake us up!
        WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
        WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1);
        WDTCSR |= (1<< WDIE);
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        //sleep_enable();
        sleep_mode();
        //sleep_disable();
      }
    }

    SIGNAL(WDT_vect) {
      WDTCSR |= (1 << WDCE) | (1 << WDE);
      WDTCSR = 0;
    }

/* End code */

Savannalife
 
Posts: 10
Joined: Sun Mar 16, 2014 4:45 pm

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by Savannalife »

I think I have located the problem with logging after the first loop. The l13 led blinks out error 4 from my code. It appears that it cant append the original file. All the files only contains the one parsed line.

I have no idea how to fix this.....

Thanks

Code: Select all

/*METADATA

Code originally written by Ladyada's and modified by Bill Greiman
to use the SdFat library. This code shows how to listen to the GPS
module in an interrupt which allows the program to have more 
'freedom' - just parse when a new NMEA sentence is available!

The code also allows for the activation of sleep mode to power down 
the gps shield and micro controller to save energy.

Code was adapted to new Ultimate GPS Shield and UNO R3 in 03/2014.

*/

//LIBRARIES TO INCLUDE
#include <SPI.h> //for SD card attached to SPI bus
#include <Adafruit_GPS.h>  //for GPS controll
#include <SoftwareSerial.h>  //for Serial communications
#include <SD.h>  //for writing to SD card
#include <avr/sleep.h>  //for the sleep functionality

//power savings modes
#define SLEEPDELAY 10  // How long unit sleep in seconds
#define TURNOFFGPS 1   // GPS on or off

SoftwareSerial mySerial(8, 7);  //tx/rx on pin 8 and 7
Adafruit_GPS GPS(&mySerial);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO  true
/* set to true to only log to SD when GPS has a fix, for debugging, keep it false */
#define LOG_FIXONLY true  

// Set the pins used
#define chipSelect 10 //default chip select
#define ledPin 13     //led is on pin 13
#define powerPin 6    //powerPin to switch the gps shield on and off

File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// blink out an error code
// the error number will blink out e.g. error 2 blinks twice
// error1 = card init failed
// error2 = file create failed
// error4 = stringsize error, can't apped to file
void error(uint8_t errno) {
    while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(200); //delay between blinks
      digitalWrite(ledPin, LOW);
      delay(200); //delay between blinks
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

//SETUP START

void setup() {

  WDTCSR |= (1 << WDCE) | (1 << WDE);
  WDTCSR = 0;
  Serial.begin(115200); //connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  Serial.println("\r\nBuffaloFMD_GPSlogger");
  pinMode(ledPin, OUTPUT);        //setup led pin as output voltage
  pinMode(powerPin, OUTPUT);     //setup power pin as output voltage
  digitalWrite(powerPin, HIGH);   //power on on shield

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  /* SD card attached to SPI bus as follows:
     UNO:  MOSI - pin 11, MISO - pin 12,
     CLK - pin 13
  */
    if (!SD.begin(chipSelect, 11, 12, 13)) {
    Serial.println("Card init. failed! (Error_1)");
    error(1);
  }
  Serial.println("Card initialised");
  
  char filename[15]; 
  strcpy(filename, "GPSLOG00.TXT");  //the digits needs to be more 000000
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = '0' + i/10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
    break;
    }
  }

  logfile = SD.open(filename, FILE_WRITE);
  if( ! logfile ) {
    Serial.print("Could not create (Error_2) "); Serial.println(filename);
    error(2);
  }
  Serial.print("Writing to "); Serial.println(filename);
    
  // connect to the GPS at the desired rate
  GPS.begin(9600);

  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For logging data, we don't suggest using anything but either RMC only or RMC+GGA
  // to keep the log files at a reasonable size
  
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 or 5 Hz update rate

  // Turn off updates on antenna status, if the firmware permits it
  GPS.sendCommand(PGCMD_NOANTENNA);
  
  Serial.println("Ready!");
}

//SETUP FINISHED

//START OF LOOP

void loop() {
  char c = GPS.read();
  if (GPSECHO)
  if (c)   Serial.print(c);

  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trying to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
        
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
    
    // Sentence parsed! 
    //Serial.println("OK Parsed");
    if (LOG_FIXONLY && !GPS.fix) {
        Serial.println("No Fix");
        return;
    }

    // Rad. lets log it!
    Serial.println("Log to card");
    char *stringptr = GPS.lastNMEA();
    uint8_t stringsize = strlen(stringptr);
    if (stringsize != logfile.write((uint8_t *)stringptr, stringsize)){
      error(4);
      Serial.println("Error_4");} 
    if (strstr(stringptr, "RMC"))   logfile.flush();  //save data to card 
    Serial.println("Done");
    
    if ((GPS.fix) && (TURNOFFGPS)){  //turn off GPS shield (don't turn off if no fix)
      digitalWrite(powerPin, LOW);  //turn off gps
      delay(100); //wait for serial write to finish
      sleep_sec(SLEEPDELAY); //turn off CPU
      digitalWrite(powerPin, HIGH); //turn on GPS
      }
 }
}

//END OF LOOP

//START OF SLEEP
 
void sleep_sec(uint8_t x) {
      while (x--) {
         // set the WDT to wake us up!
        WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
        WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1);
        WDTCSR |= (1<< WDIE);
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        //sleep_enable();
        sleep_mode();
        //sleep_disable();
      }
    }

    SIGNAL(WDT_vect) {
      WDTCSR |= (1 << WDCE) | (1 << WDE);
      WDTCSR = 0;
    }
    
//END OF SLEEP


/* End code */

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by adafruit_support_rick »

Not sure what to tell you. Your code is working here for me. It goes to sleep for 10 seconds, wakes up, reinitializes the GPS, waits for a fix, logs it, and goes back to sleep.

BTW, If you want to sleep for an hour at a time, I would recommend changing sleep_sec as follows. This sets the watchdog timer for an 8 second timeout vs. 1 second, so you will only wake up 450 times/hour vs 3600 times. Saves a little extra juice.

Code: Select all

//START OF SLEEP
 
void sleep_sec(int16_t x) {
      while (0 < x) {
         // set the WDT to wake us up!
        WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
        WDTCSR = (1<< WDE) | (1 <<WDP3) | (1 << WDP0);
        WDTCSR |= (1<< WDIE);
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   //     sleep_enable();
        sleep_mode();
   //     sleep_disable();
        x = x - 8;
      }
    }

    SIGNAL(WDT_vect) {
      WDTCSR |= (1 << WDCE) | (1 << WDE);
      WDTCSR = 0;
    }
    
//END OF SLEEP
Now, about the filename. This will give you 5 digits:

Code: Select all

  char filename[15]; 
  strcpy(filename, "GPS00000.TXT");  //the digits needs to be more 000000
  for (long i = 0; i < 100000; i++) {
    filename[3] = '0' + i/10000;
    filename[4] = '0' + (i%10000) / 1000;
    filename[5] = '0' + (i%1000) / 100;
    filename[6] = '0' + (i%100) / 10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
    break;
    }

Savannalife
 
Posts: 10
Joined: Sun Mar 16, 2014 4:45 pm

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by Savannalife »

Thank you for the suggested changes and very patient replies. I have implemented them and they have been tremendously helpfull.

I am still struggling with the write to sd card after the first loop. Is there anything that can change after the micro controller sleeps (e.g. clearing the SPRAM) that might cause this? I am using windows 7 on a 64bit system. Might that explain why it works on your system and not mine? The problem lies in this piece of code:

Code: Select all

char *stringptr = GPS.lastNMEA();
    uint8_t stringsize = strlen(stringptr);
    if (stringsize != logfile.write((uint8_t *)stringptr, stringsize)){
      Serial.println("Error_4");
      error(4);
      } 
The stringsize in the current string does not match the previous string.

In this example code for the older shield, I see they implement a buffer. Might this be related to my problem?

Code: Select all

/* Code starts here - call it GPSLogger_v2.1 :) */

// this is a generic logger that does checksum testing so the data written should be always good
// Assumes a sirf III chipset logger attached to pin 0 and 1

#include "AF_SDLog.h"
#include "util.h"
#include <avr/pgmspace.h>
#include <avr/sleep.h>

// power saving modes
#define SLEEPDELAY 0
#define TURNOFFGPS 0
#define LOG_RMC_FIXONLY 1

AF_SDLog card;
File f;

#define led1Pin 4
#define led2Pin 3
#define powerPin 2

#define BUFFSIZE 75
char buffer[BUFFSIZE];
uint8_t bufferidx = 0;
uint8_t fix = 0; // current fix data
uint8_t i;

/* EXAMPLE

$PSRF103,<msg>,<mode>,<rate>,<cksumEnable>*CKSUM<CR><LF>

<msg> 00=GGA,01=GLL,02=GSA,03=GSV,04=RMC,05=VTG
<mode> 00=SetRate,01=Query
<rate> Output every <rate>seconds, off=00,max=255
<cksumEnable> 00=disable Checksum,01=Enable checksum for specified message
Note: checksum is required

Example 1: Query the GGA message with checksum enabled
$PSRF103,00,01,00,01*25

Example 2: Enable VTG message for a 1Hz constant output with checksum enabled
$PSRF103,05,00,01,01*20

Example 3: Disable VTG message
$PSRF103,05,00,00,01*21

*/

#define SERIAL_SET   "$PSRF100,01,4800,08,01,00*0E\r\n"

// GGA-Global Positioning System Fixed Data, message 103,00
#define LOG_GGA 0
#define GGA_ON   "$PSRF103,00,00,01,01*25\r\n"
#define GGA_OFF  "$PSRF103,00,00,00,01*24\r\n"

// GLL-Geographic Position-Latitude/Longitude, message 103,01
#define LOG_GLL 0
#define GLL_ON   "$PSRF103,01,00,01,01*26\r\n"
#define GLL_OFF  "$PSRF103,01,00,00,01*27\r\n"

// GSA-GNSS DOP and Active Satellites, message 103,02
#define LOG_GSA 0
#define GSA_ON   "$PSRF103,02,00,01,01*27\r\n"
#define GSA_OFF  "$PSRF103,02,00,00,01*26\r\n"

// GSV-GNSS Satellites in View, message 103,03
#define LOG_GSV 0
#define GSV_ON   "$PSRF103,03,00,01,01*26\r\n"
#define GSV_OFF  "$PSRF103,03,00,00,01*27\r\n"

// RMC-Recommended Minimum Specific GNSS Data, message 103,04
#define LOG_RMC 1
#define RMC_ON   "$PSRF103,04,00,01,01*21\r\n"
#define RMC_OFF  "$PSRF103,04,00,00,01*20\r\n"

// VTG-Course Over Ground and Ground Speed, message 103,05
#define LOG_VTG 0
#define VTG_ON   "$PSRF103,05,00,01,01*20\r\n"
#define VTG_OFF  "$PSRF103,05,00,00,01*21\r\n"

// Switch Development Data Messages On/Off, message 105
#define LOG_DDM 1
#define DDM_ON   "$PSRF105,01*3E\r\n"
#define DDM_OFF  "$PSRF105,00*3F\r\n"

#define USE_WAAS   0     // useful in US, but slower fix
#define WAAS_ON    "$PSRF151,01*3F\r\n"       // the command for turning on WAAS
#define WAAS_OFF   "$PSRF151,00*3E\r\n"       // the command for turning off WAAS


// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// blink out an error code
void error(uint8_t errno) {
  while(1) {
    for (i=0; i<errno; i++) {
      digitalWrite(led1Pin, HIGH);
      digitalWrite(led2Pin, HIGH);
      delay(100);
      digitalWrite(led1Pin, LOW);
      digitalWrite(led2Pin, LOW);
      delay(100);
    }
    for (; i<10; i++) {
      delay(200);
    }
  }
}

void setup()
{
  WDTCSR |= (1 << WDCE) | (1 << WDE);
  WDTCSR = 0;
  Serial.begin(4800);
  putstring_nl("\r\nGPSlogger");
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(powerPin, OUTPUT);
  digitalWrite(powerPin, LOW);

  if (!card.init_card()) {
    putstring_nl("Card init. failed!");
    error(1);
  }
  if (!card.open_partition()) {
    putstring_nl("No partition!");
    error(2);
  }
  if (!card.open_filesys()) {
    putstring_nl("Can't open filesys");
    error(3);
  }
  if (!card.open_dir("/")) {
    putstring_nl("Can't open /");
    error(4);
  }

  strcpy(buffer, "GPSLOG00.TXT");
  for (buffer[6] = '0'; buffer[6] <= '9'; buffer[6]++) {
    for (buffer[7] = '0'; buffer[7] <= '9'; buffer[7]++) {
      //putstring("\ntrying to open ");Serial.println(buffer);
      f = card.open_file(buffer);
      if (!f)
        break;
      card.close_file(f);
    }
    if (!f)
      break;
  }

  if(!card.create_file(buffer)) {
    putstring("couldnt create ");
    Serial.println(buffer);
    error(5);
  }
  f = card.open_file(buffer);
  if (!f) {
    putstring("error opening ");
    Serial.println(buffer);
    card.close_file(f);
    error(6);
  }
  putstring("writing to ");
  Serial.println(buffer);
  putstring_nl("ready!");

  putstring(SERIAL_SET);
  delay(250);

  if (LOG_DDM)
    putstring(DDM_ON);
  else
    putstring(DDM_OFF);
  delay(250);

  if (LOG_GGA)
    putstring(GGA_ON);
  else
    putstring(GGA_OFF);
  delay(250);

  if (LOG_GLL)
    putstring(GLL_ON);
  else
    putstring(GLL_OFF);
  delay(250);

  if (LOG_GSA)
    putstring(GSA_ON);
  else
    putstring(GSA_OFF);
  delay(250);

  if (LOG_GSV)
    putstring(GSV_ON);
  else
    putstring(GSV_OFF);
  delay(250);

  if (LOG_RMC)
    putstring(RMC_ON);
  else
    putstring(RMC_OFF);
  delay(250);

  if (LOG_VTG)
    putstring(VTG_ON);
  else
    putstring(VTG_OFF);
  delay(250);

  if (USE_WAAS)
    putstring(WAAS_ON);
  else
    putstring(WAAS_OFF);
}

void loop()
{
  //Serial.println(Serial.available(), DEC);
  char c;
  uint8_t sum;

  // read one 'line'
  if (Serial.available()) {
    c = Serial.read();
    //Serial.print(c, BYTE);
    if (bufferidx == 0) {
      while (c != '$')
        c = Serial.read(); // wait till we get a $
    }
    buffer[bufferidx] = c;

    //Serial.print(c, BYTE);
    if (c == '\n') {
      //putstring_nl("EOL");
      //Serial.print(buffer);
      buffer[bufferidx+1] = 0; // terminate it

      if (buffer[bufferidx-4] != '*') {
        // no checksum?
        Serial.print('*', BYTE);
        bufferidx = 0;
        return;
      }
      // get checksum
      sum = parseHex(buffer[bufferidx-3]) * 16;
      sum += parseHex(buffer[bufferidx-2]);

      // check checksum
      for (i=1; i < (bufferidx-4); i++) {
        sum ^= buffer[i];
      }
      if (sum != 0) {
        //putstring_nl("Cxsum mismatch");
        Serial.print('~', BYTE);
        bufferidx = 0;
        return;
      }
      // got good data!

      if (strstr(buffer, "GPRMC")) {
        // find out if we got a fix
        char *p = buffer;
        p = strchr(p, ',')+1;
        p = strchr(p, ',')+1;       // skip to 3rd item

        if (p[0] == 'V') {
          digitalWrite(led1Pin, LOW);
          fix = 0;
        } else {
          digitalWrite(led1Pin, HIGH);
          fix = 1;
        }
      }
      if (LOG_RMC_FIXONLY) {
        if (!fix) {
          Serial.print('_', BYTE);
          bufferidx = 0;
          return;
        }
      }
      // rad. lets log it!
      Serial.print(buffer);
      Serial.print('#', BYTE);
      digitalWrite(led2Pin, HIGH);      // sets the digital pin as output

      if(card.write_file(f, (uint8_t *) buffer, bufferidx) != bufferidx) {
         putstring_nl("can't write!");
    return;
      }

      digitalWrite(led2Pin, LOW);

      bufferidx = 0;

      // turn off GPS module?
      if (TURNOFFGPS) {
        digitalWrite(powerPin, HIGH);
      }

      sleep_sec(SLEEPDELAY);
      digitalWrite(powerPin, LOW);
      return;
    }
    bufferidx++;
    if (bufferidx == BUFFSIZE-1) {
       Serial.print('!', BYTE);
       bufferidx = 0;
    }
  } else {

  }

}

void sleep_sec(uint8_t x) {
  while (x--) {
     // set the WDT to wake us up!
    WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
    WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1);
    WDTCSR |= (1<< WDIE);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_mode();
    sleep_disable();
  }
}

SIGNAL(WDT_vect) {
  WDTCSR |= (1 << WDCE) | (1 << WDE);
  WDTCSR = 0;
}

/* End code */

Any ideas to nudge me in the right direction is welcome.
Thank you again for all the help, much appreciated.

Savannalife
 
Posts: 10
Joined: Sun Mar 16, 2014 4:45 pm

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by Savannalife »

When I run my code with these two print lines I get:

Serial.println(stringsize); = 71
Serial.println(logfile.write((uint8_t *)stringptr, stringsize)); =71

during the first loop. During the second loop I get:

Serial.println(stringsize); = 71
Serial.println(logfile.write((uint8_t *)stringptr, stringsize)); = 0

This is why the code will not run during the socond loop due to:

Code: Select all

if (stringsize != logfile.write((uint8_t *)stringptr, stringsize)){
      Serial.println("Error_4");
      error(4);
      } 
If I comment this out the code runs but nothing gets logged to the card.

Any ideas on what may cause this?

Thanks

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by adafruit_support_rick »

I have no idea. Like I said, I'm running the exact code you posted earlier, and it just works.

Have you changed anything recently? Maybe post your code again?

After it sleeps, how long does it take for you to get a new fix? Mine typically goes through 4 - 8 cycles of "No Fix" before it gets a fix, logs and sleeps again.

Never mind...I was wondering if there was some issue with getting a fix too quickly, but I just saw an example go by where I got a fix immediately upon waking up.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by adafruit_support_rick »

Just occurred to me - are you cutting the power to the SD card reader? I'm not doing that. I only have the GPS running off of pin 6. My SD breakout is connected to 5V.

Savannalife
 
Posts: 10
Joined: Sun Mar 16, 2014 4:45 pm

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by Savannalife »

I cut the power to the entire shield. I removed the metal pin from the 5v pin and installed a jumper wire from pin 6 to the 5v solder hole. When pin 6 low power to the entire shield including the sd card is cut. I inserted a second delay to ensure that the data is written to the sd card completely.

My code as it currently stands:

Code: Select all

/*METADATA

Code originally written by Ladyada's and modified by Bill Greiman
to use the SdFat library. This code shows how to listen to the GPS
module in an interrupt which allows the program to have more 
'freedom' - just parse when a new NMEA sentence is available!

The code also allows for the activation of sleep mode to power down 
the gps shield and micro controller to save energy.

Code was adapted to new Ultimate GPS Shield and UNO R3 in 03/2014 by
Buffalo FMD Research with help from Adafruit support (user: adafruit_support_rick).

This code is in the public domain.

*/

//LIBRARIES TO INCLUDE
#include <SPI.h> //for SD card attached to SPI bus
#include <Adafruit_GPS.h>  //for GPS controll
#include <SoftwareSerial.h>  //for Serial communications
#include <SD.h>  //for writing to SD card
#include <avr/sleep.h>  //for the sleep functionality

//POWER SAVINGS MODE
#define SLEEPDELAY 10  // How long unit sleep in seconds
#define TURNOFFGPS 1   // GPS on or off

SoftwareSerial mySerial(8, 7);  //tx/rx on pin 8 and 7
Adafruit_GPS GPS(&mySerial);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO  true
/* set to true to only log to SD when GPS has a fix, for debugging, keep it false */
#define LOG_FIXONLY true  

//SET THE PINS USED
#define chipSelect 10 //default chip select
#define ledPin 13     //led is on pin 13
#define powerPin 6    //powerPin to switch the gps shield on and off

//SET FILE
File logfile;

// read a Hex value and return the decimal equivalent
uint8_t parseHex(char c) {
  if (c < '0')
    return 0;
  if (c <= '9')
    return c - '0';
  if (c < 'A')
    return 0;
  if (c <= 'F')
    return (c - 'A')+10;
}

// ERROR CODE
// the error number will blink out e.g. error 2 blinks twice
// error1 = card init failed
// error2 = file create failed
// error4 = stringsize error, can't apped to file
void error(uint8_t errno) {
    while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(ledPin, HIGH);
      delay(200); //delay between blinks
      digitalWrite(ledPin, LOW);
      delay(200); //delay between blinks
    }
    for (i=errno; i<10; i++) {
      delay(200);
    }
  }
}

//SETUP START

void setup() {

  WDTCSR |= (1 << WDCE) | (1 << WDE);
  WDTCSR = 0;
  Serial.begin(115200); //connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  Serial.println("\r\nBuffaloFMD_GPSlogger");
  pinMode(ledPin, OUTPUT);        //setup led pin as output voltage
  pinMode(powerPin, OUTPUT);     //setup power pin as output voltage
  digitalWrite(powerPin, HIGH);   //power on on shield

  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  /* SD card attached to SPI bus as follows:
     UNO:  MOSI - pin 11, MISO - pin 12,
     CLK - pin 13
  */
    if (!SD.begin(chipSelect, 11, 12, 13)) {
    Serial.println("Card init. failed! (Error_1)");
    error(1);
  }
  Serial.println("Card initialised");
  
  char filename[15];
  strcpy(filename, "GPS00000.TXT");  //can only be 8 char long (8.3 file format  
  for (long i = 0; i < 100000; i++) {
    filename[3] = '0' + i/10000;
    filename[4] = '0' + (i%10000) / 1000;
    filename[5] = '0' + (i%1000) / 100;
    filename[6] = '0' + (i%100) / 10;
    filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
    break;
    }
  }

  logfile = SD.open(filename, FILE_WRITE);
  if( ! logfile ) {
    Serial.print("Could not create (Error_2) "); Serial.println(filename);
    error(2);
  }
  Serial.print("Writing to "); Serial.println(filename);
    
  // connect to the GPS at the desired rate
  GPS.begin(9600);

  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For logging data, we don't suggest using anything but either RMC only or RMC+GGA
  // to keep the log files at a reasonable size
  
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 or 5 Hz update rate

  // Turn off updates on antenna status, if the firmware permits it
  GPS.sendCommand(PGCMD_NOANTENNA);
  
  Serial.println("Ready!");
}

//SETUP FINISHED

//START OF LOOP

void loop() {
  char c = GPS.read();
  if (GPSECHO)
  if (c)   Serial.print(c);

  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trying to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
        
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
    
    // Sentence parsed! 
    //Serial.println("OK Parsed");
    if (LOG_FIXONLY && !GPS.fix) {
        Serial.println("No Fix");
        return;
    }

    // Rad. lets log it!
    Serial.print("Attempt Log to card.....");
    char *stringptr = GPS.lastNMEA();
    uint8_t stringsize = strlen(stringptr);
    
    Serial.println();
    Serial.println(stringsize);
    Serial.println(logfile.write((uint8_t *)stringptr, stringsize));
    Serial.println();
    
    if (stringsize != logfile.write((uint8_t *)stringptr, stringsize)){
    //if (stringsize != logfile.write((uint8_t *)stringptr, stringsize)){
      Serial.println("Error_4");
      error(4);
      } 
    if (strstr(stringptr, "RMC")){
    logfile.flush();  //save data to card 
    Serial.println("DONE");
    Serial.println();  
  }
    
    
    
    if ((GPS.fix) && (TURNOFFGPS)){  //turn off GPS shield (don't turn off if no fix)
      delay(1000); //wait for serial write to finish in ms
      digitalWrite(powerPin, LOW);  //turn off gps
      //delay(5000); //wait for serial write to finish in ms
      sleep_sec(SLEEPDELAY); //turn off CPU
      digitalWrite(powerPin, HIGH); //turn on GPS
      //logfile = SD.open(filename, FILE_WRITE);
     }
 }
}

//END OF LOOP

//START OF SLEEP
 
void sleep_sec(int16_t x) {
      while (0 < x) {
         // set the WDT to wake us up!
        WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
        WDTCSR = (1<< WDE) | (1 <<WDP3) | (1 << WDP0);
        WDTCSR |= (1<< WDIE);
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   //     sleep_enable();
        sleep_mode();
   //     sleep_disable();
        x = x - 8;
      }
    }

    SIGNAL(WDT_vect) {
      WDTCSR |= (1 << WDCE) | (1 << WDE);
      WDTCSR = 0;
    }
   
//END OF SLEEP





/* End code */

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Need help with Adafruit Ultimate GPS Shield Code

Post by adafruit_support_rick »

OK. I don't want to hack my shield, so I'm doing this with breakout boards. I'll reconfigure my stuff to cut the power to the SD breakout, and see what happens. I'll try to get to it today...

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”