Help with Keypad + RFID Door Lock

Having problems getting my code to work with both RFID and keypad, without having to use a boolean to define which one I want to use, my aim is to give user the ability to do either or without having to change the code in anyway. My main issue is that the 'readkeypad'
function causes errors when lines 52 through 77 are within the code, (for the RFID), without these the code works perfectly fine.

#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h> //-
#include <MFRC522.h>
 
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);

LiquidCrystal_I2C lcd(0x27, 16, 2); 
Servo ServoMotor; //- 
String pad;

const int buzzer = 9;
const byte numRows = 4;
const byte numCols = 4;
String password = "281205";
char keypressed;
char keymap[numRows][numCols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

//------------------------------------------------------------

byte rowPins[numRows] = {10, 9, 8, 7};
byte colPins[numCols] = {6, 5, 4, 3};
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols); 

void setup() {
  ServoMotor.attach(11); //-
  //- LockedPosition(true); //-
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Enter Password");
  lcd.setCursor(0, 1);
  lcd.print("Or Scan Card");
  delay(3000);
  lcd.clear();
  pinMode(buzzer, OUTPUT); // Set buzzer - pin 9 as an output
}


void loop() {
  // put your main code here, to run repeatedly:
    if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
      if ( ! mfrc522.PICC_ReadCardSerial())
      return; 
    {
      String content= "";
      byte letter;
      for (byte i = 0; i < mfrc522.uid.size; i++) 
      {
        content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
        content.concat(String(mfrc522.uid.uidByte[i], HEX));
      }
      content.toUpperCase();
      if (content.substring(1) == "13 E3 B7 19") //change here the UID of the card/cards that you want to give access
      {
        lcd.print("Authorized access");
      }
      else 
      {
        lcd.print(" Access denied");
        return;
      }
      
      }
  }
  else 
  
  { 
  readKeypad();
  switch (keypressed)  //== '#') {
    { case '#':
    if (pad == password) {
      lcd.setCursor(0, 1);
      lcd.print("Access Granted");
      ServoMotor.write(60); //- motor moving
      tone(buzzer, 700); // Send 1KHz sound signal...
      delay(500);        // ...for 1 sec
      noTone(buzzer);     // Stop sound...
      delay(6000);
      lcd.clear();
      pad = "";
      
    } else {
      lcd.setCursor(0, 1);
      lcd.print("Access Denied");
    } break;
  case '*':
    pad = "";
    lcd.clear();
  break;
    case 'A':
      ServoMotor.write(11);
      ServoMotor.write(11);
      lcd.clear();
      pad = "";
      break;
    } 
  lcd.setCursor(0, 0);
  lcd.print(pad);
  delay(100);
}

void readKeypad() {
  keypressed = myKeypad.getKey(); 
  if (keypressed != '#') {
    String konv = String(keypressed);
    pad += konv;
  }
}
}

You seem to be using pin 9 for both the buzzer and the keypad

In addition, take a look at where the closing brace of loop() function is

Thank you, this did resolve the read keypad function, and the program runs, however pressing the keypad or scanning my card does nothing, do you know why this could be?

Please post your updated sketch

Have not changed the 9 pin as it does not affect the code as I'm using a breadboard


#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h> //-
#include <MFRC522.h>
 
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);

LiquidCrystal_I2C lcd(0x27, 16, 2); 
Servo ServoMotor; //- 
String pad;


const int buzzer = 9;
const byte numRows = 4;
const byte numCols = 4;
String password = "281205";
char keypressed;
char keymap[numRows][numCols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

//------------------------------------------------------------

byte rowPins[numRows] = {10, 9, 8, 7};
byte colPins[numCols] = {6, 5, 4, 3};
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols); 

void setup() {
  ServoMotor.attach(11); //-
  //- LockedPosition(true); //-
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Enter Password");
  lcd.setCursor(0, 1);
  lcd.print("Or Scan Card");
  delay(3000);
  lcd.clear();
  pinMode(buzzer, OUTPUT); // Set buzzer - pin 9 as an output
}


void loop() {
  // put your main code here, to run repeatedly:
    if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
      if ( ! mfrc522.PICC_ReadCardSerial())
      return; 
    {
      String content= "";
      byte letter;
      for (byte i = 0; i < mfrc522.uid.size; i++) 
      {
        content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
        content.concat(String(mfrc522.uid.uidByte[i], HEX));
      }
      content.toUpperCase();
      if (content.substring(1) == "13 E3 B7 19") //change here the UID of the card/cards that you want to give access
      {
        lcd.print("Authorized access");
      }
      else 
      {
        lcd.print(" Access denied");
        return;
      }
      
      }
  }
  else
  
  { 
  readKeypad();
  switch (keypressed)  //== '#') {
    { case '#':
    if (pad == password) {
      lcd.setCursor(0, 1);
      lcd.print("Access Granted");
      ServoMotor.write(60); //- motor moving
      tone(buzzer, 700); // Send 1KHz sound signal...
      delay(500);        // ...for 1 sec
      noTone(buzzer);     // Stop sound...
      delay(6000);
      lcd.clear();
      pad = "";
      
    } else {
      lcd.setCursor(0, 1);
      lcd.print("Access Denied");
    } break;
  case '*':
    pad = "";
    lcd.clear();
  break;
    case 'A':
      ServoMotor.write(11);
      ServoMotor.write(11);
      lcd.clear();
      pad = "";
      break;
    } 
  lcd.setCursor(0, 0);
  lcd.print(pad);
  delay(100);
}
}

void readKeypad() {
  keypressed = myKeypad.getKey(); 
  if (keypressed != '#') {
    String konv = String(keypressed);
    pad += konv;
  }
}

You are actually using pin 9 for 3 different things

#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);
const int buzzer = 9;
byte rowPins[numRows] = { 10, 9, 8, 7 };

What does using a breadboard have to do with it ?

I have updated it to not use pin 9 three times

#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h> //-
#include <MFRC522.h>
 
#define SS_PIN 10
#define RST_PIN 1
MFRC522 mfrc522(SS_PIN, RST_PIN);

LiquidCrystal_I2C lcd(0x27, 16, 2); 
Servo ServoMotor; //- 
String pad;


const int buzzer = 2;
const byte numRows = 4;
const byte numCols = 4;
String password = "281205";
char keypressed;
char keymap[numRows][numCols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

//------------------------------------------------------------

byte rowPins[numRows] = {10, 9, 8, 7};
byte colPins[numCols] = {6, 5, 4, 3};
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols); 

void setup() {
  ServoMotor.attach(11); //-
  //- LockedPosition(true); //-
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Enter Password");
  lcd.setCursor(0, 1);
  lcd.print("Or Scan Card");
  delay(3000);
  lcd.clear();
  pinMode(buzzer, OUTPUT); // Set buzzer - pin 9 as an output
}



void loop() {
  // put your main code here, to run repeatedly:
    if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
      if ( ! mfrc522.PICC_ReadCardSerial())
      return; 
    {
      String content= "";
      byte letter;
      for (byte i = 0; i < mfrc522.uid.size; i++) 
      {
        content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
        content.concat(String(mfrc522.uid.uidByte[i], HEX));
      }
      content.toUpperCase();
      if (content.substring(1) == "13 E3 B7 19") //change here the UID of the card/cards that you want to give access
      {
        lcd.print("Authorized access");
      }
      else 
      {
        lcd.print(" Access denied");
        return;
      }
      
      }
  }
  else
  
  { 
  readKeypad();
  switch (keypressed)  //== '#') {
    { case '#':
    if (pad == password) {
      lcd.setCursor(0, 1);
      lcd.print("Access Granted");
      ServoMotor.write(60); //- motor moving
      tone(buzzer, 700); // Send 1KHz sound signal...
      delay(500);        // ...for 1 sec
      noTone(buzzer);     // Stop sound...
      delay(6000);
      lcd.clear();
      pad = "";
      
    } else {
      lcd.setCursor(0, 1);
      lcd.print("Access Denied");
    } break;
  case '*':
    pad = "";
    lcd.clear();
  break;
    case 'A':
      ServoMotor.write(11);
      ServoMotor.write(11);
      lcd.clear();
      pad = "";
      break;
    } 
  lcd.setCursor(0, 0);
  lcd.print(pad);
  delay(100);
}
}

void readKeypad() {
  keypressed = myKeypad.getKey(); 
  if (keypressed != '#') {
    String konv = String(keypressed);
    pad += konv;
  }
}

#define RST_PIN 1

It is not usually a good ide to use pin 1 of AVR Arduinos because it is used by the Serial interface

And I just noticed this too

#define SS_PIN 10

and

byte rowPins[numRows] = { 10, 9, 8, 7 };

using pin 10 for 2 different things

I don't have enough available pins to have a different pin for each wire I need to connect, I was under the impression that the breadboard allowed you to connect several wires to the one pin, however I could be wrong as this is my first ever project?

I had the program working before when I had several different wires onto one pin through the breadboard and it did not cause any errors

You can use the analogue pins as digital pins

The breadboard allows you to connect several devices to a single pin but that does not mean that they will do what you need. Suppose, for instance, that the same pin needs to be used as both an input and and output

Thank you for letting me know, I have changed the pins however this has still not resolved the issue of the code not taking keypad/RFID input

#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h> //-
#include <MFRC522.h>
 
#define SS_PIN A2
#define RST_PIN A3
MFRC522 mfrc522(SS_PIN, RST_PIN);

LiquidCrystal_I2C lcd(0x27, 16, 2); 
Servo ServoMotor; //- 
String pad;


const int buzzer = 2;
const byte numRows = 4;
const byte numCols = 4;
String password = "281205";
char keypressed;
char keymap[numRows][numCols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

//------------------------------------------------------------

byte rowPins[numRows] = {10, 9, 8, 7};
byte colPins[numCols] = {6, 5, 4, 3};
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols); 

void setup() {
  ServoMotor.attach(11); //-
  //- LockedPosition(true); //-
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Enter Password");
  lcd.setCursor(0, 1);
  lcd.print("Or Scan Card");
  delay(3000);
  lcd.clear();
  pinMode(buzzer, OUTPUT); // Set buzzer - pin 9 as an output
}



void loop() {
  // put your main code here, to run repeatedly:
    if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
      if ( ! mfrc522.PICC_ReadCardSerial())
      return; 
    {
      String content= "";
      byte letter;
      for (byte i = 0; i < mfrc522.uid.size; i++) 
      {
        content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
        content.concat(String(mfrc522.uid.uidByte[i], HEX));
      }
      content.toUpperCase();
      if (content.substring(1) == "13 E3 B7 19") //change here the UID of the card/cards that you want to give access
      {
        lcd.print("Authorized access");
      }
      else 
      {
        lcd.print(" Access denied");
        return;
      }
      
      }
  }
  else
  
  { 
  readKeypad();
  switch (keypressed)  //== '#') {
    { case '#':
    if (pad == password) {
      lcd.setCursor(0, 1);
      lcd.print("Access Granted");
      ServoMotor.write(60); //- motor moving
      tone(buzzer, 700); // Send 1KHz sound signal...
      delay(500);        // ...for 1 sec
      noTone(buzzer);     // Stop sound...
      delay(6000);
      lcd.clear();
      pad = "";
      
    } else {
      lcd.setCursor(0, 1);
      lcd.print("Access Denied");
    } break;
  case '*':
    pad = "";
    lcd.clear();
  break;
    case 'A':
      ServoMotor.write(11);
      ServoMotor.write(11);
      lcd.clear();
      pad = "";
      break;
    } 
  lcd.setCursor(0, 0);
  lcd.print(pad);
  delay(100);
}
}

void readKeypad() {
  keypressed = myKeypad.getKey(); 
  if (keypressed != '#') {
    String konv = String(keypressed);
    pad += konv;
  }
}

What exactly happens when you run the sketch ?

Add some Serial.print()s at strategic points so that you know which portions of the code are running and what the value of pertinent variables are at those points. Are they what you expect ?

When I run the sketch it compiles with no errors, however if ( ! mfrc522.PICC_IsNewCardPresent()) { always seems to be triggered regardless which I tested through serial print, and then does not recognise the car or get to the readkeypad function.

    if (!mfrc522.PICC_IsNewCardPresent())

From the name of the function I presume that this will return true when a new card is not present which will be most of the time. If I am correct then you want to read the keypad at that point rather than reading the card

You were right in your presumption! Thank you so much for your help, it now works fully as intended. :slightly_smiling_face:

I am glad that you got it working

For the benefit of anyone reading this topic in the future please post your full working sketch

I apologise but I cannot do so as this is for my EPQ and may cause issues if I post my full final code online

I find that very strange because you were happy to post your previous code.

What issues might be caused if you post the working code ?

In fairness it wasn't wise of me to post my previous code either which my dad informed me - I may be accused of 'stealing' or 'copying' the code, although maybe unlikely it's not something I would like to risk. I'm aware this may be slightly unfair to those with similar issues and I apologise, it's just that I was only just told that it could possibly pose risk to my EPQ.