GPS read after wake up from sleep

Our weekly LIVE video chat. Every Wednesday at 8pm ET!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
tristan74656
 
Posts: 18
Joined: Tue Mar 18, 2014 3:20 pm

GPS read after wake up from sleep

Post by tristan74656 »

Hello Experts,

i have a simple programm which should read the NMEA sentence and simply write it to a micro SD card.
Since the gps is updated with 1Hz i want to put the Arduino to sleep in the meantime. I use the WDT to wake up the Arduio after 1s and this works fine.

Problem:

after the wake up i do not get gps.newNMEAreceived().
I am new to the Arduini world and maybe its a stupid question but i got stucke here.

My Hardware:
+ Arduino Uno R3
+ Adafruit Ultimate GPS Logger Shield

My Shield:

Code: Select all

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SD.h>



//--------------------------------------------------------------------------------------------------
//                                                                                            global
//--------------------------------------------------------------------------------------------------
SoftwareSerial  softwareSerial(8, 7);
Adafruit_GPS    gps(&softwareSerial);
File            logfile;



//--------------------------------------------------------------------------------------------------
//                                                                                             setup
//--------------------------------------------------------------------------------------------------
void setup()
{
  Serial.begin(115200);
  
  pinMode(13, OUTPUT);
  pinMode(10, OUTPUT);
  
  // -> SD card initialization.
  if (0 != SD.begin(10))
  {
    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;
      
      if (0 == SD.exists(filename)) break;
    }
    
    if (0 != (logfile = SD.open(filename, FILE_WRITE)))
    {
      Serial.print("writing to file: ");
      Serial.println(filename);
    }
    else
    {
      Serial.print("could not open file: ");
      Serial.println(filename);
    }
  }
  else
  {
    Serial.println("SD card initialization failed.");
  }
  // <-
  
  // -> GPS initialization
  gps.begin(9600);
  
  gps.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  gps.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
  gps.sendCommand(PGCMD_NOANTENNA);
  // <-
  
    // -> watch dog timer
  MCUSR &= ~(1<<WDRF);  /* Clear the reset flag. */
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  WDTCSR = 1<<WDP1 | 1<<WDP2 | 0<<WDP3; /* 1.0 seconds */
  WDTCSR |= _BV(WDIE);
  // <-
  
  Serial.println("setup done.");
  delay(5);
}



//--------------------------------------------------------------------------------------------------
//                                                                                              loop
//--------------------------------------------------------------------------------------------------
void loop()
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  
  /* Now enter sleep mode. */
  sleep_mode();
  
  /* The program will continue from here after the WDT timeout*/
  sleep_disable(); /* First thing to do is disable sleep. */
  
  /* Re-enable the peripherals. */
  power_all_enable();
  
  Serial.println("wake up.");
  delay(5);
        
  gps.read();
  
  if (0 != gps.newNMEAreceived())
  {
    if (0 != gps.parse(gps.lastNMEA()))
    {
      if (0 != gps.fix)
      {
        const char*     pcSentence     = gps.lastNMEA();
        const uint8_t   uiSentenceSize = strlen(pcSentence);
        
        logfile.write((uint8_t *)pcSentence, uiSentenceSize);
        logfile.flush();
        
        Serial.println("flush.");
        delay(5);
      }
    }
  }
}



//--------------------------------------------------------------------------------------------------
//                                                                         watch dog timer interrupt
//--------------------------------------------------------------------------------------------------
ISR(WDT_vect)
{
}
Thanks

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

Re: GPS read after wake up from sleep

Post by adafruit_support_rick »

The problem is that you are only doing a single gps.read call, which will only read a single character from the GPS (assuming that there's even one available. Instead, you need to read until newNMEAreceived becomes true:

Code: Select all

  Serial.println("wake up.");
  delay(5);
 
  while (!gps.newNMEAreceived())
    gps.read();

  if (0 != gps.parse(gps.lastNMEA()))
  {
    if (0 != gps.fix)
    {
    . . . etc . . .
    }
  }

tristan74656
 
Posts: 18
Joined: Tue Mar 18, 2014 3:20 pm

Re: GPS read after wake up from sleep

Post by tristan74656 »

Thank you for your reply. This solved my problem but there is another one ;-)
I have encountered a strange behaviour when using the gps together with the WDT.

WDT only (2s sleep)
-> WDT interrupt
-> loop
-> WDT interrupt
-> loop
... which seems perfectly ok.

If i also enable the gps with 1Hz i get something like this:
WDT (2s sleep) and gps
-> WDT interrupt
-> loop
-> loop
-> loop
-> loop
-> WDT interrupt
-> loop
-> loop
-> loop
-> loop
...

I can not figure out why this is happening. But I want to learn and I am happy for any suggestions.

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

Re: GPS read after wake up from sleep

Post by adafruit_support_rick »

You're using software serial, which relies on pin-change interrupts for receiving characters from the GPS. Pin-change interrupts will wake the CPU from sleep. So, you're waking up on every character the GPS transmits.

Are you turning off the GPS while you sleep? The way to do that is to power the GPS from a digital output pin instead of from 5V. Set the pin HIGH to power the GPS, set it LOW to turn it off.

tristan74656
 
Posts: 18
Joined: Tue Mar 18, 2014 3:20 pm

Re: GPS read after wake up from sleep

Post by tristan74656 »

Thanks that explains a lot.

Since my programm has to run at least 7 days on battery power i am looking for ways to save energy. Is there a way to prevent those interrupts and read gps only in 4s interval ?

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

Re: GPS read after wake up from sleep

Post by adafruit_support_rick »

You could turn the GPS off, as I described in my earlier post, although that may not be practical if you want to maintain a rate of one sample every 4 seconds.

You might also try disabling the software serial interrupt. I don't know if it will work, but it's worth a try. Do it this way (the '8' should be the number of the pin you have set up for receive):

Code: Select all

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  *digitalPinToPCMSK(8) &= ~_BV(digitalPinToPCMSKbit(8));  //disable software serial receive interrupts
 
  /* Now enter sleep mode. */
  sleep_mode();
  
  /* The program will continue from here after the WDT timeout*/
  sleep_disable(); /* First thing to do is disable sleep. */
  *digitalPinToPCMSK(8) |= _BV(digitalPinToPCMSKbit(8));    //re-enable software serial receive interrupts

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

Return to “Ask an Engineer! VIDEO CHAT (closed)”