Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Door Lock logic v0.1 by @Caverntwo
- *
- * This code is published to accompany my video about my new door lock. It is published under the MIT License (see below).
- *
- * You need to have the LiquidCrystal_I2C Library by marcoschwartz installed for it to correctly compile with the latest Arduino IDE
- * (https://github.com/marcoschwartz/LiquidCrystal_I2C).
- *
- * I'M NOT A C/C++ PROGRAMMER AND DON'T KNOW A LOT ABOUT THE LANGUAGE!!!
- * This code is probably the worst you've seen so far! I'm not proud of it, but I don't know any better.
- * I'm going to improve, but this takes some time!
- *
- *
- * The MIT License
- *
- * Copyright 2018 Caverntwo
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- #include <LiquidCrystal_I2C.h>
- #include <Wire.h>
- class InputHandler
- {
- private:
- int *keys;
- int *rowPins;
- int *colPins;
- unsigned int keysLength;
- unsigned int rows;
- unsigned int cols;
- unsigned int subDelay;
- char entered;
- char invalid;
- unsigned long unblockMillis;
- public:
- InputHandler(unsigned int _subDelay, char _invalid, int *_keys, unsigned int _keysLength, int *_rowPins, unsigned int _rows, int *_colPins, unsigned int _cols)
- {
- keys = _keys;
- rowPins = _rowPins;
- colPins = _colPins;
- keysLength = _keysLength;
- rows = _rows;
- cols = _cols;
- subDelay = _subDelay;
- invalid = _invalid;
- entered = invalid;
- }
- void Setup()
- {
- for (unsigned int row = 0; row < rows; row++)
- {
- pinMode(rowPins[row], INPUT_PULLUP);
- }
- for (unsigned int col = 0; col < cols; col++)
- {
- pinMode(colPins[col], OUTPUT);
- }
- }
- void Update()
- {
- if (millis() > unblockMillis)
- {
- entered = invalid;
- //write columns and read rows
- int activeCol = -1;
- int activeRow = -1;
- for (unsigned int col = 0; col < cols; col++)
- {
- for (unsigned int scol = 0; scol < cols; scol++)
- {
- if (scol != col)
- {
- digitalWrite(colPins[scol], HIGH);
- }
- }
- digitalWrite(colPins[col], LOW);
- delay(subDelay);
- for (unsigned int row = 0; row < rows; row++)
- {
- if (digitalRead(rowPins[row]) == LOW)
- {
- activeCol = col;
- activeRow = row;
- }
- }
- }
- //decode result
- if (activeCol >= 0 && activeRow >= 0)
- {
- entered = keys[activeRow * cols + activeCol];
- }
- else
- {
- entered = invalid;
- }
- }
- }
- char GetEnteredKey()
- {
- return entered;
- }
- //blocks any input for the specified milliseconds
- void BlockInput(unsigned int milliseconds)
- {
- unblockMillis = millis() + milliseconds;
- }
- };
- class CodeBuilder
- {
- private:
- char* code;
- unsigned int codeLength;
- char* entered;
- unsigned int currentPosition = 0;
- unsigned int maxCodeLength;
- char invalid;
- void clearEntered()
- {
- for (unsigned int i = 0; i < maxCodeLength; i++)
- {
- entered[i] = invalid;
- currentPosition = 0;
- }
- }
- public:
- CodeBuilder(char* _code, unsigned int _codeLength, char _invalid, unsigned int _maxCodeLength)
- {
- code = _code;
- codeLength = _codeLength;
- maxCodeLength = _maxCodeLength;
- entered = new char[maxCodeLength];
- invalid = _invalid;
- clearEntered();
- }
- void AddChar(char c)
- {
- if (currentPosition < maxCodeLength)
- {
- entered[currentPosition] = c;
- currentPosition++;
- }
- }
- bool VerifyEnteredCode()
- {
- currentPosition = 0;
- bool success = true;
- //get entered length
- unsigned int enteredLength = 0;
- for (unsigned int i = 0; i < maxCodeLength; i++)
- {
- if (entered[i] != invalid)
- {
- enteredLength++;
- }
- else
- {
- break;
- }
- }
- if (enteredLength != codeLength)
- {
- success = false;
- }
- else
- {
- //compare them in detail
- for (unsigned int i = 0; i < codeLength; i++)
- {
- if ((entered[i] != code[i]) || (entered[i] == invalid))
- {
- success = false;
- break;
- }
- }
- }
- //reset everything for the next time
- clearEntered();
- return success;
- }
- };
- class OutputHandler
- {
- private:
- LiquidCrystal_I2C lcd;
- char secret;
- long openTime;
- long waitTime;
- unsigned long lastMillis;
- bool successfulEntry = false;
- bool unsuccessfulEntry = false;
- int *outputPins;
- uint8_t outputPinsLength;
- bool outputPinsActiveLevel;
- char *line1;
- char *line2;
- char *success1;
- char *success2;
- char *fail1;
- char *fail2;
- void reset()
- {
- lcd.clear();
- lcd.setCursor(0,0);
- }
- void resetMessage()
- {
- reset();
- lcd.print(line1);
- lcd.setCursor(0,1);
- lcd.print(line2);
- }
- void unlockDoor()
- {
- for(int i = 0; i < outputPinsLength; i++)
- {
- digitalWrite(outputPins[i], outputPinsActiveLevel);
- }
- }
- void lockDoor()
- {
- for(int i = 0; i < outputPinsLength; i++)
- {
- digitalWrite(outputPins[i], !outputPinsActiveLevel);
- }
- }
- public:
- OutputHandler(uint8_t lcdRows, uint8_t lcdCols, unsigned int lcdI2CAddress, char _secret, long _openTime, long _waitTime, int *_outputPins, uint8_t _outputPinsLength, bool _outputPinsActiveLevel, char* _line1, char* _line2, char* _success1, char* _success2, char* _fail1, char* _fail2) : lcd(lcdI2CAddress, lcdCols, lcdRows)
- {
- secret = _secret;
- openTime = _openTime;
- waitTime = _waitTime;
- outputPins = _outputPins;
- outputPinsLength = _outputPinsLength;
- outputPinsActiveLevel = _outputPinsActiveLevel;
- line1 = _line1;
- line2 = _line2;
- success1 = _success1;
- success2 = _success2;
- fail1 = _fail1;
- fail2 = _fail2;
- }
- void Setup()
- {
- lcd.init();
- lcd.backlight();
- resetMessage();
- for (int i = 0; i < outputPinsLength; i++)
- {
- pinMode(outputPins[i], OUTPUT);
- }
- lockDoor();
- }
- void Update()
- {
- if (successfulEntry && (lastMillis + openTime < millis())) //openTime is over
- {
- resetMessage();
- successfulEntry = false;
- lockDoor();
- }
- if (unsuccessfulEntry && (lastMillis + waitTime < millis())) //closedTime is over
- {
- resetMessage();
- unsuccessfulEntry = false;
- }
- }
- void CodeCharEntered()
- {
- lcd.print(secret);
- }
- void CodeTrial(bool success)
- {
- if (success)
- {
- reset();
- lcd.print(success1);
- lcd.setCursor(0,1);
- lcd.print(success2);
- successfulEntry = true;
- unlockDoor();
- }
- else
- {
- reset();
- lcd.print(fail1);
- lcd.setCursor(0,1);
- lcd.print(fail2);
- unsuccessfulEntry = true;
- }
- lastMillis = millis(); //get the current Time
- }
- };
- /////////////////////////////////////////////////////////////////
- //Configuration Area - Do all your configs here!
- /////////////////////////////////////////////////////////////////
- ////Section: LCD Setup
- //Represent the keypad. The code will loop thru the columns and listens the rows for clicks.
- //Make sure that the total number of chars is equal to the total number of buttons!
- int keys[] = {
- '1','2','3',
- '4','5','6',
- '7','8','9',
- '*','0','#'
- };
- //The columns of the LCD
- const uint8_t lcdCols = 16;
- //The rows of the LCD
- const uint8_t lcdRows = 2;
- //The I²C Address of the LCD
- uint8_t lcdI2CAddress = 0x27;
- ////================================================================
- ////Section: Arduino Pins
- ////================================================================
- //The pins where the rows are connected to: 1 pin per row only!!!
- int rowPins[] = {2,3,4,5};
- //The pins where the columns are connected to: 1 pin per column only!!!
- int columnPins[] = {6,7,8};
- //The pins that are switched on a successful code. You can add as many as you want and have.
- int outputPins[] = {10,11};
- //Should the output pins be HIGH or LOW on successful entry?
- bool outputPinsActiveLevel = LOW;
- ////================================================================
- ////Section: Characters and Password / Code
- ////================================================================
- //The password that needs to be entered to unlock the door. Make sure that it only contains characters
- //of the keypad and neither the invalid and the accept character! Also, it mustn't be longer than the maxCodeLength!
- char password[] = "12345";
- //The maximum code length. I was about to hard-calculate it but it could be used to set a maximum entry length.
- //Further characters will be ignored.
- //Example: if you have a 16x2 LCD, "Code:" takes 5 characters, so the most
- uint8_t maxCodeLength = 10;
- //The character (found in the keys[]) that accepts the code entry. It mustn't be part of password[]!
- char acceptKey = '#';
- //The character used for displaying the entered code on the LCD. It can be whatever the LCD understands.
- char lcdSecret = '*';
- //The character representing "invalid". Set it to something you do not have in your keys[]!
- char invalid = ' ';
- //The amount of milliseconds to wait between each keypad loop.
- unsigned int subDelay = 2;
- ////================================================================
- ////Section: Timing
- ////================================================================
- //The time to wait after unsuccessful entry [ms]
- long waitTime = 10000;
- //The time the door relay is unlocked (successful entry) [ms]
- long openTime = 2500;
- ////================================================================
- ////Section: Texts
- ////================================================================
- //The text displayed in the first line
- char Line1[lcdCols+1] = "3d-print shop";
- //The text displayed in front of the entered code
- char Line2[lcdCols+1] = "Code:";
- //The text displayed in the first line when the entered code was correct.
- char Success1stLine[lcdCols+1] = "Code correct!";
- //The text displayed in the second line when the entered code was correct.
- char Success2ndLine[lcdCols+1] = "Please enter...";
- ////The text displayed in the first line when the entered code was wrong.
- char Fail1stLine[lcdCols+1] = "Wrong code!";
- ////The text displayed in the second line when the entered code was wrong.
- char Fail2ndLine[lcdCols+1] = "Try again in 10s";
- ///End of adaptions///
- unsigned int keysLength = sizeof(keys)/sizeof(keys[0]);
- unsigned int rows = sizeof(rowPins)/sizeof(rowPins[0]);
- unsigned int columns = sizeof(columnPins)/sizeof(columnPins[0]);
- unsigned int codeLength = sizeof(password)/sizeof(password[0]) - 1;
- unsigned int outputPinsLength = sizeof(outputPins)/sizeof(outputPins[0]);
- InputHandler input(subDelay, invalid, keys, keysLength, rowPins, rows, columnPins, columns);
- CodeBuilder builder(password, codeLength, invalid, maxCodeLength);
- OutputHandler out(lcdCols, lcdRows, lcdI2CAddress, lcdSecret, openTime, waitTime, outputPins, outputPinsLength, outputPinsActiveLevel, Line1, Line2, Success1stLine, Success2ndLine, Fail1stLine, Fail2ndLine);
- void setup() {
- // put your setup code here, to run once:
- out.Setup();
- input.Setup();
- }
- char old_e = invalid;
- void loop() {
- // put your main code here, to run repeatedly:
- input.Update();
- char _e = input.GetEnteredKey();
- if (_e != old_e)
- {
- if (_e != invalid) //a char has been entered
- {
- if (_e == acceptKey) //the char was the acceptKey
- {
- bool success = builder.VerifyEnteredCode();
- out.CodeTrial(success);
- if (success)
- {
- input.BlockInput(openTime);
- }
- else
- {
- input.BlockInput(waitTime);
- }
- }
- else { //the char was any other
- builder.AddChar(_e);
- out.CodeCharEntered();
- }
- }
- old_e = _e;
- }
- out.Update();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement