Seeduino Stalker V3 Loop Hanging after Sleep cycle

Hi
I am new to this whole thing so I'm on a steep learning curve here, I have a Seeduino Stalker V3 Datalogger and a Maxbotix 7360 ultrasonic range finder, put together and My goal is to Log the serial output from the rangefinder every 10 sec and record it to the SD card,
The code I have so far does everything well but wont seem to do more that one data entry to the SD card and will the hang.
the serial data output get as far as printing
sleep
awake from sleep
All I can think of is that something that is turned off or unset when the arduino goes to sleep isn't being woken up again the next time round. but I cant seem to find the issue.
Any help really appreciated!

/*
Used to Read MaxSonar MB7360 HRXL
Written for SEEDUINO STALKER V3
Will be using the serial Data pin output on the sensor MB7360HRXL 3.3V Supply from stalker with power filter and pin 11 softwareserial data input 
1.Solder P3 and P2 PCB jumper pads on the Stalker V3
2.Compile and upload the sketch
3.See if everything works fine using Serial Monitor.
4.Remove all Serial port code, recompile the sketch and upload.
 This reduces power consumption during battery mode.
*/

#include <avr/sleep.h> 
#include <avr/power.h>
#include <avr/power.h>
#include <Wire.h>
#include <DS1337.h>
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 12,true); // RX, TX, true sets the inverter

//The following code is taken from sleep.h as Arduino Software v22 (avrgcc) in w32 does not have the latest sleep.h file
#define sleep_bod_disable() \
{ \
  uint8_t tempreg; \
  __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
                       "ori %[tempreg], %[bods_bodse]" "\n\t" \
                       "out %[mcucr], %[tempreg]" "\n\t" \
                       "andi %[tempreg], %[not_bodse]" "\n\t" \
                       "out %[mcucr], %[tempreg]" \
                       : [tempreg] "=&d" (tempreg) \
                       : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
                         [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
                         [not_bodse] "i" (~_BV(BODSE))); \
}


DS1337 RTC; //Create RTC object for DS1337 RTC
static uint8_t prevSecond=0; 
static DateTime interruptTime;

static uint16_t interruptInterval = 10; //Seconds. Change this to suitable value.


void setup () 
{
     /*Initialize INT0 pin for accepting interrupts */
     PORTD |= 0x04; 
     DDRD &=~ 0x04;
     // set the data rate for the SoftwareSerial port
     mySerial.begin(9600);
     delay(50);
     Wire.begin();
     Serial.begin(57600);
     RTC.begin();
     
     pinMode(4,OUTPUT);//SD Card power control pin. LOW = On, HIGH = Off
     digitalWrite(4,LOW); //Power On SD Card.
     
     Serial.print("Load SD card...");

     // Check if SD card can be intialized.
     if (!SD.begin(10))  //Chipselect is on pin 10
     {
        Serial.println("SD Card could not be intialized, or not found");
        return;
     }
     Serial.println("SD Card found and initialized.");
  delay(10);
     
     attachInterrupt(0, INT0_ISR, LOW); //Only LOW level interrupt can wake up from PWR_DOWN
     set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 
     //Enable Interrupt 
     //RTC.enableInterrupts(EveryMinute); //interrupt at  EverySecond, EveryMinute, EveryHour
     // or this
     DateTime  start = RTC.now();
     interruptTime = DateTime(start.get() + interruptInterval); //Add interruptInterval in seconds to start time
}

void loop () 
{
  ////////////////////Inserted for sonar Sensor////////////////
  int index = 0;
  boolean startreading = false;
  char mm[6];
  mm[4] = 0;
  mySerial.flush();
    delay(10);
  while(index < 4){
    if(mySerial.available()){
      byte incoming = mySerial.read();    
      if(incoming == 'R') {
        startreading = true; 
      } else if(startreading) {
        mm[index++] = incoming;
      }
    }
  }
  int i = atoi(mm);
  long inches = i;
  delay(10);
  ///////////////////////// End of inserted stuff for sonar, wonder if I have inserted in a good place? /////////
    ////////////////////// START : Application or data logging code//////////////////////////////////
    
    float voltage;
    int BatteryValue;
 
    BatteryValue = analogRead(A7);
    voltage = BatteryValue * (1.1 / 1024)* (10+2)/2;  //Voltage divider
 
    DateTime now = RTC.now(); //get the current date-time    
    if((now.second()) !=  prevSecond )
    {
    //print only when there is a change
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.date(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print(',');
    Serial.print(voltage);
    Serial.print(" V");
    Serial.print("  ");
    Serial.print(mm);
delay(10);
    Serial.print(" Millimeters");
    Serial.println();
    }
     prevSecond = now.second();
    
    //|||||||||||||||||||Write to Disk|||||||||||||||||||||||||||||||||| 
    File logFile = SD.open("DATALOG.CSV", FILE_WRITE);
    
    if(logFile) {
    
    logFile.print(now.year(), DEC);
    logFile.print('/');
    logFile.print(now.month(), DEC);
    logFile.print('/');
    logFile.print(now.date(), DEC);
    logFile.print(',');
    logFile.print(now.hour(), DEC);
    logFile.print(':');
    logFile.print(now.minute(), DEC);
    logFile.print(':');
    logFile.print(now.second(), DEC);
    logFile.print(',');
    logFile.print(mm);
delay(10);
    logFile.print(',');
    logFile.println(voltage);
    logFile.close();
    }

    //|||||||||||||||||||Write to Disk||||||||||||||||||||||||||||||||||
    
    RTC.clearINTStatus(); //This function call is a must to bring /INT pin HIGH after an interrupt.
    RTC.enableInterrupts(interruptTime.hour(),interruptTime.minute(),interruptTime.second());    // set the interrupt at (h,m,s)
    attachInterrupt(0, INT0_ISR, LOW);  //Enable INT0 interrupt (as ISR disables interrupt). This strategy is required to handle LEVEL triggered interrupt
    
    
    ////////////////////////END : Application code //////////////////////////////// 
   
    
    //\/\/\/\/\/\/\/\/\/\/\/\/Sleep Mode and Power Down routines\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
            
    //Power Down routines
    cli(); 
    sleep_enable();      // Set sleep enable bit
    sleep_bod_disable(); // Disable brown out detection during sleep. Saves more power
    sei();
        
    digitalWrite(4,HIGH); //Power Off SD Card.
    
    Serial.println("\nSleeping");
    delay(10); //This delay is required to allow print to complete
    //Shut down all peripherals like ADC before sleep. Refer Atmega328 manual
    power_all_disable(); //This shuts down ADC, TWI, SPI, Timers and USART
    sleep_cpu();         // Sleep the CPU as per the mode set earlier(power down)  
    sleep_disable();     // Wakes up sleep and clears enable bit. Before this ISR would have executed
    power_all_enable();  //This shuts enables ADC, TWI, SPI, Timers and USART
    delay(10); //This delay is required to allow CPU to stabilize
    Serial.println("Awake from sleep");   
    delay(10); 
    digitalWrite(4,LOW); //Power On SD Card.
    
    //\/\/\/\/\/\/\/\/\/\/\/\/Sleep Mode and Power Saver routines\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

} 

  
//Interrupt service routine for external interrupt on INT0 pin conntected to DS1337 /INT
void INT0_ISR()
{
  //Keep this as short as possible. Possibly avoid using function calls
    detachInterrupt(0); 
    interruptTime = DateTime(interruptTime.get() + interruptInterval);  //decide the time for next interrupt, configure next interrupt  
}

Capture.PNG

interruptTime Should probably be volatile

I assume you want to enter Rxxx only once because you never reset index so never go back checking serial - you should probably put also your code to calculate i with atoi or mm[4]=0 in that same range just for the sake of not doing that work everytime.

You should not mess around with PORTD and DDRD at the beginning of the code, this is done for you by the high level functions and I would recommend you use enable/disable interrupt functions, rather than attaching and detaching your INT0_ISR all the time.

your problem might be that the sleep_enable() command should go above the attachInterrupts. If you are unlucky and the clock interrupt is set already after your attachInterrupts and before you sleep then you don't have a way to wake up.

Have a look here - you should disable sleep in your ISR and the order of calls is documented

Hi
Thanks for your help here, I will admit most of what you said went over my head.
My goal is to have the Arduino wake up, take the RTC data, the Rxxxx from the range finder and another value from the A7 pin and record it to the SD card, Then go to sleep and do it all again in an amount of time.
The code I have is put together from two codes I have found on the web and checked for functionality the tried to merge the two.

The two codes that work ok are here.

The code that I seem to get good Data from the range finder I changed it from inches to mm so I hope I didnt change the wrong things while trying to do this.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 12,true); // RX, TX, true sets the inverter
 
void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
 
  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  delay(50);
}
 
void loop() {
  int index = 0;
  boolean startreading = false;
  char mm[6];
  mm[5] = 0;
  mySerial.flush();
  while(index < 4){
    if(mySerial.available()){
      byte incoming = mySerial.read();    
      if(incoming == 'R') {
        startreading = true; 
      } else if(startreading) {
        mm[index++] = incoming;
      }
    }
  }
  int i = atoi(mm);
  long inches = i;
  Serial.println(mm);
  //delay(1000);
}

and the code that Seeduino gives as an example for Data-logging with the Seeduino Stalker V3.

//Data logger Demonstration using Seeeduino Stalker v3.0. Logs Battery Voltage every 10 seconds to DATALOG.CSV file
//Use this demo code to implement your Data-logger functionality, add additional sensors.

//1.Solder P3 and P2 PCB jumper pads
//2.Compile and upload the sketch
//3.See if everything works fine using Serial Monitor.
//4.Remove all Serial port code, recompile the sketch and upload.
// This reduces power consumption during battery mode.

#include <avr/sleep.h> 
#include <avr/power.h>
#include <avr/power.h>
#include <Wire.h>
#include <DS1337.h>
#include <SPI.h>
#include <SD.h>

//The following code is taken from sleep.h as Arduino Software v22 (avrgcc) in w32 does not have the latest sleep.h file
#define sleep_bod_disable() \
{ \
  uint8_t tempreg; \
  __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
                       "ori %[tempreg], %[bods_bodse]" "\n\t" \
                       "out %[mcucr], %[tempreg]" "\n\t" \
                       "andi %[tempreg], %[not_bodse]" "\n\t" \
                       "out %[mcucr], %[tempreg]" \
                       : [tempreg] "=&d" (tempreg) \
                       : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
                         [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
                         [not_bodse] "i" (~_BV(BODSE))); \
}


DS1337 RTC; //Create RTC object for DS1337 RTC
static uint8_t prevSecond=0; 
static DateTime interruptTime;

static uint16_t interruptInterval = 10; //Seconds. Change this to suitable value.


void setup () 
{
     /*Initialize INT0 pin for accepting interrupts */
     PORTD |= 0x04; 
     DDRD &=~ 0x04;

     Wire.begin();
     Serial.begin(57600);
     RTC.begin();
     
     pinMode(4,OUTPUT);//SD Card power control pin. LOW = On, HIGH = Off
     digitalWrite(4,LOW); //Power On SD Card.
     
     Serial.print("Load SD card...");

     // Check if SD card can be intialized.
     if (!SD.begin(10))  //Chipselect is on pin 10
     {
        Serial.println("SD Card could not be intialized, or not found");
        return;
     }
     Serial.println("SD Card found and initialized.");
  
     
     attachInterrupt(0, INT0_ISR, LOW); //Only LOW level interrupt can wake up from PWR_DOWN
     set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 
     //Enable Interrupt 
     //RTC.enableInterrupts(EveryMinute); //interrupt at  EverySecond, EveryMinute, EveryHour
     // or this
     DateTime  start = RTC.now();
     interruptTime = DateTime(start.get() + interruptInterval); //Add interruptInterval in seconds to start time
}

void loop () 
{
    ////////////////////// START : Application or data logging code//////////////////////////////////
    
    float voltage;
    int BatteryValue;
 
    BatteryValue = analogRead(A7);
    voltage = BatteryValue * (1.1 / 1024)* (10+2)/2;  //Voltage divider
 
    DateTime now = RTC.now(); //get the current date-time    
    if((now.second()) !=  prevSecond )
    {
    //print only when there is a change
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.date(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print("   ");
    Serial.print(voltage);
    Serial.print(" V");
    Serial.println();
    }
     prevSecond = now.second();
    
    //|||||||||||||||||||Write to Disk|||||||||||||||||||||||||||||||||| 
    File logFile = SD.open("DATALOG.CSV", FILE_WRITE);
    
    if(logFile) {
    
    logFile.print(now.year(), DEC);
    logFile.print('/');
    logFile.print(now.month(), DEC);
    logFile.print('/');
    logFile.print(now.date(), DEC);
    logFile.print(',');
    logFile.print(now.hour(), DEC);
    logFile.print(':');
    logFile.print(now.minute(), DEC);
    logFile.print(':');
    logFile.print(now.second(), DEC);
    logFile.print(',');
    logFile.println(voltage);
    logFile.close();
    }

    //|||||||||||||||||||Write to Disk||||||||||||||||||||||||||||||||||
    
    RTC.clearINTStatus(); //This function call is a must to bring /INT pin HIGH after an interrupt.
    RTC.enableInterrupts(interruptTime.hour(),interruptTime.minute(),interruptTime.second());    // set the interrupt at (h,m,s)
    attachInterrupt(0, INT0_ISR, LOW);  //Enable INT0 interrupt (as ISR disables interrupt). This strategy is required to handle LEVEL triggered interrupt
    
    
    ////////////////////////END : Application code //////////////////////////////// 
   
    
    //\/\/\/\/\/\/\/\/\/\/\/\/Sleep Mode and Power Down routines\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
            
    //Power Down routines
    cli(); 
    sleep_enable();      // Set sleep enable bit
    sleep_bod_disable(); // Disable brown out detection during sleep. Saves more power
    sei();
        
    digitalWrite(4,HIGH); //Power Off SD Card.
    
    Serial.println("\nSleeping");
    delay(10); //This delay is required to allow print to complete
    //Shut down all peripherals like ADC before sleep. Refer Atmega328 manual
    power_all_disable(); //This shuts down ADC, TWI, SPI, Timers and USART
    sleep_cpu();         // Sleep the CPU as per the mode set earlier(power down)  
    sleep_disable();     // Wakes up sleep and clears enable bit. Before this ISR would have executed
    power_all_enable();  //This shuts enables ADC, TWI, SPI, Timers and USART
    delay(10); //This delay is required to allow CPU to stabilize
    Serial.println("Awake from sleep");    
    digitalWrite(4,LOW); //Power On SD Card.
    
    //\/\/\/\/\/\/\/\/\/\/\/\/Sleep Mode and Power Saver routines\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

} 

  
//Interrupt service routine for external interrupt on INT0 pin conntected to DS1337 /INT
void INT0_ISR()
{
  //Keep this as short as possible. Possibly avoid using function calls
    detachInterrupt(0); 
    interruptTime = DateTime(interruptTime.get() + interruptInterval);  //decide the time for next interrupt, configure next interrupt  
}

I'm don't know the shortfalls in ether Code and I'm completely open to any Suggestion for making this work. Even if I need to start from scratch.

Let me re explain as it is important to understand:

In your level interrupt function

//Interrupt service routine for external interrupt on INT0 pin conntected to DS1337 /INT
void INT0_ISR()
{
  //Keep this as short as possible. Possibly avoid using function calls
    detachInterrupt(0); 
    interruptTime = DateTime(interruptTime.get() + interruptInterval);  //decide the time for next interrupt, configure next interrupt  
}

you call detachInterrupt(0); . The reason for detaching it is that with a level interrupt, the pin triggering the interrupt has to be held in that state for a certain amount of time before the interrupt is called. Because the level is maintained, the ISR would be repeatedly called until the pin changes state. Thus The interrupt must be detached to prevent the interrupt to keep happening.

If you detach the interrupt, a consequence is that the interrupt must be re-attached again in the code (once the pin has gone back to a normal state). so You can't just attach the interrupt once in the setup code.

And good news, in your code you do indeed re attach it in the section before going to sleep:
attachInterrupt(0, INT0_ISR, LOW);
followed by many instructions, during the first part interruptions are not possible because you do cli();

   cli(); 
      sleep_enable();      // Set sleep enable bit
      sleep_bod_disable(); // Disable brown out detection during sleep. Saves more power
   sei();

But from here on until you sleep interrupts are enabled and you have quite some time spent there...
========= RISKY SECTION INTERRUPT CAN HAPPEN ==============

    digitalWrite(4,HIGH); //Power Off SD Card.
    Serial.println("\nSleeping");
    delay(10); //This delay is required to allow print to complete
    //Shut down all peripherals like ADC before sleep. Refer Atmega328 manual
    power_all_disable(); //This shuts down ADC, TWI, SPI, Timers and USART

=================================================
Then finally, you go to sleep
  sleep_cpu();        // Sleep the CPU as per the mode set earlier(power down) 
The problem is if the interrupt occurs in the RISKY SECTION, after attachInterrupt but before sleep_cpu(), let's say in your code after the digitalWrite. Then your interrupt is called and its code executed, the interrupt gets detached, and you come back to execute delay(10); etc and then the CPU will enter sleep mode.

But because you detached the interrupt, there will no longer be any interrupt enabled so you are sending your Arduino into a deep coma from which it will never wake up. (You will need to force the reset)... This is sad, don't do that to your nice arduino! :wink:

But there is a solution! The sleep enable bit can be cleared during the execution of your interrupt and thus if the interrupt has been called, the arduino will refuse to go to sleep when you ask sleep_cpu();

So To summarize, the sleep_enable(); command goes above the attachInterrupt function (this way if an interrupt happens and the ISR gets detached, sleep won't be re-enabled begore asking the Arduino to sleep) and that should look like this:

sleep_enable();// before attaching the interrupt !!! Important
attachInterrupt(0, INT0_ISR, LOW);

/* your  many other lines of code here */

set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
sleep_bod_disable();
sei();
sleep_cpu(); // won't be executed if the interrupt has been called since [tt]attachInterrupt[/tt]
                   // and thus it is like an instant wake up.
/* wake up here */
sleep_disable();
.....

And your interrupt should look like this

//Interrupt service routine for external interrupt on INT0 pin conntected to DS1337 /INT
void INT0_ISR()
{
  //Keep this as short as possible. Possibly avoid using function calls
    sleep_disable(); // in case the interrupt was called before we sleep
    detachInterrupt(0); 
    interruptTime = DateTime(interruptTime.get() + interruptInterval);  //decide the time for next interrupt, configure next interrupt  
}

Does this make more sense?

So when you say

The code I have so far does everything well but wont seem to do more that one data entry to the SD card and will then hang.

I don't think it hangs, I think your arduino is stuck in coma without an interrupt set to wake it up.

Wow I'm really impressed at this community, I hope I can be this helpful so someone else some day.

I have changed my code to implement all of your suggestions to the best of my limited skill and I think I'm still doing something wrong as the result is the same.
Here is the updated code

/*
Used to Read MaxSonar MB7360 HRXL
Written for SEEDUINO STALKER V3
Will be using the serial Data pin output on the sensor MB7360HRXL 3.3V Supply from stalker with power filter and pin 11 softwareserial data input 
1.Solder P3 and P2 PCB jumper pads on the Stalker V3
2.Compile and upload the sketch
3.See if everything works fine using Serial Monitor.
4.Remove all Serial port code, recompile the sketch and upload.
 This reduces power consumption during battery mode.
*/

#include <avr/sleep.h> 
#include <avr/power.h>
#include <avr/power.h>
#include <Wire.h>
#include <DS1337.h>
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(11, 12,true); // RX, TX, true sets the inverter

//The following code is taken from sleep.h as Arduino Software v22 (avrgcc) in w32 does not have the latest sleep.h file
#define sleep_bod_disable() \
{ \
  uint8_t tempreg; \
  __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
                       "ori %[tempreg], %[bods_bodse]" "\n\t" \
                       "out %[mcucr], %[tempreg]" "\n\t" \
                       "andi %[tempreg], %[not_bodse]" "\n\t" \
                       "out %[mcucr], %[tempreg]" \
                       : [tempreg] "=&d" (tempreg) \
                       : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
                         [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
                         [not_bodse] "i" (~_BV(BODSE))); \
}


DS1337 RTC; //Create RTC object for DS1337 RTC
static uint8_t prevSecond=0; 
static DateTime interruptTime;

static uint16_t interruptInterval = 10; //Seconds. Change this to suitable value.


void setup () 
{
     /*Initialize INT0 pin for accepting interrupts */
     PORTD |= 0x04; 
     DDRD &=~ 0x04;
     // set the data rate for the SoftwareSerial port
     mySerial.begin(9600);
     delay(50);
     Wire.begin();
     Serial.begin(57600);
     RTC.begin();
     
     pinMode(4,OUTPUT);//SD Card power control pin. LOW = On, HIGH = Off
     digitalWrite(4,LOW); //Power On SD Card.
     
     Serial.print("Load SD card...");

     // Check if SD card can be intialized.
     if (!SD.begin(10))  //Chipselect is on pin 10
     {
        Serial.println("SD Card could not be intialized, or not found");
        return;
     }
     Serial.println("SD Card found and initialized.");
  delay(10);
     sleep_enable();      // Set sleep enable bit
     attachInterrupt(0, INT0_ISR, LOW); //Only LOW level interrupt can wake up from PWR_DOWN
     
 
     //Enable Interrupt 
     //RTC.enableInterrupts(EveryMinute); //interrupt at  EverySecond, EveryMinute, EveryHour
     // or this
     DateTime  start = RTC.now();
     interruptTime = DateTime(start.get() + interruptInterval); //Add interruptInterval in seconds to start time
}

void loop () 
{
  ////////////////////Inserted for sonar Sensor////////////////
  int index = 0;
  boolean startreading = false;
  char mm[6];
  mm[4] = 0;
  mySerial.flush();
    delay(10);
  while(index < 4){
    if(mySerial.available()){
      byte incoming = mySerial.read();    
      if(incoming == 'R') {
        startreading = true; 
      } else if(startreading) {
        mm[index++] = incoming;
      }
    }
  }
  int i = atoi(mm);
  long inches = i;
  delay(10);
  ///////////////////////// End of inserted stuff for sonar, wonder if I have inserted in a good place? /////////
    ////////////////////// START : Application or data logging code//////////////////////////////////
    
    float voltage;
    int BatteryValue;
 
    BatteryValue = analogRead(A7);
    voltage = BatteryValue * (1.1 / 1024)* (10+2)/2;  //Voltage divider
 
    DateTime now = RTC.now(); //get the current date-time    
    if((now.second()) !=  prevSecond )
    {
    //print only when there is a change
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.date(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print(',');
    Serial.print(voltage);
    Serial.print(" V");
    Serial.print("  ");
    Serial.print(mm);
delay(10);
    Serial.print(" Millimeters");
    Serial.println();
    }
     prevSecond = now.second();
    
    //|||||||||||||||||||Write to Disk|||||||||||||||||||||||||||||||||| 
    File logFile = SD.open("DATALOG.CSV", FILE_WRITE);
    
    if(logFile) {
    
    logFile.print(now.year(), DEC);
    logFile.print('/');
    logFile.print(now.month(), DEC);
    logFile.print('/');
    logFile.print(now.date(), DEC);
    logFile.print(',');
    logFile.print(now.hour(), DEC);
    logFile.print(':');
    logFile.print(now.minute(), DEC);
    logFile.print(':');
    logFile.print(now.second(), DEC);
    logFile.print(',');
    logFile.print(mm);
delay(10);
    logFile.print(',');
    logFile.println(voltage);
    logFile.close();
    }

    //|||||||||||||||||||Write to Disk||||||||||||||||||||||||||||||||||
    
    RTC.clearINTStatus(); //This function call is a must to bring /INT pin HIGH after an interrupt.
    RTC.enableInterrupts(interruptTime.hour(),interruptTime.minute(),interruptTime.second());    // set the interrupt at (h,m,s)
    attachInterrupt(0, INT0_ISR, LOW);  //Enable INT0 interrupt (as ISR disables interrupt). This strategy is required to handle LEVEL triggered interrupt
    
    
    ////////////////////////END : Application code //////////////////////////////// 
   
    
    //\/\/\/\/\/\/\/\/\/\/\/\/Sleep Mode and Power Down routines\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
            
    //Power Down routines
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    cli(); 
    sleep_bod_disable(); // Disable brown out detection during sleep. Saves more power
    sei();
    sleep_cpu();         // Sleep the CPU as per the mode set earlier(power down)
        
    digitalWrite(4,HIGH); //Power Off SD Card.
    
    Serial.println("\nSleeping");
    delay(10); //This delay is required to allow print to complete
    //Shut down all peripherals like ADC before sleep. Refer Atmega328 manual
    power_all_disable(); //This shuts down ADC, TWI, SPI, Timers and USART
      
    sleep_disable();     // Wakes up sleep and clears enable bit. Before this ISR would have executed
    power_all_enable();  //This shuts enables ADC, TWI, SPI, Timers and USART
    delay(10); //This delay is required to allow CPU to stabilize
    Serial.println("Awake from sleep");    
    digitalWrite(4,LOW); //Power On SD Card.
    
    //\/\/\/\/\/\/\/\/\/\/\/\/Sleep Mode and Power Saver routines\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

} 

  
//Interrupt service routine for external interrupt on INT0 pin conntected to DS1337 /INT
void INT0_ISR()
{
  //Keep this as short as possible. Possibly avoid using function calls
    sleep_disable(); // in case the interrupt was called before we sleep
    detachInterrupt(0); 
    interruptTime = DateTime(interruptTime.get() + interruptInterval);  //decide the time for next interrupt, configure next interrupt  
}