Door lock with pass code adjustable over internet!

Hi, could any of the masters here help me with the following:

I want to make a door lock, opened by a physical keypad(from outside) and a button (from the inside). The tricky part is that I want to be able to change the pass code over internet.

What I bought so far:

  • Arduino Nano;
  • ENC28J60 Ethernet Shield V1.0 for Arduino Nano 3.0 RJ45 Webserver Module;
  • LCD display
  • numeric keypad with matrix output
  • relay
  • door lock

What I did so far:

  • Found online and adapted the following sketch and the system works :
#include <Keypad.h>
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>

#define Relay 11                //Controls the Relay
#define O_Button 10             //Push Button

#define I2C_ADDR 0x27           //I2C adress, you should use the code to scan the adress first (0x27) here
#define BACKLIGHT_PIN 3         // Declaring LCD Pins
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7

const byte numRows= 4;          //number of rows on the keypad
const byte numCols= 4;          //number of columns on the keypad

char keymap[numRows][numCols]= 
{
{'1', '2', '3', 'A'}, 
{'4', '5', '6', 'B'}, 
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

char keypressed;                 //Where the keys are stored it changes very often
char code[]= {'2','2','0','1','1'};  //The default code, you can change it or make it a 'n' digits one

char code_buff1[sizeof(code)];  //Where the new key is stored
char code_buff2[sizeof(code)];  //Where the new key is stored again so it's compared to the previous one

short a=0,i=0,s=0,j=0;          //Variables used later

byte rowPins[numRows] = {9,8,7,6}; //Rows 0 to 3 //if you modify your pins you should modify this too
byte colPins[numCols]= {5,4,3,2}; //Columns 0 to 3

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

void setup()
         {
          lcd.begin (16,2);
          lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
          lcd.setBacklight(HIGH); //Lighting backlight
          lcd.home ();
          lcd.print("Standby");      //What's written on the LCD you can change
          
          pinMode(Relay,OUTPUT);
          pinMode(O_Button,INPUT);
                      
          for(i=0 ; i<sizeof(code);i++){        //When you upload the code the first time keep it commented
            EEPROM.get(i, code[i]);             //Upload the code and change it to store it in the EEPROM
             }                                  //Then uncomment this for loop and reupload the code (It's done only once)

         }


void loop()
{

  keypressed = myKeypad.getKey();               //Constantly waiting for a key to be pressed
    if(keypressed == '*'){                      // * to open the lock
            lcd.clear();
            lcd.setCursor(0,0);
            lcd.print("Enter code");            //Message to show
            GetCode();                          //Getting code function
                  if(a==sizeof(code))           //The GetCode function assign a value to a (it's correct when it has the size of the code array)
                  OpenDoor();                   //Open lock function if code is correct
                  else{
                  lcd.clear();               
                  lcd.print("Wrong");          //Message to print when the code is wrong
                  }
            delay(2000);
            lcd.clear();
            lcd.print("Standby");             //Return to standby mode it's the message do display when waiting
        }

     if(keypressed == '7'){                  //To change the code it calls the changecode function
      ChangeCode();
      lcd.clear();
      lcd.print("Standby");                 //When done it returns to standby mode
     }

     if(digitalRead(O_Button)==HIGH){      //Opening by the push button
       digitalWrite(Relay,LOW);
       delay(5000);                        //Opens for 3s you can change
       digitalWrite(Relay,HIGH);
     
     }
         
}

void GetCode(){                  //Getting code sequence
       i=0;                      //All variables set to 0
       a=0;
       j=0; 
                                     
     while(keypressed != '#'){                                     //The user press A to confirm the code otherwise he can keep typing
           keypressed = myKeypad.getKey();                         
             if(keypressed != NO_KEY && keypressed != '#' ){       //If the char typed isn't A and neither "nothing"
              lcd.setCursor(j,1);                                  //This to write "*" on the LCD whenever a key is pressed it's position is controlled by j
              lcd.print("*");
              j++;
            if(keypressed == code[i]&& i<sizeof(code)){            //if the char typed is correct a and i increments to verify the next caracter
                 a++;                                              //Now I think maybe I should have use only a or i ... too lazy to test it -_-'
                 i++;
                 }
            else
                a--;                                               //if the character typed is wrong a decrements and cannot equal the size of code []
            }
            }
    keypressed = NO_KEY;

}

void ChangeCode(){                      //Change code sequence
      lcd.clear();
      lcd.print("Changing code");
      delay(1000);
      lcd.clear();
      lcd.print("Enter old code");
      GetCode();                      //verify the old code first so you can change it
      
            if(a==sizeof(code)){      //again verifying the a value
            lcd.clear();
            lcd.print("Changing code");
            GetNewCode1();            //Get the new code
            GetNewCode2();            //Get the new code again to confirm it
            s=0;
              for(i=0 ; i<sizeof(code) ; i++){     //Compare codes in array 1 and array 2 from two previous functions
              if(code_buff1[i]==code_buff2[i])
              s++;                                //again this how we verifiy, increment s whenever codes are matching
              }
                  if(s==sizeof(code)){            //Correct is always the size of the array
                  
                   for(i=0 ; i<sizeof(code) ; i++){
                  code[i]=code_buff2[i];         //the code array now receives the new code
                  EEPROM.put(i, code[i]);        //And stores it in the EEPROM
                  
                  }
                  lcd.clear();
                  lcd.print("Code Changed");
                  delay(2000);
                  }
                  else{                         //In case the new codes aren't matching
                  lcd.clear();
                  lcd.print("Codes are not");
                  lcd.setCursor(0,1);
                  lcd.print("matching !!");
                  delay(2000);
                  }
            
          }
          
          else{                     //In case the old code is wrong you can't change it
          lcd.clear();
          lcd.print("Wrong");
          delay(2000);
          }
}

void GetNewCode1(){                      
  i=0;
  j=0;
  lcd.clear();
  lcd.print("Enter new code");   //tell the user to enter the new code and press A
  lcd.setCursor(0,1);
  lcd.print("and press #");
  delay(2000);
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print("and press #");     //Press A keep showing while the top row print ***
             
         while(keypressed != '#'){            //A to confirm and quits the loop
             keypressed = myKeypad.getKey();
               if(keypressed != NO_KEY && keypressed != '#' ){
                lcd.setCursor(j,0);
                lcd.print("*");               //On the new code you can show * as I did or change it to keypressed to show the keys
                code_buff1[i]=keypressed;     //Store caracters in the array
                i++;
                j++;                    
                }
                }
keypressed = NO_KEY;
}

void GetNewCode2(){                         //This is exactly like the GetNewCode1 function but this time the code is stored in another array
  i=0;
  j=0;
  
  lcd.clear();
  lcd.print("Confirm code");
  lcd.setCursor(0,1);
  lcd.print("and press #");
  delay(3000);
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print("and press #");

         while(keypressed != '#'){
             keypressed = myKeypad.getKey();
               if(keypressed != NO_KEY && keypressed != '#' ){
                lcd.setCursor(j,0);
                lcd.print("*");
                code_buff2[i]=keypressed;
                i++;
                j++;                    
                }
                }
keypressed = NO_KEY;
}

void OpenDoor(){             //Lock opening function open for 3s
  lcd.clear();
  lcd.print("Welcome");       //With a message printed
  digitalWrite(Relay,LOW);
  delay(5000);
  digitalWrite(Relay,HIGH);
}
  • read all the relevant topics here but I’m stuck

What I still need to do (with your help):

  • connect the Arduino Nano to Cayenne;
  • find a way to change the pass code from Cayenne to Arduino and the code to remain valid until further change.

Respect and gratitude to all who decide to help a soul in need!

This shield is not supported. You can find all the supported connection here https://github.com/myDevicesIoT/Cayenne-MQTT-Arduino/tree/master/examples/Connections

Here is a similar project Smart Lock and Doorbell using cayenne , though you will need to add the function of changing the pass code.

Hi, Shramik. Thanks for the directions. I’ll try to get one f the supported Ethernet shields, although in this topic it is mentioned that mine should work as well :

Does it support ENC28J60 module?

I’ve read your project a few times already, but I have no idea how to replace the pass code for opening via Cayenne. I imagine it should be a kind of field in the Cayenne window. And when I type the numbers in that field, they are “magically” sent to Arduino and stored in the EEPROM, replacing the existing pass code… :grimacing:
Any advice?

here you go CAYENNE Smart Home

1 Like

This is awesome!

For the door lock project you use :

Wemos D1
Nodemcu ESP8266

Do I need to buy exactly those components, or I can use what I already bought?

Arduino Nano V3
Ethernet shield Nano W5100 (compatible with Cayenne)

If ‘‘Yes’’, is the sketch the only thing that I need to upload to the Arduino Nano, or there is something else?

How can add the option to use physical keypad at the door, and a physical button to open the door from inside?

-------- Оригинално писмо --------
От: Shramik salgaonkar via myDevices Cayenne Community mydevices@discoursemail.com
Относно: [myDevices Cayenne Community] [Community Help With My Project] Door lock with pass code adjustable over internet!
До: dimitkovec@abv.bg
Изпратено на: 28.12.2020 15:30

| shramik_salgaonkar Community Manager
December 28 |

  • | - |

here you go CAYENNE Smart Home

this is depends on your application. Do you need it to be wired (Ethernet) or over wireless(wifi). here are types of connection supported https://github.com/myDevicesIoT/Cayenne-MQTT-Arduino/tree/master/examples/Connections. if you are buying a new just go for the same device which i have used.

you will need to combine both the project code togethere.

1 Like

I won’t need the connection over wifi. So I will go with what I already bought. Arduino Nano, and Ethernet shield W5100.

OK, combining both codes it is then! I will read and learn and I believe I will be able to do it. However, if after a month I am still struggling I will ask for an advice again.

Thank you sincerely for the help and guidance!

you brought a new W5100 shield? or referring to ENC28J60 Ethernet Shield V1.0 ?

Bought a new W5100 (still waiting to arrive though) :slight_smile:
After all you pointed that ENC28J60 is not supported and I don’t have the habit to argue with specialists in an area where I am a noob :slight_smile:

I try to use W5100 with arduino UNO, but usefulness.
Remain almost none free space for program. I suggest that use ESP8266

Thank you for the advice, Simon. I already bought all other available Ethernet adapters, so why not by another one. :slight_smile:
However, can you recommend me which exactly to use together with Arduino Nano, because there are so many modules based on ESP8266? I prefer not to be wifi, but I only find those:

https://www.aliexpress.com/item/1005001842894649.html?spm=a2g0o.productlist.0.0.7cec52833llf5w&algo_pvid=null&algo_expid=null&btsid=2100bdca16096734791474202e140a&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_

If I get one, do I need other components in order to use it with Arduino Nano?

that’s the best dev board right now.

I’m not good in programming, but I think it there is enough free pin then it is no problem to use it as direct replacement of arduino nano

you can all about the device here NodeMCU ESP8266 Specifications, Overview and Setting Up

Ok, that’s a new perspective for me! So you suggest that I leave aside the Arduino and the other electronics I’ve bought so far. Which is not big of a deal, but what about the sketches? Are they identical for Arduino and LoLin NodeMCU?

shramik, thank you for the link! I feel that I will try and go for this option, but the headache just starts: I need to buy a special soldering machine, because I don’t find online an expansion board like I bought for the Nano

… probably on youtube I should find explanation how to solder those fine elements and cables, without frying them. :thinking:
I will order tomorrow the LoLin NodeMCU (unless you have anther advice).
I’m afraid soon my wife will start throwing modules and chips at me, because they keep arriving at home by the bucket! :sweat_smile:

hold on, this is getting a bit confusing. Which device do you have with you right now (device and shield) and what is the purpose of the expansion board.

My confusion is not small either. Because I want to get something in my hands , but I don’t know what exactly I need.
So far I have physically in my home:
-Arduino Nano,
-the expansion shield ( so that I can screw the cables and not solder them)
-the ENC28J60 ethernet module

Since ENC28J60 didn’t work with Cayenne, I ordered W5100, and I’m waiting to receive it.
Then simon.skocir mentioned that W5100 is not a good solution, I’m considering to order now the LoLin NodeMCU … or should I? :dizzy_face:

the code for lock uses 83% space, do you need to attach any other sensor or extra code?
this is the basic code for the lock:-

This example shows how to connect to Cayenne using an Ethernet W5100 shield and send/receive sample data.

The CayenneMQTT Library is required to run this sketch. If you have not already done so you can install it from the Arduino IDE Library Manager.

Steps:
1. Set the Cayenne authentication info to match the authentication info from the Dashboard.
2. Compile and upload the sketch.
3. A temporary widget will be automatically generated in the Cayenne Dashboard. To make the widget permanent click the plus sign on the widget.
*/

//#define CAYENNE_DEBUG       // Uncomment to show debug messages
#define CAYENNE_PRINT Serial  // Comment this out to disable prints and save space
#include <CayenneMQTTEthernet.h>

// Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
char username[] = "MQTT_USERNAME";
char password[] = "MQTT_PASSWORD";
char clientID[] = "CLIENT_ID";

unsigned long lastMillis = 0;
int x;
const int codelength = 6;

const int code[codelength] = {1, 0, 1, 0, 0, 1};

int codecounter = 0;

void setup() {
	Serial.begin(9600);
	Cayenne.begin(username, password, clientID);
}

void loop() {
	Cayenne.loop();
          if (codecounter == (codelength) ) {
    Serial.println("Welcome  home");
    digitalWrite(LED_BUILTIN, LOW);
    delay(2000);
    digitalWrite(LED_BUILTIN, HIGH);
    codecounter = 0;
  }
}
CAYENNE_IN(V1)
{
  int currentValue = getValue.asInt();
  if (currentValue == 2)
  {
    if (code[codecounter] == 1)
    {
      codecounter++;
      x = 0;
      Serial.println(codecounter);
      Serial.println("true");
    }
    else
    {
      codecounter = 0;
      Serial.println(codecounter);
      Serial.println("false");

    }
  }
}
CAYENNE_IN(V2)
{
  int currentValue = getValue.asInt();
  if (currentValue == 3)
  {
    if (code[codecounter] == 0)
    {
      codecounter++;
      x = 0;
      Serial.println(codecounter);
      Serial.println("true");
    }
    else
    {
      codecounter = 0;
      x = 1;
      Serial.println(codecounter);
      Serial.println("false");

    }
  }
} CAYENNE_IN(V3)
{
  int currentValue = getValue.asInt();
  if (currentValue == 1)
  {
    if (code[codecounter] == 1)
    {
      codecounter++;
      x = 0;
      Serial.println(codecounter);
      Serial.println("true");
    }
    else
    {
      codecounter = 0;
      x = 1;
      Serial.println(codecounter);
      Serial.println("false");

    }
  }
}
CAYENNE_IN(V4)
{
  int currentValue = getValue.asInt();
  if (currentValue == 4)
  {
    if (code[codecounter] == 0)
    {
      codecounter++;
      x = 0;
      Serial.println(codecounter);
      Serial.println("true");
    }
    else
    {
      codecounter = 0;
      Serial.println(codecounter);
      x = 1;
      Serial.println("false");

    }
  }
}
CAYENNE_IN(V5)
{
  int currentValue = getValue.asInt();
  if (currentValue == 5)
  {
    if (code[codecounter] == 0)
    {
      codecounter++;
      x = 0;
      Serial.println(codecounter);
      Serial.println("true");
    }
    else
    {
      codecounter = 0;
      x = 1;
      Serial.println(codecounter);
      Serial.println("false");

    }
  }
}
CAYENNE_IN(V6)
{
  int currentValue = getValue.asInt();
  if (currentValue == 3)
  {
    if (code[codecounter] == 1)
    {
      codecounter++;
      x = 0;
      Serial.println(codecounter);
      Serial.println("true");
    }
    else
    {
      codecounter = 0;
      x = 1;
      Serial.println(codecounter);
      Serial.println("false");

    }
  }
}

I only need it for the door lock. If I don’t need to add any other code for the option to change the lock pass code via Cayenne, then I’m OK.
Just I’m not sure if is it possible to program those actions with only one sketch?

Actually, If there is a way to edit directly the Nano sketch over internet at any time, then my problem would be solved. Is there a way to do so?