Exiting While Loop with Keypad? Delay a problem?

Hello, I am completely new to programming so forgive me in advance if my code is inefficient or my question seems obvious. I have tried searching but am having a hard time finding a scenario that matches my situation.

I am trying to make an alarm system as a fun project to learn about arduino, programming, and electronics. My main question involves how to exit a while loop with the press of a keypad button.

I have successfully figured out how to have a user enter a password and then verify this password. I change the states of the alarm to "ARMED" and "OFF" accordingly. When the alarm enters the "ARMED" state, there is a countdown timer that allows the user to leave the house, before it enters the "ARMED" state.

What I am trying to figure out is how to exit out of this countdown timer with a key press? Essentially cancel the timer if necessary. I have tried while loops, do-while loops, and switch-case statements and I am having trouble finding something that works. I think the main problem in the code is the "delay" statement. I think while the delay is active, the arduino is not able to search for a keypad entry. I was able to kind of get it to work, but I have to press a buttons very fast in succession to get the program to recognize it in the middle of the while loop. I have read using .getKey twice is not good practice, but I am unsure of another way to accomplish finding a key press while in the while loop. Any suggestions? Code is below:

#include <Password.h>

#include <Keypad.h>

Password password = Password("2508");

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

String alarmStatus = "DISARMED";
String prevalarmStatus = "NOTHING";
String switchStatus = "ARMED";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  keypad.addEventListener(keypadPress);
  pinMode(13, OUTPUT);
  pinMode(9,OUTPUT);
  Serial.println("Enter Code: ");
}

void loop() {
  keypad.getKey();
}

void keypadPress(KeypadEvent keyPress) {
  switch (keypad.getState()) {
    case PRESSED:
      Serial.println(keyPress);
      switch (keyPress) {
        case '*': checkPassword(); break;
        //case '#': password.reset(); break;
        default: password.append(keyPress);
      }
  }
}

void checkPassword() {
  if (password.evaluate()) {
    alarmStatus = switchStatus;
    if (alarmStatus == "ARMED"){
    digitalWrite(13, HIGH);
    digitalWrite(9,HIGH);
    delay(1000);
    digitalWrite(9,LOW);
    Serial.println(alarmStatus);
    switchStatus="OFF";
    delay(1100);
    countdownTimer();
    }
    if (alarmStatus =="OFF"){
      digitalWrite(13, LOW);
      confirmCommand();
      Serial.println(alarmStatus);
      switchStatus = "ARMED";
      }  
    }    
  else {
    Serial.println("Password Incorrect. Retry");
    Serial.println("Enter Code: ");
    password.reset();
  }
  password.reset();
}

void countdownTimer(){
    int seconds = 10;
    while (seconds > 0){
      char cancelKey = keypad.getKey();
      if (cancelKey != NO_KEY){
          Serial.println("CANCELLED");
          switchStatus = "ARMED";
          confirmCommand();
          break;  
    }
      seconds -= 1;
      delay(1000);
      Serial.println(seconds);
    }   
}   
        
void confirmCommand(){
   digitalWrite(9,HIGH);
   delay(300);
   digitalWrite(9,LOW);
   delay(200);
   digitalWrite(9,HIGH);
   delay(300);
   digitalWrite(9,LOW);
}

http://forum.arduino.cc/index.php?topic=388675.0

This post actually seems to be describing my exact scenario. I will look into this alternative for timing.

Got it to work. Mostly. When the alarm becomes "ARMED" I set an iteration variable. The "loop" portion of the code has an "if" statement that constantly looks to see if this variable falls below a value. When it falls below the value it calls a timer which keeps incrementing the variable until the end of the period. Code is below. Hopefully this may help someone else who may have a problem creating an interrupt while in a loop.

One thing I still can't figure out is the very first print on the serial monitor prints out 2 values at once, and then prints a value per second as expected. Code is below:

#include <Password.h>

#include <Keypad.h>

Password password = Password("2508");

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

String alarmStatus = "DISARMED";
String switchStatus = "ARMED";

unsigned long currentTime = 1000;
const int countdownInterval = 1000;
unsigned long prevTime = 1000;
int countdownIteration = 11;
int totalSeconds = 11;
String cancelCountdown = "OFF";
int seconds = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  keypad.addEventListener(keypadPress);
  pinMode(13, OUTPUT);
  pinMode(9,OUTPUT);
  Serial.println("Enter Code: ");
}

void loop() {
  currentTime = millis();
  keypad.getKey();
  if (countdownIteration < totalSeconds){
    countdownTimer();
}
}
void keypadPress(KeypadEvent keyPress) {
  switch (keypad.getState()) {
    case PRESSED:
      Serial.println(keyPress);
      switch (keyPress) {
        case '*': checkPassword(); break;
        case '#': {cancelCountdown = "CANCEL"; break;}
        default: password.append(keyPress);
      }
  }
}

void checkPassword() {
  if (password.evaluate()) {
    alarmStatus = switchStatus;
    if (alarmStatus == "ARMED"){
    digitalWrite(13, HIGH);
    digitalWrite(9,HIGH);
    delay(1000);
    digitalWrite(9,LOW);
    Serial.println(alarmStatus);
    switchStatus="OFF";
    countdownIteration=-1;
    seconds = totalSeconds;
    cancelCountdown = "OFF";
    }
    if (alarmStatus =="OFF"){
      digitalWrite(13, LOW);
      confirmCommand();
      Serial.println(alarmStatus);
      switchStatus = "ARMED";
      }  
    }    
  else {
    Serial.println("Password Incorrect. Retry");
    Serial.println("Enter Code: ");
    password.reset();
  }
  password.reset();
}

void countdownTimer(){
    if (cancelCountdown == "CANCEL"){
      Serial.println("CANCELLED");
      switchStatus = "ARMED";
      confirmCommand();
      cancelCountdown = "OFF";
      countdownIteration = totalSeconds;
      password.reset();
      return;  
      }
        if (currentTime - prevTime >= countdownInterval){
         Serial.println (seconds);
         seconds -= 1;
         countdownIteration++;
         prevTime = currentTime;
         } 
    password.reset();   
  }   
        
void confirmCommand(){
   digitalWrite(9,HIGH);
   delay(300);
   digitalWrite(9,LOW);
   delay(200);
   digitalWrite(9,HIGH);
   delay(300);
   digitalWrite(9,LOW);
}[\code]