My entire sketch is quite long, but i will add it, this is my first project, if you find any flaws other than the subject , i will be happy to accept all the notes i can.
//including libraries.
#include <LiquidCrystal.h> //Lcd functions library
#include <Servo.h> //Servo Motor
#include <TM1637.h> //4 digit display functions library
#include <SPI.h> //Serial Peripheral interface protocol library. needed for rfid
#include <MFRC522.h> //rfid functions library.
#include <EEPROM.h>
//DEFINING PINS
//pins are declared as CONST since they need to stay constant throughout the code
const int rs = 38, en = 39, d4 = 36 ,d5 = 37, d6 = 41, d7 = 40;//Defining LCD PINS
const int DA=31, D0=30,D1=33,D2=32,D3=35;//Defining KEYPAD data PINS
const int servoEntrancePin=43, servoExitPin=34,buzzer=42, CLK=49,DIO=48;//Defining(By order): servo pin, buzzer pin, 4DD pins
const int IrEntrance=29,IrExit=28,IrExitHold=27;
const int SS_PIN=45,RST_PIN=44;
const int carCountAdress=5;
//Declaring variables that are later on used to count several things. I will not
//im declaring most here since they need to be global/they are used in the loop()
//and i do not want them to declare themselved on every run of the loop..
int keysPressedIndex = 0;//Index for keysPressed array
int passwordCorrectCounter=0;//this cnt is used later on to make sure all 5 chars are equal.
int cnt2=0;//used for switch case to count how many chars were already received
int carCount=0;//Keeps track of the amount of cars that are in the lot.
int rfidCnt=0;//Used to check if UID matches UID in AllowedUID array.
char charKey=0;//this is where we place the char received from the keypad
int key; //variable to store what key was pressed from 0-15,
char password[5] = {'8', '5', '2', '0', '#'};
char keysPressed[5] = "";
//this is for beauty purposes only, can be removed easily and wont affect the code*
//(this is the heart and smiley in our lcd)*-considering you remove the lines that refer
//to that...
byte smileyChar[] = {
B00000,
B00000,
B01010,
B00000,
B10001,
B01110,
B00000,
B00000
};
byte heartChar[] = {//Custom Char for lcd screen, in this case; a heart.
B00000,
B00000,
B01010,
B11111,
B11111,
B01110,
B00100,
B00000
};
//an object is an instance(מופע) of a class(מחלקה) so using LiquidCrystal
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);//Creating LCD object
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 object.
Servo servoEntrance;//creating Servo object for the entrance servo
Servo servoExit;//creating Servo object for the exit servo
TM1637 fourDigit(CLK, DIO);//creating a TM1637 4DD object
byte allowedUID[4][4]={{0xA3,0xF3,0x3E,0x94},{0xBA,0xFA,0x22,0x28},{2,2,2,2},{3,3,3,3}};//array of UID(rfid chips) that can open the gate
void setup()
{
Serial.begin(9600);//starting Serial communication for serial monitor
Serial3.begin(9600);//Starting Serial3 communication to communicate with bluetooth w UART protocol
SPI.begin();//Starting SPI communication protocol
pinMode(DA,INPUT);//setting all keypad pins to input since we want to get information from those pins(what key was pressed?) DA is interrupt pin D0-3 Are data pins.
pinMode(D0,INPUT);
pinMode(D1,INPUT);
pinMode(D2,INPUT);
pinMode(D3,INPUT);
pinMode(IrEntrance,INPUT);//setting all IR pins as input, since we want to get information from them(Is something infront of them?)
pinMode(IrExit,INPUT);
pinMode(IrExitHold, INPUT);
mfrc522.PCD_Init(); // Initiate MFRC522
lcd.begin(20,4);//intializes the lcd interface, giving the size of our LCD (20x4)
lcdSetup();//Self Created function that turns lcd to our preffered default screen "Home screen"
servoEntrance.attach(servoEntrancePin);//Attaching the servo object to the pin. A built in function from the Servo.h library
servoExit.attach(servoExitPin);
servoEntrance.write(10);//giving both servos setup degree, where the servos start when the
servoExit.write(105);
fourDigit.init();//intializing four digit
fourDigit.set(7);//setting 4DD brightness to max
pinMode(buzzer,OUTPUT);//setting buzzer as output, so we can tell it what to do.
lcd.createChar(2, smileyChar);//creating custom char for the LCD. The lcd can hold up to 8 custom chars.
lcd.createChar(1, heartChar);
carCount=EEPROM.read(carCountAdress);//Reading from eeprom memory, getting how much cars were in the parking before power down
digitalWrite(buzzer, HIGH); //running a quick beep to hear we finished the setup.
delay(200);
digitalWrite(buzzer, LOW);
}
void loop()
{
Serial3.begin(9600);//starting Bluetooth serial each time, because we shut it off once the parking lot is full.
EEPROM.write(carCountAdress, carCount);//write to eeprom in every loop how much cars are in the parking, so we can keep track incase the power goes down
fourDigit.display(0,((12-carCount)/10));//we can write to each 7 segment display a digit, so we split our number of avaliable spots and unavaliable and display in each segment
fourDigit.display(1,((12-carCount)%10));
fourDigit.display(2,carCount/10);
fourDigit.display(3,carCount%10);
if(digitalRead(IrExit)==LOW){//when the exit ir detects a car, it opens the leave gate.
leaveGate();
}
if(carCount==-1){
carCount=0;
}
if(carCount==12)//when parking lot is full. first do this.
{
Serial3.end();//stop bluetooth communication to prevent information coming in while system in unavailable
//I use this few functions to edit and decorate the LCD i will explain them once here.
lcd.setCursor(0,0);//setting the cursor(where we are typing at the moment) to the 0,0 meaning the first collumn in the first row.
lcd.print("|------------------|");//<<--printing this on the LCD, this will appear on the entire first row
lcd.setCursor(0,1);//setting the cursor(where we are typing at the moment) to the 0,1 meaning the first collumn in the second row.
lcd.print("| SORRY |");//<<--printing this on the LCD, this will appear on the entire second row. etc etc
lcd.setCursor(0,2);
lcd.print("| PARKING IS FULL |");
lcd.setCursor(0, 3);
lcd.print("|------------------|");
while(carCount==12){// and as long as its full do nothing other than wait for the ir to sense someone leaving.
if(digitalRead(IrExit)==LOW){
leaveGate();
}
}
}
bluetoothGate();//A function to check if someone has opened the gate using bluetooth
rfidGate();//A function to check if someone has opened the gate using RFID
while(digitalRead(DA)==1){ //While recieving characters from keypad.
key =digitalRead(D3)*8 + digitalRead(D2)*4 +digitalRead(D1)*2 + digitalRead(D0);//We get from the keypad data send in parallel as a binary number, we convert that to decimal and give it to our variable
returnKey(key);//We give the decimal number of the key pressed from 0-15 indicating location of key pressed, this function converts key pressed to actual value of key pressed and puts in the variable charKey.
if(charKey!='D'){//if the key pressed isnt the D button
keysPressed[keysPressedIndex]=charKey;//Placing key pressed into an array
keysPressedIndex++;//raising array index
}
else{//if it is D
keysPressed[keysPressedIndex]="";//delete the key pressed before
keysPressedIndex--;//deduct one from the arrayIndex
}
switch(cnt2){//Switch case just to print on LCD the key pressed and * beforehand
case 0:
if(charKey != 'D'){
lcd.clear();
lcd.setCursor(9, 0);
lcd.print(keysPressed[keysPressedIndex-1]);
cnt2++;
Beep();
break;
}
else break;
case 1:
if(charKey!='D'){
lcd.setCursor(8,0);
lcd.print("*");
lcd.print(keysPressed[keysPressedIndex-1]);
cnt2++;
Beep();
break;
}
else{
lcd.clear();
lcdSetup();
cnt2--;
break;
}
case 2:
if(charKey!='D'){
lcd.setCursor(8, 0);
lcd.print("**");
lcd.print(keysPressed[keysPressedIndex-1]);
cnt2++;
Beep();
break;
}
else
{
lcd.clear();
lcd.setCursor(9,0);
cnt2--;
lcd.print(keysPressed[keysPressedIndex-1]);
break;
}
case 3:
if(charKey!='D')
{
lcd.setCursor(8, 0);
lcd.print("***");
lcd.print(keysPressed[keysPressedIndex-1]);
cnt2++;
Beep();
break;
}
else{
lcd.clear();
lcd.setCursor(9,0);
lcd.print("*");
cnt2--;
lcd.print(keysPressed[keysPressedIndex-1]);
break;
}
case 4:
if(charKey!='D')
{
cnt2=0;
}
else
{
lcd.clear();
lcd.setCursor(9, 0);
lcd.print("**");
cnt2--;
lcd.print(keysPressed[keysPressedIndex-1]);
}
break;
}
while(digitalRead(DA)==1);//Making sure we wont get double input from one press, forcing the loop to stay there as long as a key is pressed
if (keysPressedIndex == 5)//when count reaches 5, meaning array is full check if array 'password' is equal to the 5 keys the user just entered.
{
for (int i = 0; i < 5; i++)
{
if (password[i] == keysPressed[i])//if keys are the same add one to pasSwordCorrectCounter, if pasSwordCorrectCounter equals to 5, it means all keys were the same
{
passwordCorrectCounter++;
}
}
//
if(passwordCorrectCounter==5){
gateOpenSequence();
passwordCorrectCounter=0;
}
else{
wrongPassword();
passwordCorrectCounter=0;
}
}
}
}
void returnKey(int key)//gets what key location was pressed and returns actual key pressed
{
char arrkey[16]={ '1','2','3','A','4','5','6','B','7','8','9','C','*','0','#','D' };
charKey=arrkey[key];
}
void lcdSetup(){
lcd.setCursor(0,0);
lcd.write(2);
lcd.setCursor(1, 0);
lcd.write(1);
lcd.setCursor(18,0);
lcd.write(1);
lcd.setCursor(19,0);
lcd.write(2);
lcd.setCursor(2,0);
lcd.print("----Welcome-----");
lcd.setCursor(0,1);
lcd.print("| Enter password |");
lcd.setCursor(0,2);
lcd.print("|and then press '#'|");
lcd.setCursor(0, 3);
lcd.print("|------------------|");
}
void leaveGate()//opens gate and changes the amount of cars in the lot
{
lcd.print("|------------------|");
lcd.setCursor(0,1);
lcd.print("| GoodBye! |");
lcd.setCursor(0,2);
lcd.print("| |");
lcd.setCursor(0, 3);
lcd.print("|------------------|");
keysPressedIndex = 0;
cnt2=0;
servoOpen("Exit");
delay(500);
carCount--;
while(digitalRead(IrExitHold)==LOW);
servoDown("Exit");
lcdSetup();
}
void gateOpenSequence()
{
carCount++;
int start = 0;
int desired = 105;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("|------------------|");
lcd.setCursor(0,1);
lcd.print("| Correct Password |");
lcd.setCursor(0, 2);
lcd.print("| Welcome |");
lcd.setCursor(0, 3);
lcd.print("|------------------|");
keysPressedIndex = 0;
cnt2=0;
digitalWrite(buzzer,HIGH);
servoOpen("Entrance");
delay(500);
servoDown("Entrance");
lcdSetup();
delay(10);
}
void wrongPassword()
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print("|------------------|");
lcd.setCursor(0,1);
lcd.print("| Wrong Password |");
lcd.setCursor(0, 2);
lcd.print("| Try Again |");
lcd.setCursor(0, 3);
lcd.print("|------------------|");
keysPressedIndex = 0;
for(int jj=0;jj<3;jj++)
{
Beep();
}
delay(200);
lcdSetup();
}
void Beep(){
digitalWrite(buzzer,HIGH);
delay(200);
digitalWrite(buzzer,LOW);
delay(200);
}
void servoOpen(char gate[10])//Function that opens servo gate depending on the string it gets. if its gets "Exit" it opens the exit gate and if it gets "Entrance" the other opens.
{
if(gate=="Exit")
{
int start=105;
servoExit.write(start);
while(start>10)
{
servoExit.write(--start);
delay(10);
}
}
if(gate=="Entrance")
{
Serial.print("servoOpen entrance: ");
int start=5;
servoEntrance.write(start);
while(start<105)
{
servoEntrance.write(++start);
delay(10);
}
}
}
void servoDown(char gate[10])
{
if(gate=="Exit"){
int start=10;
servoExit.write(start);
while(start<105){
servoExit.write(start);
if(digitalRead(IrExitHold)==LOW){
servoExit.write(10);
start=10;
}
servoExit.write(++start);
delay(10);
}
}
if(gate=="Entrance"){
int start=105;
servoEntrance.write(start);
while(start>5){
servoEntrance.write(start);
if(digitalRead(IrEntrance)==LOW){
servoEntrance.write(105);
start=105;
}
servoEntrance.write(--start);
delay(10);
}
}
digitalWrite(buzzer,LOW);
}
void bluetoothGate()
{
if(Serial3.available() > 0) //Wait for user input
{
int DataReceived = Serial3.read(); //Read user input and hold it in a variable // Bluetooth data variable
if(char(DataReceived)=='1')//if the input is '1'
{
Serial.print(DataReceived
);
gateOpenSequence();
Serial3.end();
}
Serial.print("AfterBluetooth");
}
}
void rfidGate()
{
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
byte buffer[4];
int i,j;
for (i = 0; i < 4; i++) {
buffer[i] = mfrc522.uid.uidByte[i];
}
mfrc522.PICC_HaltA();
Serial.print("UID: ");
for (byte i = 0; i < 4; i++) {
Serial.print(buffer[i],HEX);
Serial.print(" ");
}
Serial.println("Hello");
for(i=0;i<5;i++){
for(j=0;j<4;j++){
// Serial.print("Allowed: ");
// Serial.println((int)allowedUID[i][j]);
// Serial.print("Buffer: ");
// Serial.println((int)buffer[j]);
if(buffer[j]==allowedUID[i][j]){
rfidCnt++;
}
}
}
if(rfidCnt==4){
gateOpenSequence();
rfidCnt=0;
}
else{
wrongPassword();
rfidCnt=0;
}
}
}