Problem with keypad for an alarm system with Arduino MEGA

Hi guys, i’m making an alarm system with Arduino and i’ve been working on it for 3 weeks.

Today got stuck while i was programming the function to acquire chars from the keypad.

I created a way that when i click on the “#” button the “keypad” function runs and the program shows a message telling me to insert a PIN, so the program have to wait until i insert the code. I’ve done something to solve that, but i noticed that it doesn’t work properly. All explained in the comments in the code. Thanks in advance!!! :wink:

//#include <EEPROM.h>
#include <RFID.h>
#include <SPI.h>
#include <DS3232RTC.h>
#include <Keypad.h>
#include <LiquidCrystal.h>

#define dim 10
#define dim2 4
LiquidCrystal lcd(8,7,6,4,3,2);
RFID RC522(53,5);

const byte ROWS=4;
const byte COLS=3;
char keys[ROWS][COLS] = {
                          {'1','2','3'},
                          {'4','5','6'},
                          {'7','8','9'},
                          {'*','0','#'}
                        };
char pwd[5]="1234";
char cod_ins[dim2];
                                               
byte rowPins[ROWS]={24,25,26,27};
byte colPins[COLS]={28,29,30};

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

bool movement=false,activation=false/*,flag=false*/;  //flag respectively for movement detection and for keypad to recognize if the alarm is activated or not  

String c[dim]={"212040E","EC4753758D","215C954B9",    //for now i've stored them as well 
            "12040F","2120400","120400",              //because i haven't set up the EEPROM yet
            "120402E","212040F","21590F","EC47300"};  // 

void setup() 
{    
    pinMode(23,INPUT);  //for PIR
    lcd.begin(16,2);
    SPI.begin(); 
    RC522.init();
    setSyncProvider(RTC.get);
    keypad.setDebounceTime(250);
    
    lcd.print("Benvenuto !!!");
    delay(2000);
    lcd.clear();
    lcd.print("Allarme inattivo");
    delay(3000);
    lcd.clear();
}

void loop() 
{
    //savemode();
    
    if(movement==false)
    {
        //if(flag==false)
        //{
            clocks();
        //}
    }
    else if(movement==true)
    {
        lcd.setCursor(0,0);
        lcd.print("ALLARME!!!");
    }
    
    rfid();
    pir();
    keypads();
}

/*void savemode()
{
    
}*/

void clocks()                 //it print on the screen current time,date and temperature using a RTC; 
{                             //it's like a main screen because the program, after any function execution, comes back here  
    lcd.setCursor(0,0);

    if(hour()<10)
    {
        lcd.print('0');
    }
    
    lcd.print(hour());
    
    lcd.print(":");
          
    if(minute()<10)
    {
        lcd.print('0');
    }
    
    lcd.print(minute());
    
    lcd.print(":");
  
    if(second()<10)
    {
        lcd.print('0');
    }
    
    lcd.print(second());

    lcd.setCursor(8,0); 
    lcd.print(" ");
      
    lcd.setCursor(0,1);
  
    lcd.print(day());
    lcd.print("/");
    lcd.print(month());
    lcd.print("/");  
    lcd.print(year());
    
    lcd.setCursor(10,1);

    lcd.print(RTC.temperature()/4.0);
    lcd.print("C");
}

void rfid()                                       //if the code key or the code card are valid, assign "false" to movement flag and stops any tone on pin 22;
{                                                 //if the code key or the code card are not valid, starts a tone for 5 mins until the key is valid
    bool error=true;
    
    if(RC522.isCard())
    {
        RC522.readCardSerial();
        String cod="";
        
        for(byte i=0; i<5; i++)
        {
            cod+=String(RC522.serNum[i],HEX);
            cod.toUpperCase();
        }

        for(byte i=0; i<dim; i++)
        {                       
            if(cod==c[i])
            {
                error=false;
            }
        } 

        if(error==true)
        {   
            lcd.clear();
            lcd.print("Codice non valido!!!");
            lcd.setCursor(0,1);
            lcd.print(cod);
            tone(22,4000,300000);                                  
            delay(1500);
            lcd.clear();  
        }
        else
        {
            noTone(22);
            movement=false;
            //digitalWrite(24,HIGH);
            lcd.clear();
            lcd.print("Codice accettato");
            lcd.setCursor(0,1);
            lcd.print(cod);
            tone(22,3000,100);
            delay(3000);
            lcd.clear();
        }
    }
}

void pir()                       //detects motion using PIR, and if so starts a tone for 5 mins until code key or code card are valid
{
   if(digitalRead(23)==HIGH)
   {
      movement=true;
      //digitalWrite(24,LOW);
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("MOVIMENTO");
      lcd.setCursor(0,1);
      lcd.print("RILEVATO!!!");
      tone(22,4000,300000);
      delay(1500);
      lcd.clear();
   }
}

void keypads()                       //it switch between "alarm activated" and "alarm deactivated" by using activation flag; at first it's "deactivated"
{
   char key=keypad.getKey();
 
   if(key=='#' && activation==false)
   {
      byte j=0,i=0;
      //flag=true;
      
      lcd.clear();
      lcd.print("Inserisci il PIN...");
      delay(1500);
      lcd.clear();

      while(keypad.waitForKey())           //here it is the problem
      {
         if(i<dim2)                        //i don't know how to quit from the "while"
         {                                 //as soon as i've inserted four chars
            lcd.print('*');
            cod_ins[i]=key;                //as soon as i've inserted four chars, the program goes in loop inside the "while"
            i++;
         }
      }

      if(key=='*')                                  //hereafter it would need a way to not let out the program from the function until i press "*" button
      {                                             
         lcd.clear();
         lcd.print("Verificando il codice"); 
         delay(1500);

         for(i=0; i<4; i++)
         {
            if(cod_ins[i]==pwd[i])
            {
               j++;
            }
         }

         if(j==4)
         {
            //flag=false;
            lcd.clear();
            lcd.print("Codice accettato");
            delay(1500);
            lcd.print("Allarme attivato");
            activation=true;
            delay(2000);
         }
         else
         {
            lcd.clear();
            lcd.print("Codice errato!!!");
            delay(1500);
         }
      }
   }
    else if(key=='#' && activation==true)
    {
       byte j=0,k=0,i=0;
       //flag=true;
              
       lcd.clear();
       lcd.print("Inserisci il PIN...");
       delay(1500);
       lcd.clear();
  
       while(keypad.waitForKey())             //same problem
       {
           if(i<6)
           {
              lcd.print('*');
              cod_ins[i]=key;
              i++;
           }
       }
  
       if(key=='*')                         //same problem
       {
          lcd.clear();
          lcd.print("Verificando il codice"); 
          delay(1500);
  
          for(i=0; i<4; i++)
          {
             if(cod_ins[i]==pwd[i])
             {
                j++;
             }
          }
  
          if(j==4)
          {
             //flag=false;
             lcd.clear();
             lcd.print("Codice accettato");
             delay(1500);
             lcd.print("Allarme disattivato");
             activation=false;
             delay(2000);
          }
          else
          {
             lcd.clear();
             lcd.print("Codice errato!!!");
             k++;
  
             if(k==3)
             {
                lcd.clear();
                lcd.print("ALLARME!!!");
                delay(1500);
                tone(22,4000,300000);
             }
          }
       }
    }
}

I leave you also the .ino file

Antifurto.zip (2.23 KB)

If you watch my YouTube video #13 it deals with reading values from a keypad membrane type switch which may help you solve your own problem. URL in the footer of this post. Enjoy!

Just suggestin' :)

I’ve seen your video… but switch case doesn’t resolve my problem… check my code for clarifications.

while(keypad.waitForKey())           //here it is the problem
      {
         if(i<dim2)                        //i don't know how to quit from the "while"
         {                                 //as soon as i've inserted four chars
            lcd.print('*');
            cod_ins[i]=key;                //as soon as i've inserted four chars, the program goes in loop inside the "while"
            i++;
         }

Will waitForKey automatically put the key that’s pressed into the key variable? How does it know which variable to use? It couldn’t so that makes no sense. My guess is that you need set key equal to the return from getKey at some point or you just get an array full if #.

Problem solved... thanks to all ;)