user63191: I have a setup with an Arduino Pro Mini, a DS1307 RTC, a microSD shield and a microswitch. I've set an interrupt to the microswitch, so it'll wake up the Arduino when it changes status. Here is some relevant code:
void setup() {
  rtc.begin();
  pinMode(button, INPUT);
  SD.begin(chipSelect);

  /*Omitted the same write to file as in button_ISR()*/
}

void loop() {
  delay(5000);
  goToSleep();
}

void goToSleep() {
  sleep_enable();
  attachInterrupt(digitalPinToInterrupt(button), button_ISR, CHANGE);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  delay(500);
  sleep_cpu();
}

void button_ISR() {
    sleep_disable();
    detachInterrupt(0);
    rtc.begin();
    String data = (digitalRead(button))?"OPEN":"CLOSE";
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    if(dataFile) {
      DateTime now = rtc.now();
      dataFile.print(now.year(), DEC);
      dataFile.print('.');
      dataFile.print(now.month(), DEC);
      dataFile.print('.');
      dataFile.print(now.day(), DEC);
      dataFile.print(". (");
      dataFile.print(daysOfTheWeek[now.dayOfTheWeek()]);
      dataFile.print(") ");
      dataFile.print(now.hour(), DEC);
      dataFile.print(":");
      dataFile.print(now.minute(), DEC);
      dataFile.print(":");
      dataFile.print(now.second(), DEC);
      dataFile.print(";");
      dataFile.println(data);
      dataFile.close();
    }
    delay(1000);
}

If I don't call rtc.now(), and omit the DateTime prints, the code perfectly writes "OPEN" and "CLOSE" in the txt. I have the same dateTime writing inside the setup(), with "START", and it perfectly writes the current date/time.
What am I missing? How could I get the time from RTC after wake up?

user7508: You should not delay in an ISR, for two reasons:

Interrupts are disabled while the ISR runs, and delay() relies on
interrupts.

Interrupts are used to handle time-critical tasks. The longer the
interrupts are disabled, the larger the chances that one of those
time-critical tasks is handled too late. Thus, ISRs should execute as
fast as possible.


In this particular case, if we try to make the ISR as short as possible,
the optimal version is this:
void button_ISR() {}

Since the interrupt is meant to wake up the Arduino, and nothing more,
everything the ISR does can be done at wake-up, right after
sleep_cpu();.
A few more comments and suggestions:

set_sleep_mode(SLEEP_MODE_PWR_DOWN); can be done once and for all in
setup()

instead combining sleep_enable(), sleep_cpu() and
sleep_disable(), you can use a single call to sleep_mode()

you most probably do not need to reinitialize the RTC and re-open the
file at every loop iteration: do this only once, in setup()

String objects are not friendly to a small Arduino's memory; in this
case you can get rid of them by simply replacing the word String
with const char *

if you are using RTClib, you may want to use the
DateTime::toString() method, which can make your code
shorter and simpler.



63191: <p>I have a setup with an Arduino Pro Mini, a DS1307 RTC, a microSD shield and a microswitch. I've set an interrupt to the microswitch, so it'll wake up the Arduino when it changes status. Here is some relevant code:</p>
<pre><code>void setup() {
  rtc.begin();
  pinMode(button, INPUT);
  SD.begin(chipSelect);

  /*Omitted the same write to file as in button_ISR()*/
}

void loop() {
  delay(5000);
  goToSleep();
}

void goToSleep() {
  sleep_enable();
  attachInterrupt(digitalPinToInterrupt(button), button_ISR, CHANGE);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  delay(500);
  sleep_cpu();
}

void button_ISR() {
    sleep_disable();
    detachInterrupt(0);
    rtc.begin();
    String data = (digitalRead(button))?&quot;OPEN&quot;:&quot;CLOSE&quot;;
    File dataFile = SD.open(&quot;datalog.txt&quot;, FILE_WRITE);
    if(dataFile) {
      DateTime now = rtc.now();
      dataFile.print(now.year(), DEC);
      dataFile.print('.');
      dataFile.print(now.month(), DEC);
      dataFile.print('.');
      dataFile.print(now.day(), DEC);
      dataFile.print(&quot;. (&quot;);
      dataFile.print(daysOfTheWeek[now.dayOfTheWeek()]);
      dataFile.print(&quot;) &quot;);
      dataFile.print(now.hour(), DEC);
      dataFile.print(&quot;:&quot;);
      dataFile.print(now.minute(), DEC);
      dataFile.print(&quot;:&quot;);
      dataFile.print(now.second(), DEC);
      dataFile.print(&quot;;&quot;);
      dataFile.println(data);
      dataFile.close();
    }
    delay(1000);
}
</code></pre>
<p>If I don't call rtc.now(), and omit the DateTime prints, the code perfectly writes &quot;OPEN&quot; and &quot;CLOSE&quot; in the txt. I have the same dateTime writing inside the setup(), with &quot;START&quot;, and it perfectly writes the current date/time.</p>
<p>What am I missing? How could I get the time from RTC after wake up?</p>
 7508: <p>You should not delay in an ISR, for two reasons:</p>
<ol>
<li><p>Interrupts are disabled while the ISR runs, and <code>delay()</code> relies on
interrupts.</p>
</li>
<li><p>Interrupts are used to handle time-critical tasks. The longer the
interrupts are disabled, the larger the chances that one of those
time-critical tasks is handled too late. Thus, ISRs should execute as
fast as possible.</p>
</li>
</ol>
<p>In this particular case, if we try to make the ISR as short as possible,
the optimal version is this:</p>
<pre class="lang-cpp prettyprint-override"><code>void button_ISR() {}
</code></pre>
<p>Since the interrupt is meant to wake up the Arduino, and nothing more,
everything the ISR does can be done at wake-up, right after
<code>sleep_cpu();</code>.</p>
<p>A few more comments and suggestions:</p>
<ul>
<li><p><code>set_sleep_mode(SLEEP_MODE_PWR_DOWN);</code> can be done once and for all in
<code>setup()</code></p>
</li>
<li><p>instead combining <code>sleep_enable()</code>, <code>sleep_cpu()</code> and
<code>sleep_disable()</code>, you can use a single call to <code>sleep_mode()</code></p>
</li>
<li><p>you most probably do not need to reinitialize the RTC and re-open the
file at every loop iteration: do this only once, in <code>setup()</code></p>
</li>
<li><p><code>String</code> objects are not friendly to a small Arduino's memory; in this
case you can get rid of them by simply replacing the word <code>String</code>
with <code>const char *</code></p>
</li>
<li><p>if you are using RTClib, you may want to use <a href="https://adafruit.github.io/RTClib/html/class_date_time.html#a3753bf2ae254315a56f7ee38ff0b188b" rel="nofollow noreferrer">the
<code>DateTime::toString()</code> method</a>, which can make your code
shorter and simpler.</p>
</li>
</ul>
