Notifications
Clear all

4 Solenoid combination lock

13 Posts
3 Users
4 Likes
506 Views
(@nerguy197)
Member
Joined: 2 years ago
Posts: 6
Topic starter  

Hey Guys,

I'm just learning this stuff so bear with me if this is a total trainwreck...

I wanted to build a combination lock with 4 solenoid outputs so the user can enter one of 4 stored passwords and it and open whichever lock corresponds to that code.  I also want to make it so the master password can be entered allowing a change of password to any of the 4 lock combinations.  I started with the keypad combination program with lcd project i found on the dronebot youtube video and got that fully working.  

I tried to modify it but that totally didn't work and my knowledge of programming is beginner level, so I called my brother who knows some programming but isn't too familiar with C and he gave it a crack. I sent him the original code and he modified it.   That's the code posted here.  

The equipment I'm using is a 4x4 matrix keypad, lcd display with i2c backpack, arduino uno, 4 relay opto coupled (5V control), and 4 12V lock solenoids powered by a benchtop power supply.  

 

When I enter the correct master password into the program it will print "master password not supported yet" as intended.  

 

When I entered any of the pre programmed stored user passwords it prints "wrong password" then returns to the beginning of the loop.  I intended it to compare the input to a stored pw and output on the associated pin to relay.  

 

Any ideas?

/*
Matrix Keypad Combination Lock Demo
keypad-demo-lock.ino
Combination lock using 4x4 matrix membrane keypad with Arduino
Results on LCD display
Drives relay

DroneBot Workshop 2020
https://dronebotworkshop.com

Based upon code from https://www.circuitbasics.com/

*/

// Include Arduino Wire library for I2C
#include <Wire.h>
// Include LCD display library for I2C
#include <LiquidCrystal_I2C.h>
// Include Keypad library
#include <Keypad.h>
// EEPROM library
#include <EEPROM.h>

// Length of master_password password + 1 for null character
#define PASSWORD_LENGTH 8
// Character to hold master_password password input
char user_input[PASSWORD_LENGTH];

// Passwords
char master_password[PASSWORD_LENGTH] = "123A456";
#define NUM_USER_PASSWORDS 4
char user_passwords[NUM_USER_PASSWORDS][PASSWORD_LENGTH] = {"1111111", "2222222", "3333333", "4444444"};

// Pins connected to lock relay inputs. Pins 10-13 are available.
int lock_outputs[NUM_USER_PASSWORDS] = {10, 11, 12, 13};

// Counter for character entries
byte user_input_count = 0;

// Constants for row and column sizes
#define ROWS 4
#define COLS 4

// Array to represent keys on keypad
char hexaKeys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

// Connections to Arduino
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};

// Create keypad object
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

// Create LCD object
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup() {
// Setup LCD with backlight and initialize
lcd.init();
lcd.backlight();

// Set all lock_outputs as an OUTPUT pin
for (int output = 0; output++; output < NUM_USER_PASSWORDS) {
pinMode(lock_outputs[output], OUTPUT);
}

// Write the user passwords to EEPROM.
// For each password
for (int password_number = 0; password_number++; password_number < NUM_USER_PASSWORDS) {
// For each character in this password
int password_starting_address = password_number * PASSWORD_LENGTH;
for (int password_char = 0; password_char++; password_char < PASSWORD_LENGTH) {
int eeprom_address = password_starting_address + password_char;
// Write the current character to memory.
EEPROM.update(eeprom_address, user_passwords[password_number][password_char]);
}
}
}

// Loop forever.
void loop() {
// Initialize LCD and print
lcd.setCursor(0, 0);
lcd.print("Enter Password:");
digitalWrite(lock_outputs[0], HIGH);

// Look for keypress
readKeypad(user_input);

// See if we have reached the password length
if (user_input_count == PASSWORD_LENGTH - 1) {
lcd.clear();

// Compare the user-supplied password with stored passwords.
int match_found = checkPassword(user_input);

// Password is incorrect.
if (match_found < 0) {
lcd.print("Incorrect Password");
delay(1000);
}

// Clear user_input and LCD display
lcd.clear();
clearUserInput();
}
}

// Determine if the entered password is a match and do something if it is.
int checkPassword(char user_input[]) {
// If this is a master password match, do something...
if (!strcmp(user_input, master_password)) {
handleMasterPassword();
return 12345; // Just a random number.
}

// Check all the stored user passwords.
char storedUserPassword[PASSWORD_LENGTH];
for (int stored_password = 0; stored_password++; stored_password < NUM_USER_PASSWORDS) {

// Get the current stored password, one char at a time.
int password_starting_address = stored_password * PASSWORD_LENGTH;
for (int password_char = 0; password_char++; password_char < PASSWORD_LENGTH) {
int eeprom_address = password_starting_address + password_char;
// Write the current character to memory.
EEPROM.get(eeprom_address, storedUserPassword[password_char]);
}

// If this is a user match, open the proper relay.
if (!strcmp(user_input, storedUserPassword)) {
lcd.print("Dispensing Key!");
delay(5000);

int output_pin = lock_outputs[stored_password];

// Turn on relay for 5 seconds
digitalWrite(output_pin, LOW);
delay(5000);
digitalWrite(output_pin, HIGH);
return stored_password;
}
}

return -1;
}

void clearUserInput() {
// Go through array and clear user_input
while (user_input_count != 0) {
user_input[user_input_count--] = 0;
}
return;
}

// Handle a master password input.
void handleMasterPassword() {
lcd.print("Master Pass not supported yet");
delay(5000);
return false;

// TODO: Write some logic to enable the master password to program a user password slot.
lcd.print("Enter the user password number to set:");
int password_number = customKeypad.getKey();

if (setUserPassword(password_number)) {
lcd.print("Success!");
} else {
lcd.print("You suck!");
}
}

// Read input and set a new user password in the specified slot.
bool setUserPassword(int password_number) {
// Get the new password.
char message[64];
snprintf(message, sizeof(message), "Enter the user password for slot #%d", password_number);
lcd.print(message);
// Read `PASSWORD_LENGTH` keys
while (user_input_count < PASSWORD_LENGTH - 1) {
readKeypad(user_input);
}

// Validate passcode entry by getting the password again.
lcd.clear();
snprintf(message, sizeof(message), "Re-Enter the user password for slot #%d", password_number);
lcd.print(message);
// Read `PASSWORD_LENGTH` inputs
char user_input2[PASSWORD_LENGTH];
// Read `PASSWORD_LENGTH` keys
while (user_input_count < PASSWORD_LENGTH - 1) {
readKeypad(user_input2);
}

// Don't write to EEPROM if the passwords don't match.
if (strcmp(user_input, user_input2)) {
return false;
}

// Entry complete; write to EEPROM.
int password_starting_address = password_number * PASSWORD_LENGTH;
for (int password_char = 0; password_char++; password_char < PASSWORD_LENGTH) {
int eeprom_address = password_starting_address + password_char;
// Write the current character to memory.
EEPROM.update(eeprom_address, user_input[password_char]);
}

return true;
}

// Reads one character from the keypad into the `user_input` array.
void readKeypad(char input[]) {
// Look for keypress
char customKey = customKeypad.getKey();
if (customKey) {
// Enter keypress into array and increment counter
input[user_input_count] = customKey;
lcd.setCursor(user_input_count, 1);
lcd.print(input[user_input_count]);
user_input_count++;
}
}

 

 

 


   
Quote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2535
 

Anything seems possible when you don't know what you're talking about.


   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 7001
 

@will I was going to reply that until the code was readable I wasn't interested. I am sure you know there is a format function in the IDE menu under Tools/Auto Format. Back in my IBM days, I would fail a programmer if the code was not formatted to my standard (I was the standards guru as well as project tech and project management guru)

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2535
 

@zander 

Yeah, but there was that nice shiny (out-of-date) .ino file just sitting there and I wouldn't have to copy and paste anything, it was there all shiny and soft and ... ahem, yes - well it just seemed easier 🙂

Anything seems possible when you don't know what you're talking about.


   
Inst-Tech and Ron reacted
ReplyQuote
(@nerguy197)
Member
Joined: 2 years ago
Posts: 6
Topic starter  

Wow, I didn't expect replies that quickly!  Yeah, sorry about the format.  As I said I'm new to this.  I can clearly see the niceness of Will's code vs. mine that was modified by my brother.  Thanks for the replies and especially to Will.  No, I wasn't aware of the auto format function.  Thanks for pointing that out.  I'll test this code tonight and post what happens!!


   
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2535
 

@nerguy197 

I had some time to look over the updated version and I note that the password length has changed and that you're using EEPROM to store passwords between sessions. I have made some changes to separate out EEPROM operations and simplify the password management.

I have not filled in any of the required operations except for preloading the password set from the EEPROM in setup() because I don't know how you intend to implement them

I have renamed the file to make it version 5.2 since this is the second revision.

Anything seems possible when you don't know what you're talking about.


   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 7001
 

@will Good start @will. Is there any reason why the compare password function isn't 

return(strcmp(raw, final));

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2535
 

@zander 

You'll note that the password set is now an array of chars instead of an array of C-strings, so they no longer have their terminating zero char which I believe is required by strcmp.

Anything seems possible when you don't know what you're talking about.


   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 7001
 

@will Ok, but there are ways around that, just real quick, make the array 1 bigger than max password length, then fill the array with all 0's. You could also use the strncmp function since you are using PASSWORDLENGTH anyway.

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2535
 

@zander 

Of course. There are many ways of doing the comparison but there's only room for one in the sketch (so far at least) 🙂

Anything seems possible when you don't know what you're talking about.


   
ReplyQuote
(@nerguy197)
Member
Joined: 2 years ago
Posts: 6
Topic starter  

OK, here's where this project is currently.  My brother had extra time and re wrote the program and I built it on my bench and tested it.  We de bugged it and it works well.  Thanks to everyone who helped, especially Will who spent time writing code for me.  I look forward to learning more as I digest what is actually going on with the code (as well as Will's).  I think this was too large of a project for my first one honestly.  Hardware wise, no, but software wise, definitely.  

 

I've posted a file so everyone can use it if they want.  This is for a key box system that will hold keys in 4 separate boxes with unique codes to unlock them. This is how it operates:

 

There is a master password that can be entered to change any one of the 4 box codes.  Once entered it will prompt to confirm.  Once confirmed it will store that combo in memory even if the power is disconnected.  When that individual code is entered it unlocks one of the 4 boxes for 5 sec. via a relay.  

 

There are several messages displayed at any given point via LCD display that you can see in the program.  

 

Thanks again for the help.  I look forward to doing more fun Arduino projects in the future!

 

P.S.  - is it practical to do home automation with Arduino?  I think it would be kind of cool. 


   
Inst-Tech reacted
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2535
 

@nerguy197 

Good, it's always satisfying to see somebody successfully complete a project 🙂

Anything seems possible when you don't know what you're talking about.


   
Inst-Tech reacted
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 7001
 

@nerguy197 Absolutely, in fact I think many commercial home automation devices are ESP8266 or ESP32. Not exactly Arduino but most folks include them when speaking about 'arduino', after all the Arduino IDE and the new cloud support them.

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote