Safe with Display and Buttons

Hello there!

For a school project, I have to create a "hotel safe" with the LCD display and six buttons. Four of them are for the digits 1, 2, 3, 4 and the other two left are for set and clear.

I just started with the programming and I haven't much experience yet. So, here's what I got (I excluded the setup):

if(codeset==0){ //If devie is run for the first time, do this
    while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW && setbtn==LOW && clsbtn==LOW){
      lcd.setCursor(0,5);
      lcd.print("Hello");
      lcd.setCursor(1,1);
      lcd.print("Press any key");
    }
    while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Set password");
    }

Until here, everything's okay. But now, I don't know how to continue - the user now has to set a 4-digit password with the digits 1-4 (buttons n1btn, n2btn, n3btn & n4btn). But how can you do this and how do you store the password combination and use it for lates use (e.g. unlocking the safe)?

Thanks for your advice!

Greetings from Switzerland,
Sandro

I typed up a complete answer, and then snipped a bunch of it. This is what is left.

If you post ALL of your code, I'll post all of my answer.

So here's all of my code, now it's your turn to post all of your answer:

#include <LiquidCrystal.h> //Bibliothek für das Display inkludieren

LiquidCrystal lcd(12,11,5,4,3,2); //Pins des Displays einlesen
int n1btn, n2btn, n3btn, n4btn, setbtn, clsbtn; //Variablen für Buttons deklarieren
int ln1btn, ln2btn, ln3btn, ln4btn; //Variablen für last Button State
int codeset = 0; //Variable zur Überprüfung, ob das Gerät zum ersten Mal gestartet wird
int password;

void setup() {
  lcd.begin(16,2); //Pins des Displays konfigurieren
  pinMode(0,INPUT); //Pins der Buttons konfigurieren
  pinMode(1,INPUT);
  pinMode(6,INPUT);
  pinMode(7,INPUT);
  pinMode(8,INPUT);
  pinMode(9,INPUT);
  n1btn = digitalRead(6); //Buttons einlesen in die Variablen
  n2btn = digitalRead(7);
  n3btn = digitalRead(8);
  n4btn = digitalRead(9);
  clsbtn = digitalRead(0);
  setbtn = digitalRead(1);
  ln1btn = n1btn;
  ln2btn = n2btn;
  ln3btn = n3btn;
  ln4btn = n4btn;
}

void loop() {
  lcd.clear(); //Display leeren (zur Sicherheit)
  if(codeset==0){ //Falls das Gerät zum ersten Mal gestartet wird, folgendes ausführen
    while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW && setbtn==LOW && clsbtn==LOW){
      lcd.setCursor(0,5);
      lcd.print("Hello");
      lcd.setCursor(1,1);
      lcd.print("Press any key");
    }
    while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Set password");
    }
    
    
  }else{
    
  }

}

Ignore the german comments

sandroko:
So here's all of my code, now it's your turn to post all of your answer:

:slight_smile: :slight_smile: :slight_smile:

You need a counter to count how may digits of the code have been entered.
You need an array to store each of the digits as they are pressed.

Keep using the LCD for the User Interface, but also add some print statements into your code so that you can 'see' what it is doing.

Also think about what states your safe might be in e.g. code set/not set, opened/closed, locked/unlocked

The "loop()" method is repeated over and over until the arduino is turned off. For each loop you are clearing the display and writing the same text to it. You should start by modifying your code so that the display is only cleared and written to when necessary. When you've got that sorted, you can continue with actually reading the code / number sequence and store it in memory (char codeBuffer[4]) - but in order to do this, you would need to learn how to read the state of a button and how to handle debounce :slight_smile:

Oh, and: The "setup()" method is only executed once during startup - reading the button pins here makes no sense since their state may change during the "loop()" phase of your sketch :slight_smile:

int n1btn, n2btn, n3btn, n4btn, setbtn, clsbtn; //Variablen für Buttons deklarieren
int ln1btn, ln2btn, ln3btn, ln4btn; //Variablen für last Button State

Arrays are your friends, not you enemies.

   while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW && setbtn==LOW && clsbtn==LOW){
      lcd.setCursor(0,5);
      lcd.print("Hello");
      lcd.setCursor(1,1);
      lcd.print("Press any key");
    }

n1btn, n2btn, n3btn, n4btn, setbtn, and clsbtn are not bound to the digitalRead() function. If all of the switches are not pressed when the Arduino boots up, you will enter this while loop with no way to exit it.

How ARE your switches wired? You are not using the internal pullup resistors, so you must have external resistors. How are they wired?

   while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Set password");
    }

Another infinite loop with no way to exit.

You need to scrap this code, and start over. Treat each switch COMPLETELY independently.

There are two parts to your project - setting the initial code and entering the code to re-open the door.

You need to look at the state change detection example, to learn how to detect that a switch HAS BECOME, not IS, pressed.

When you are in the "Enter a new door lock code" mode, each time a switch has become pressed, you record the number of the switch in an array and increment the index into the array. When the 4th switch has been pressed, you exit the "Enter a new door lock code" and enter the "Guess the door combination" mode.

In that mode, each time a switch has become pressed, you record the number of the switch in a different array. When the 4th switch has been pressed, you compare the contents of the two arrays, and open the door, or not, depending on whether the values match, or not.

An oops key and a "shit, I want to start over" key are good things to have. And to handle.

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

How have you got your buttons wired.
Are they press/momentary buttons?

Thanks.. Tom... :slight_smile:

PaulS:

int n1btn, n2btn, n3btn, n4btn, setbtn, clsbtn; //Variablen für Buttons deklarieren

int ln1btn, ln2btn, ln3btn, ln4btn; //Variablen für last Button State



Arrays are your friends, not you enemies.



while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW && setbtn==LOW && clsbtn==LOW){
      lcd.setCursor(0,5);
      lcd.print("Hello");
      lcd.setCursor(1,1);
      lcd.print("Press any key");
    }



n1btn, n2btn, n3btn, n4btn, setbtn, and clsbtn are not bound to the digitalRead() function. If all of the switches are not pressed when the Arduino boots up, you will enter this while loop with no way to exit it.

How ARE your switches wired? You are not using the internal pullup resistors, so you must have external resistors. How are they wired?



while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Set password");
    }



Another infinite loop with no way to exit.

You need to scrap this code, and start over. Treat each switch COMPLETELY independently.

There are two parts to your project - setting the initial code and entering the code to re-open the door.

You need to look at the state change detection example, to learn how to detect that a switch HAS BECOME, not IS, pressed.

When you are in the "Enter a new door lock code" mode, each time a switch has become pressed, you record the number of the switch in an array and increment the index into the array. When the 4th switch has been pressed, you exit the "Enter a new door lock code" and enter the "Guess the door combination" mode.

In that mode, each time a switch has become pressed, you record the number of the switch in a different array. When the 4th switch has been pressed, you compare the contents of the two arrays, and open the door, or not, depending on whether the values match, or not.

An oops key and a "shit, I want to start over" key are good things to have. And to handle.

Hey Paul,

thanks for your answer!

I just really didn't see, that you cannot exit the while loops, so I updated that. I also added an "codeindex" integer to count the digits to exit the "Set Code" after four digits are entered.
But can you explain me how you would do it and paste an example code? I'm just a newbie and I don't know what an array is.

And to clarify a bit: I've got the SET and CLEAR buttons (setbtn & clsbtn in the code). If you press the CLEAR button while setting the password, it should go back to the beginning and delete the WHOLE password, not just the last digit that was entered.

I think, if I got it how to set a password and read it to "unlock" the safe, I'm able to do it on my own with the different states.
And as it's a school project, I also got a state diagram and attached it as a png (unfortunatly, its commented in german).

And finally, here's the whole code:

#include <LiquidCrystal.h> //Bibliothek für das Display inkludieren

LiquidCrystal lcd(12,11,5,4,3,2); //Pins des Displays einlesen
int n1btn, n2btn, n3btn, n4btn, setbtn, clsbtn; //Variablen für Buttons deklarieren
int ln1btn, ln2btn, ln3btn, ln4btn; //Variablen für last Button State
int codeset = 0; //Variable zur Überprüfung, ob das Gerät zum ersten Mal gestartet wird
int password, codeindex;

void setup() {
  lcd.begin(16,2); //Pins des Displays konfigurieren
  pinMode(0,INPUT); //Pins der Buttons konfigurieren
  pinMode(1,INPUT);
  pinMode(6,INPUT);
  pinMode(7,INPUT);
  pinMode(8,INPUT);
  pinMode(9,INPUT);
  ln1btn = n1btn;
  ln2btn = n2btn;
  ln3btn = n3btn;
  ln4btn = n4btn;
  codeindex = 1;
}

void loop() {
  n1btn = digitalRead(6); //Buttons einlesen in die Variablen
  n2btn = digitalRead(7);
  n3btn = digitalRead(8);
  n4btn = digitalRead(9);
  clsbtn = digitalRead(0);
  setbtn = digitalRead(1);
  
  if(codeset==0){ //Falls das Gerät zum ersten Mal gestartet wird, folgendes ausführen
    while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW && setbtn==LOW && clsbtn==LOW){
      n1btn = digitalRead(6); //Buttons einlesen in die Variablen
      n2btn = digitalRead(7);
      n3btn = digitalRead(8);
      n4btn = digitalRead(9);
      clsbtn = digitalRead(0);
      setbtn = digitalRead(1);
      lcd.setCursor(0,5);
      lcd.print("Hello");
      lcd.setCursor(1,1);
      lcd.print("Press any key");
    }
    while(n1btn==LOW && n2btn==LOW && n3btn==LOW && n4btn==LOW){
      n1btn = digitalRead(6); //Buttons einlesen in die Variablen
      n2btn = digitalRead(7);
      n3btn = digitalRead(8);
      n4btn = digitalRead(9);
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Set password");
    }

    if(n1btn==LOW){
      //How do i set a code in here?
    }
    
    
    codeset = 1; //Nach dem ersten Start anpassen
  }else{
    
  }

}

Greetings,
Sandro

    if(n1btn==LOW){
      //How do i set a code in here?
    }

Don't worry about that, yet. You want to record the fact that the nth switch HAS BECOME pressed, in the mth position in the array that you don't have.

You MUST look at the state change detection example to learn how to detect that a switch HAS BECOME pressed.

Your entire code is based on the "do nothing unless" principal, which is a lousy way to program.

Instead, it should be based on a "do something if" principal.

On any given pass through loop(), you should read the state of all 6 switches, and compare the current states to the previous states. When a change is detected, you then need to decide if the change was from not pressed to pressed, or from pressed to not pressed.

There may be things you want to do when a given switch becomes pressed, and there may be things you want to do when a given switch becomes released. Or, one change may be completely meaningless.

As you can probably imagine, being able to read the 4 number switches in a for loop would be advantageous. Instead of blowing off arrays because you don't know anything about them, hit the reference page and learn something.

byte numberPins[4] = { 6, 7, 8, 9 };
byte currStates[4];
byte prevStates[4];
byte lockCode[4];
byte lockIndex = 0;

void loop()
{
   for(byte b=0; b<4; b++)
   {
      currState[b] = digitalRead(numberPins[b]);
      if(currState[b] != prevState[b])
      {
         // The state of the bth pin changed...
         if(currState[b] == LOW)
         {
            // to pressed...
            if(lockIndex < 4)
            {
               lockCode[lockIndex++] = b+1;
            }
         }
      }
    }

    // Deal with the SET and CLEAR switches here
}

This is NOT complete. It is simply meant to show you how arrays can REALLY shorten your code. You'll still need to deal with the two modes - set the initial code and open the safe.

I unterstood that I should program in the "do-something-if" way and not in the "do-nothing-unless" way. But the point is, that I just don't know how to handle that.

So, I dont wan't to question your skills with the arduino programming language (in fact, almost C#) but your post is usless for me unless you explain how to do it (or just send me a link that describes it) - not what I have to do (except, you know a better way to do it as you did in your first post).

Thanks for your advice!

@sandroko: PaulS is in fact helping you a lot.. If what you want is working code, you should hire a programmer to do your homework for you :wink: