Programming an Arduino Door lock

So I have been thinking about an arduino door lock for a while. Here's the idea:

The door lock consists of a servo which opens the door if ALL the following stages are passed by the user in order:

1) Correct fingerprint entry 2) RFID 3) password entry on keypad

I have 4x3 keypad, MFRC522 rfid module and a fingerprint sensor.

I need it to work like if fingerprint is authentic , it moves on to the next stage , which is RFID. If the Fingerprint is is unauthentic, the program must break with a warning message displayed on lcd. Similarly, if the RFID is successful, it moves to password entry on keypad test and so on.

THE PROBLEM:

I am wondering what will be the logical flow of the program. I used IF-ELSE condition like:

--- IF fingerprint is authentic (TRUE) , THEN proceed to RFID test --- ELSE IF fingerprint is unauthentic (FALSE) , THEN display an error message on the lcd.

But then I realized that this isn't working because my fingerprint sensor keeps checking for a fingerprint after short intervals, say 10 seconds. Now when I put my finger ,the condition only becomes TRUE for 10 seconds and then again it will become FALSE. Using the IF-ELSE condition here means that the program will only proceed to the next stage for 10 seconds and then the program would break giving an error message.

I want some kind of condition which goes like if the condition was TRUE once , proceed to the next stage and do not check fingerprint again.Otherwise the program would break.

Somebody please help me out!

You could use a State machine for this. Advance to the next state when the current state is satisfied. When a time out happens, go back to the first state. StateMachine

But then I realized that this isn't working because my fingerprint sensor keeps checking for a fingerprint after short intervals, say 10 seconds.

Then, don't write the code that way.

Actually, the fingerprint scanner SHOULD check ofter, as should the RFID scanner, as should the keypad. It's what you do with the data that is important. Paranoid, though, aren't you?

PaulS: Then, don't write the code that way.

Actually, the fingerprint scanner SHOULD check ofter, as should the RFID scanner, as should the keypad. It's what you do with the data that is important. Paranoid, though, aren't you?

well...maybe ....but I was wondering if all of them keep working and checking often, then that means I could pass any of the stages anytime in any order and open the door . What I really want is pass each and every stage and that too , one after another , and that too in the defined order.

LarryD: You could use a State machine for this. Advance to the next state when the current state is satisfied. When a time out happens, go back to the first state. StateMachine

Thanks for helping out. I went over the link but as I am not very good at programming , I dont really understand how to use the State Machine Function for this doorlock . Can you explain a bit ? or if u can give a short example code for my scenario, that would help me greatly... :sweat_smile:

this isn't code but a example of what the code might look like

void loop() {
  
  
  
  
  
  switch (state) {
    case 0:
      Serial.println("access denied");
      state = 1;
      break;
    case 1:
      Serial.println("place finger on scanner");
      //call fingerprint code
      //fingerprint()
      if (fingerCode == 1) {
        Serial.println("finger print excepted");
        state = 2;
      }
      if (fingerCode == 0 && timerIsDone) {
        Serial.println("finger print rejected");
        State = 0;
      }
      break;
    case 2:
      Serial.println("put card to sensor");
      if (cardCode == 1) {
        Serial.println("card excepted");
        state = 3;
      }
      if (cardCode == 0 && timerIsDone) {
        Serial.println("card rejected");
        state = 0;
      }
      break;
    case 3:
      Serial.println("enter password");
      if (password == 1) {
        Serial.println("password excepted");
        state = 4;
      }
      if (password == 0 && timerIsDone) {
        Serial.println("password rejected");
        state = 0; //go to beginning or allow another attempt
      }
      break;
    case 4:
      //open door lock
      break;
  }
}

While you could do this using if/else statements it would be easier to create and understand using a state machine.

I could pass any of the stages anytime in any order and open the door

This is where you need to control the logic of how you progress thru the different states(cases) you will need to learn how to use Logical Operators.

Using gpop1's example case 3 might look like:

case 3:
      Serial.println("enter password");
      if (password == 1 && fingerprint has been accepted && RFID has been accepted) {
        Serial.println("password excepted");
        state = 4;
      }

by using the logical operator && the password will not be accepted unless both fingerprint and RFID have already been accepted.

Using these techniques you could easily add features such as after 3 tries it wont allow any more tries for a set period of time or one i always thought would be good is a capacitive switch connected to a nearby bolt/screw head that needs to be touched or it wont accept input.

lots of things a paranoid mind could come up with ;)

well, the code makes sense....ummm... what do i do if I want to give another chance after a wrong attempt/try

gpop1:         state = 0; //go to beginning or allow another attempt

what do i change in this line for a retry or maybe 2 retries/re-attempts?

Hutkikz:
Using these techniques you could add features such as after 3 tries it wont allow
any more tries for a set period of time etc.

Can you please give me a hint how do I make that delay?

Maaz_Khurram: well, the code makes sense....ummm... what do i do if I want to give another chance after a wrong attempt/try

what do i change in this line for a retry or maybe 2 retries/re-attempts?

that line does take you back to the beginning to make another attempt .

if you want to limit the number of tries you need to create a variable to keep track of how many tries have been made and increment it every time you try. when the maximum is reached set a case that handles a delay

Maaz_Khurram: well, the code makes sense....ummm... what do i do if I want to give another chance after a wrong attempt/try

what do i change in this line for a retry or maybe 2 retries/re-attempts?

I would add 2 more cases.

if password fail move from 3 to 4 if password fail move from 4 to 5 if password fail move from 5 to 0

if password excepted move from 3 to 7

7 open lock

as for a timer look at millis examples.

then use something like

unsigned long previousMillis = 0;
unsigned long interval = 3000; // 3 seconds

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:
  unsigned long currentMillis = millis();
  switch (state) {
    case 0:
      Serial.println("access denied");
      state = 1;
      break;
    case 1:
      Serial.println("place finger on scanner");
      //call fingerprint code
      //fingerprint()
      if (fingerCode == 1) {
        Serial.println("finger print excepted");
        state = 2;
        previousMillis = currentMillis;
      }
      if ((fingerCode == 0 || (currentMillis - previousMillis >= interval)) {
      Serial.println("finger print rejected");
        State = 0;
      }
      break;
    case 2:
        Serial.println("put card to sensor");
        if (cardCode == 1) {
        Serial.println("card excepted");
          state = 3;
          previousMillis = currentMillis;
        }
      if ((cardCode == 0 || (currentMillis - previousMillis >= interval)) {
      Serial.println("card rejected");
        state = 0;
      }
      break;
    case 3:
        Serial.println("enter password");
        if (password == 1) {
        Serial.println("password excepted");
          state = 7;
          previousMillis = currentMillis;
        }
      if ((password == 0 || (currentMillis - previousMillis >= interval)) {
      Serial.println("password rejected");
        state = 4; //go to beginning or allow another attempt
      }
      break;
    case 4:
        Serial.println("enter password attempt 2");
        if (password == 1) {
        Serial.println("password excepted");
          state = 7;
          previousMillis = currentMillis;
        }
      if ((password == 0 || (currentMillis - previousMillis >= interval)) {
      Serial.println("password rejected attempt 2");
        state = 5; //go to beginning or allow another attempt
      }
      break;
    case 5:
        Serial.println("enter password last attempt");
        if (password == 1) {
        Serial.println("password excepted");
          state = 7;
          previousMillis = currentMillis;
        }
      if ((password == 0 || (currentMillis - previousMillis >= interval)) {
      Serial.println("password rejected");
        state = 0; //go to beginning or allow another attempt
      }

      break;
    case 7:
        //open door lock
        //once open return to state 0 and relock door
        break;
      }
}

}

thanks , gonna try that out....one other thing , I want to make this lock a bit more personalized,smooth and quick . A normal person trying to open the lock will have to go through all the 7 steps following the instructions showing up on the lcd and this whole thing takes a lot of time. So I want to create a short route to open the door lock that just the authorized personnel know. For example, I was thinking that even though all the stages come one by one, I want my 4x3 keypad (as the keypad doesn't have any LEDs which show a new user that it can be used before time) to remain active throughout the process . Like if I just enter the passcode on the 4x3 keypad straight away , it will not need to verify my fingerprint , RFID etc. But only and only I will know this info about the 4x3 keypad and nobody else.....what would be the changes in the code you just provided? :o

we could go round and round for days on this

you need a plan

you need to make small sketches that test the fingerprint sensor, keypad, password, rfid to see what conditions you can receive from each test.

example: does the rdif tell you if a card was swiped but failed to match the database or does it only tell you when a card was excepted?

you will also need to look at the example code "blink with out delay" as this code is going to require a very good understanding of timing

The fact that you said " A normal person trying to open the lock will have to go through all the 7 steps following the instructions " shows that you do not understand the code I posted. 7 steps would be if they fail to enter the password correctly. There are only 3 steps if every test is accepted first time.

The plan needs to include how to unlock and relock the door.

gpop1:
1–you need to make small sketches that test the fingerprint sensor, keypad, password, rfid to see what conditions you can receive from each test.

2–you will also need to look at the example code “blink with out delay” as this code is going to require a very good understanding of timing

3–The fact that you said " A normal person trying to open the lock will have to go through all the 7 steps following the instructions " shows that you do not understand the code I posted. 7 steps would be if they fail to enter the password correctly. There are only 3 steps if every test is accepted first time.

1–Well, I tried many small sketches for testing if my modules are working . I made individual programs for these modules with lcd and a servo as a small test. Now I am working on combining on all these sketches into a one master sketch .

3–Ahhh…I was referring to some different 7 stages…not the 7 stages in the code…actually, I just mentioned 3 sensors over here just to explain the problem…in real, I am gonna use about 7-8 sensors so ultimately, user will have to got through 7-8 stages if he makes no mistake, if he does, even more stages just like your code suggests :slight_smile:

2–Nevertheless, I will go over “blink without delay” sketch to get a better idea…Thanks for the help guys…I will work with the code and let you know if there are any problems. Again, a massive thank you for helping me here! :slight_smile:

guys, I tried a lot to call the fingerprint function but I am still unable to do it.

I have the fingerprint sketch here:

/*************************************************** 
  This is an example sketch for our optical Fingerprint sensor

  Designed specifically to work with the Adafruit BMP085 Breakout 
  ----> http://www.adafruit.com/products/751

  These displays use TTL Serial to communicate, 2 pins are required to 
  interface
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/


#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>

int getFingerprintIDez();

// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
SoftwareSerial mySerial(52,53);


Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

void setup()  
{
  Serial.begin(9600);
  Serial.println("fingertest");

  // set the data rate for the sensor serial port
  finger.begin(57600);
  
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1);
  }
  Serial.println("Waiting for valid finger...");
}

void loop()                     // run over and over again
{
  getFingerprintIDez();
  delay(50);            //don't ned to run this at full speed.
}

uint8_t getFingerprintID() {
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }
  
  // OK converted!
  p = finger.fingerFastSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    Serial.println("Did not find a match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }   
  
  // found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID); 
  Serial.print(" with confidence of "); Serial.println(finger.confidence); 
}

// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK)  return -1;

  p = finger.image2Tz();
  if (p != FINGERPRINT_OK)  return -1;

  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK)  return -1;
  
  // found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID); 
  Serial.print(" with confidence of "); Serial.println(finger.confidence);
  return finger.fingerID; 
}

and I have to put in the above code in another master code which was mentioned earlier in this thread:

case 1:

  • Serial.println(“place finger on scanner”);*
    _ //call fingerprint code_
    ** //fingerprint()**

I asked around in other forums as well but didn’t get a satisfactory reply. Plz help me out here so that I copy the same thing for other sensors as well and make my master sketch complete. Thanks in advance!

guys, I tried a lot to call the fingerprint function but I am still unable to do it.

To call which fingerprint function? Where is one of your attempts? What problems did you have? Or psychic is out on maternity leave. He's due back on the 12th of never. If you can't wait, post some attempt.

PaulS:
To call which fingerprint function? Where is one of your attempts? What problems did you have?

I was trying to call the routine where the fingerprint sensor becomes active and tests the fingers. As far as I know its getFingerprintID().
This was my attempt to merge the two codes:

unsigned long previousMillis = 0;
unsigned long interval = 3000; // 3 seconds
int state;
#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>
int getFingerprintIDez();

// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
SoftwareSerial mySerial(52,53);


Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);


void setup() {
  {
  Serial.begin(9600);
  Serial.println("fingertest");

  // set the data rate for the sensor serial port
  finger.begin(57600);
  
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1);
  }
  Serial.println("Waiting for valid finger...");
}// put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:
  unsigned long currentMillis = millis();
  switch (state) {
    case 0:
      Serial.println("access denied");
      state = 1;
      break;
    case 1:
      Serial.println("place finger on scanner");
      int getFingerprintIDez();
      int getFingerprintID();
//      if (fingerCode == 1) {
//        Serial.println("finger print excepted");
//        state = 2;
//        previousMillis = currentMillis;
//      }
//      if ((fingerCode == 0 || (currentMillis - previousMillis >= interval)) {
//      Serial.println("finger print rejected");
//        State = 0;
//      }
//      break;
//    case 2:
//        Serial.println("put card to sensor");
//        if (cardCode == 1) {
//        Serial.println("card excepted");
//          state = 3;
//          previousMillis = currentMillis;
//        }
//      if ((cardCode == 0 || (currentMillis - previousMillis >= interval)) {
//      Serial.println("card rejected");
//        state = 0;
//      }
//      break;
//    case 3:
//        Serial.println("enter password");
//        if (password == 1) {
//        Serial.println("password excepted");
//          state = 7;
//          previousMillis = currentMillis;
//        }
//      if ((password == 0 || (currentMillis - previousMillis >= interval)) {
//      Serial.println("password rejected");
//        state = 4; //go to beginning or allow another attempt
//      }
//      break;
//    case 4:
//        Serial.println("enter password attempt 2");
//        if (password == 1) {
//        Serial.println("password excepted");
//          state = 7;
//          previousMillis = currentMillis;
//        }
//      if ((password == 0 || (currentMillis - previousMillis >= interval)) {
//      Serial.println("password rejected attempt 2");
//        state = 5; //go to beginning or allow another attempt
//      }
//      break;
//    case 5:
//        Serial.println("enter password last attempt");
//        if (password == 1) {
//        Serial.println("password excepted");
//          state = 7;
//          previousMillis = currentMillis;
//        }
//      if ((password == 0 || (currentMillis - previousMillis >= interval)) {
//      Serial.println("password rejected");
//        state = 0; //go to beginning or allow another attempt
//      }

  //    break;
    case 7:
        //open door lock
        //once open return to state 0 and relock door
        break;
      }
}

So here’s one of my amateur attempts. I am having a hard time trying to figure out where the problem is. When I upload this code I get only this repeatedly on the Serial monitor :

fingertest
Found fingerprint sensor!
Waiting for valid finger…
access denied

Note: This was just for testing fingerprint sensor. So I have commented the useless lines.

  switch (state) {
    case 0:
      Serial.println("access denied");
      state = 1;
      break;

So, state defaults to 0, so on the first pass through loop(), you get the access denied message, and state is set to 1.

On subsequent passes:

    case 1:
      Serial.println("place finger on scanner");
      int getFingerprintIDez();
      int getFingerprintID();

You should be printing a message and then declaring two function prototypes. You are NOT calling either function.

And, neither function is in that snippet.

in the code example I posted

 case 1:
      Serial.println("place finger on scanner");
      //call fingerprint code
      //fingerprint()
      if (fingerCode == 1) {
        Serial.println("finger print excepted");
        state = 2;
        previousMillis = currentMillis;
      }
      if ((fingerCode == 0 || (currentMillis - previousMillis >= interval)) {
      Serial.println("finger print rejected");
        State = 0;
      }
      break;

you seem to have read this as real code rather than a example of what the code could be

your finger print sketch needs to return 3 different states to the program

0/ nothing happening waiting 1/ finger print was taken and failed , set state back to 0 2/ finger print was taken and passed, set state to 2

you can call the finger print code inside the switch and use there code as long as you add the extra lines to change state.

as finger print is the first step then theres no need for a timer

gpop1: you can call the finger print code inside the switch

I am having great trouble calling the fingerprint code . I saw many other posts on this topic, even posted on different forums , made some attempts myself but it doesn't work . I posted one of my attempt in reply#17. If you can please be kind enough to just point out how fingerprint code will be called in this case, it would be a great help. I am totally clueless now about this issue. :(

P.S: I know you posted the example code. I am trying to use that as a structure and add relevant code where necessary. I will increase the states afterwards cuz I will be using more than 3 sensors....but for now , i just wanna make sure the first test (fingerprint test) works and something comes up on my serial monitor . That's why I commented the other lines out in reply#17