Calling functions once with an interrupt

Hi everyone, I'm working on a clock project with an RTC. The RTC drops its SQW pin low when the alarm fires, and I'd like to wake the arduino and update the clock when that happens. I'd also like to wake the arduino if the button is pressed to set the time. I tried playing around a little but neither works well. I'm very new to this so if you're willing to help and provide an example as to how to fix it, I'd REALLY appreciate it. Thank you all so much!

#include <SPI.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 8);
int loopWait = 0;
bool needsUpdate = true;

void setup() {
  Serial.begin(9600);
  pinMode(3, INPUT_PULLUP); //set time button
  pinMode(9, INPUT_PULLUP); //set time button
  
  //Initial RTC calls
  rtc.begin(10);
  rtc.set12Hour();
  rtc.autoTime(); //Get time automatically

  pinMode(2, INPUT_PULLUP); //Set interrupt for alarm
  attachInterrupt(digitalPinToInterrupt(2), alarm, FALLING);
  rtc.update(); //Update + Set alarms
  rtc.enableAlarmInterrupt();
  rtc.setAlarm2(rtc.minute() + 1);

  //Initial display calls
  display.begin();

  printClock(rtc.hour(),rtc.minute());
}

void alarm() {
  updateClock();
}

void loop() {
  rtc.update();
  //static int8_t lastMinute = -1;
  /*if (rtc.minute() != lastMinute) {
    printClock(rtc.hour(), rtc.minute());
    lastMinute = rtc.minute();
    rtc.setAlarm2(rtc.minute() + 1, rtc.hour());
  }*/
  if (digitalRead(3) == LOW) {
    setTime();
  }
  if (digitalRead(9) == LOW) {
    loopWait++;
    delay(1000);
    if (loopWait >= 4) {
      display.clearDisplay();
      display.setFont(&FreeSansBold12pt7b);
      display.setCursor(5,30);
      display.println("Prom?");
      display.display();
      loopWait = 0;
    }
  }
}

void setTime() {
  rtc.update();
  int hour = rtc.hour();
  int minute = rtc.minute();
  int day = rtc.day();
  int date = rtc.date();
  int month = rtc.month();
  int year = rtc.year();
  bool pm = rtc.pm();

  delay(200);
  display.setFont();
  display.setTextSize(1);
  display.clearDisplay();
  display.setTextWrap(true);
  display.println("Entering time set mode. Press to contuinue...");
  display.display();
  //SET DAY
  while (true) {
     if (digitalRead(3) == LOW) {
      if (day == 7) {
        day = 0;
      }
      day++;
      delay(200);
      
      display.clearDisplay();
      display.setCursor(15,20);
      switch(day) {
        case 1:
          display.println("SUNDAY");
          break;
        case 2:
          display.println("MONDAY");
          break;
        case 3:
          display.println("TUESDAY");
          break;
        case 4:
          display.println("WEDNESDAY");
          break;
        case 5:
          display.println("THURSDAY");
          break;
        case 6:
          display.println("FRIDAY");
          break;
        case 7:
          display.println("SATURDAY");
          break;
      }
      display.display();
    } else if (digitalRead(9) == LOW) {
      display.clearDisplay();
      display.display();
      break;
    }
  }
  delay(500);
  //SET MONTH
  display.setCursor(15,20);
  display.println("MONTH");
  display.display();
  while (true) {
     if (digitalRead(3) == LOW) {
      if (month == 12) {
        month = 0;
      }
      month++;
      delay(200);
      display.clearDisplay();
      display.setCursor(15,20);
      switch(month) {
        case 1:
          display.println("JANUARY");
          break;
        case 2:
          display.println("FEBRUARY");
          break;
        case 3:
          display.println("MARCH");
          break;
        case 4:
          display.println("APRIL");
          break;
        case 5:
          display.println("MAY");
          break;
        case 6:
          display.println("JUNE");
          break;
        case 7:
          display.println("JULY");
          break;
        case 8:
          display.println("AUGUST");
          break;
        case 9:
          display.println("SEPTEMBER");
          break;
        case 10:
          display.println("OCTOBER");
          break;
        case 11:
          display.println("NOVEMBER");
          break;
        case 12:
          display.println("DECEMBER");
          break;
      }
      display.display();
    } else if (digitalRead(9) == LOW) {
      display.clearDisplay();
      display.display();
      break;
    }
  }
  delay(500);
  display.setCursor(15,20);
  display.println("DATE:" + String(date));
  display.display();
  Serial.println("set date");
  //SET DATE
  while (true) {
     if (digitalRead(3) == LOW) {
      if (date == 31) {
        date = 0;
      }
      date++;
      delay(200);
      display.clearDisplay();
      display.setCursor(15,20);
      display.println("DATE:" + String(date));
      display.display();
    } else if (digitalRead(9) == LOW) {
      display.clearDisplay();
      display.display();
      break;
    }
  }
  delay(500);
  display.setCursor(0,20);
  display.println("YEAR after 2000: " + String(year));
  display.display();
  Serial.println("set date");
  //SET YEAR
  while (true) {
     if (digitalRead(3) == LOW) {
      if (year == 99) {
        year = 16;
      }
      year++;
      delay(200);
      display.clearDisplay();
      display.setCursor(0,20);
      display.println("YEAR after 2000: " + String(year));
      display.display();
    } else if (digitalRead(9) == LOW) {
      display.clearDisplay();
      display.display();
      break;
    }
  }
  delay(500);
  printClock(hour, minute);
  display.setCursor(35,0);
      display.setFont();
      display.setTextSize(1);
      display.setTextWrap(false);
      if (pm == true) {
        display.println("PM");
        display.display();
      } else {
        display.println("AM");
        display.display();
      }
  //SET HOUR
  while (true) {
    if (digitalRead(3) == LOW) {
      if (hour == 12) {
        hour = 0;
        pm = !pm;
      }
      hour++;
      delay(200);
      printClock(hour, minute);
      display.setCursor(35,0);
      display.setFont();
      display.setTextSize(1);
      display.setTextWrap(false);
      if (pm == true) {
        display.println("PM");
        display.display();
      } else {
        display.println("AM");
        display.display();
      }
    } else if (digitalRead(9) == LOW) {
      break;
    }
  }
  delay(500);
  printClock(hour, minute);
  //SET MINUTE
  while (true) {
     if (digitalRead(3) == LOW) {
      if (minute == 60) {
        minute = 0;
      }
      minute++;
      delay(200);
      printClock(hour, minute);
    } else if (digitalRead(9) == LOW) {
      break;
    }
  }
  if (pm) {
    rtc.setTime(0, minute, hour, PM, day, date, month, year);
  } else {
    rtc.setTime(0, minute, hour, AM, day, date, month, year);
  }
  
  Serial.println("Time set for " + String(hour) + ":" + String(minute) + " on " + String(date) + " " + String(month) + " " + String(year));
  display.setFont();
  display.setTextSize(1);
  display.clearDisplay();
  display.println("Time set");
  display.display();
  delay(2000);
  printClock(hour, minute);
}

void printClock(int hour, int minute) {
  display.setFont(&FreeSansBold18pt7b);
  display.clearDisplay();
  if (hour >=10) {
    display.setCursor(-3,35);
  } else {
    display.setCursor(9,35);
  }
  if (minute < 10) {
    display.println(String(hour) + ":0" + minute);
    display.display();
   } else {
    display.println(String(hour) + ':' + minute);
    display.display();
  }
  printHeader();
  printFooter();
}
}

void updateClock() {
  rtc.update();
  printClock(rtc.hour(), rtc.minute());
}

I had to omit some code, the entire code is on pastebin here: https://pastebin.com/igaqnYTw.

NOTE: I haven't implemented sleep code yet, but I'd assume I need to use interrupts in order for the device to ever wake out of sleep. Any advice on that would also be appreciated! Thanks!

I haven't looked at your code but your description of the problem says nothing related to your title.

Unless a function can complete in a matter of microseconds I would not call it from an Interrupt. I would use the interrupt to set a flag variable that would let the rest of your program know that the interrupt had happened.

,,,R

Robin2:
I haven't looked at your code but your description of the problem says nothing related to your title.

Unless a function can complete in a matter of microseconds I would not call it from an Interrupt. I would use the interrupt to set a flag variable that would let the rest of your program know that the interrupt had happened.

,,,R

Could you suggest a better title? I was mainly looking for a way to call the setTime and PrintClock functions from an interrupt event.

Previously I had thought of using flags and had the code working just fine without using interrupts, but if I want to sleep as far as I'm aware the loop won't run, so I didn't think flags would work.

novicode:
the loop won't run, so I didn't think flags would work.

The interrupt will wake the Arduino, sets the flag and lets the Arduino resume looping.

Whandall:
The interrupt will wake the Arduino, sets the flag and lets the Arduino resume looping.

I can't believe I didn't get that-makes perfect sense now! Thank you! I'll give that a try. :slight_smile:

novicode:
Could you suggest a better title? I was mainly looking for a way to call the setTime and PrintClock functions from an interrupt event.

I realize the answer is academic now, but just so as not to ignore your question ...

Now that you have explained your problem I suggest "Using an interrupt to wake Arduino and call a function".

...R