Davide Gomba
Published © GPL3+

Smarten Your Home From The Entrance: MKR Keylock

The entrance is one of the main devices in your house, yet it uses pretty old tech. Now you can upgrade your door to the IoT century!

IntermediateProtip3 hours1,214
Smarten Your Home From The Entrance: MKR Keylock

Things used in this project

Hardware components

Arduino MKR WiFi 1010
Arduino MKR WiFi 1010
×1
4x4 Keypad
×1
Electronic door lock
×1
Buzzer
Buzzer
×1
SparkFun Snappable Protoboard
SparkFun Snappable Protoboard
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Wire Cable - By the Foot
OpenBuilds Wire Cable - By the Foot
×1

Software apps and online services

Arduino Web Editor
Arduino Web Editor
Home Assistant
Home Assistant
MQTT
MQTT

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Mastech MS8217 Autorange Digital Multimeter
Digilent Mastech MS8217 Autorange Digital Multimeter
Electrician Scissors
Screwdriver set

Story

Read more

Schematics

Circuit Diagram

This is the circuit diagram of the project. Follow it to connect the peripherals.

Code

Simple keypad

Arduino
This is the simple keypad sketch. Use it to debug your connections.
/* Simple Keypad using Arduino MKR WiFi1010
 * -----------------------------------------
 * This sketch provide a simple keypad lock using an electronic lock and a keypad.
 * Mapping:
 * 7 --> CONTACT TO OPENER (ACTIVE HIGH)
 * 9 --> CONTACT TO RINGBELL (ACTIVE HIGH)
 * -----------------------------------------
 * Materials:
 * Arduino MKR WiFi1010
 * 4x4 Keypad
 * Keyless or other electronic locks
 * Ringbell
 * -----------------------------------------
 * Created by Alberto Perro
 * Officine Innesto 2018
 */
 
#include <Keypad.h>

//keypad settings
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = { //keypad mapping
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {1,0,A6,A5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5,4,3,2}; //connect to the column pinouts of the keypad
Keypad pad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

//lock definitions
const int doorOpener = 7; //opener contact
const int doorRing = 9;   //ring contact
const int buzzer = 12;    //buzzer pin
char master[] = {'2', '6', '7', '8'}; //master key
//variables
unsigned long timer;
char temp[10];
int keyCount = 0;

void setup(){
  Serial.begin(9600);
  //while (!Serial);
  pinMode (buzzer, OUTPUT);
  pinMode (doorOpener, OUTPUT);
  pinMode (doorRing, OUTPUT);
  digitalWrite(doorOpener, HIGH);
  digitalWrite(doorRing, HIGH);
}

void loop(){
  if ((millis() - timer) > 10000) { // reset key buffer after 10s
    timer = millis();
    Serial.println("Reset keys");
    resetKeys();
  }
  char key = pad.getKey(); //read keys
  if (key){ //key selection
    timer = millis();
    Serial.println(key);
    if(key=='D'){               //key to ringbell
      Serial.println("RING");
      digitalWrite(doorRing, LOW);
      tone(buzzer,784,500);
      delay(500);
      tone(buzzer,659,500);
      digitalWrite(doorRing, HIGH);
      resetKeys();
    }else if(key=='C'){         //key to reset
      resetKeys();
    }else if(key=='#'){         //key to open
      checkKey()?openTheDoor():tone(buzzer,500,500);
      resetKeys();
    }else if(key!='A'&& key!='B'){ // buffer manager
      temp[keyCount]=key;
      keyCount++;
  }
}
}
// key check method
bool checkKey(){
  bool check = true;
  Serial.println("check Master key");
  for(int i =0;i<sizeof(master)/sizeof(char);i++){
    if(master[i]!=temp[i]) check=false;
  }
  return check;
}
// key reset method
void resetKeys(){
  keyCount=0;
  temp[4]={0};
}
// open the door routine
void openTheDoor() {
  digitalWrite(doorOpener, LOW);
  delay(100);
  digitalWrite(doorOpener, HIGH);
  tone(buzzer,784,300);
  delay(200);
  tone(buzzer,1047,300);
}

WiFi Keypad

Arduino
This is the full firmware, implementing MQTT over WiFi.
/* WiFi-enabled Keypad using Arduino MKR WiFi1010
 * -----------------------------------------
 * This sketch provide a simple keypad lock using an electronic lock and a keypad
 * It also has MQTT implementing opening and setting a guest code.
 * Mapping:
 * 7 --> CONTACT TO OPENER (ACTIVE HIGH)
 * 9 --> CONTACT TO RINGBELL (ACTIVE HIGH)
 * -----------------------------------------
 * Materials:
 * Arduino MKR WiFi1010
 * 4x4 Keypad
 * Keyless or other electronic locks
 * Ringbell
 * -----------------------------------------
 * Created by Alberto Perro
 * Officine Innesto 2018
 */
#include <Keypad.h>
#include <MQTTClient.h>
#include <WiFiNINA.h>
//keypad settings
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {1,0,A6,A5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5,4,3,2}; //connect to the column pinouts of the keypad
Keypad pad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// Network settings
char ssid[] = "YOUR SSID";     //  your network SSID (name)
char pass[] = "YOUR PASSWORD";  // your network password

// MQTT settings
char MQTTClient_id[] = "door_lock";
char MQTTClient_topic[] = "door_lock";
char MQTTBroker_ip[] = "YOUR BROKER IP";

// Client settings
WiFiClient net;
MQTTClient client;

//lock definitions
const int doorOpener = 7; // DOOR CONTACT
const int doorRing = 9;   // RINGBELL CONTACT
const int buzzer = 12;    // BUZZER PIN
unsigned long timer;
char master[] = {'0', '0', '0', '0'}; // MASTER KEY
char guest[10];
char guestLength = 0;
char temp[10];
int keyCount = 0;
bool toOpen = false;

void setup(){
  Serial.begin(9600);
  pinMode (buzzer, OUTPUT);
  pinMode (doorOpener, OUTPUT);
  pinMode (doorRing, OUTPUT);
  digitalWrite(doorOpener, HIGH);
  digitalWrite(doorRing, HIGH);
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
  Serial.println("You're connected to the network");
  client.begin(MQTTBroker_ip, net);
  client.onMessage(messageReceived);
  if(client.connect(MQTTClient_id)){
    client.subscribe("door_lock/" + String(MQTTClient_topic) + "/code");
    client.subscribe("door_lock/" + String(MQTTClient_topic) + "/open");
    Serial.println("\nMQTT connected!");
  }
}

void loop(){
  if (!client.connected()) { // check net and MQTT connection
    Serial.println("reconnection");
    if(client.connect(MQTTClient_id)){
      client.subscribe("door_lock/" + String(MQTTClient_topic) + "/code");
      client.subscribe("door_lock/" + String(MQTTClient_topic) + "/open");
      Serial.println("\nMQTT connected!");
    }
  }
  client.loop();
  if ((millis() - timer) > 10000) { //send alive message
    timer = millis();
    client.publish("door_lock/" + String(MQTTClient_topic) + "/alive/status", "OK");
    Serial.println("keep it alive");
    resetKeys();
  }
  char key = pad.getKey();
  if (key){           //key functions 
    timer = millis();
    Serial.println(key);
    if(key=='D'){ // play ringbell
      client.publish("door_lock/" + String(MQTTClient_topic) + "/ringbell/pressed", "YES");
      Serial.println("RING");
      digitalWrite(doorRing, LOW);
      tone(buzzer,784,500);
      delay(500);
      tone(buzzer,659,500);
      digitalWrite(doorRing, HIGH);
      resetKeys();
    }else if(key=='C'){ // delete code
      resetKeys();
    }else if(key=='#'){ // enter code
      checkKey()?openTheDoor():tone(buzzer,500,500);
      resetKeys();
    }else if(key!='A'&& key!='B'){
      temp[keyCount]=key;
      keyCount++;
  }
}
if(toOpen) openTheDoor();
}
//check keys method
bool checkKey(){
  bool check = true;
  Serial.println("check Master key");
  for(int i =0;i<sizeof(master)/sizeof(char);i++){
    if(master[i]!=temp[i]) check=false;
  }
  if(check){return true;}else{check=true;}
  Serial.println("check Guest key");
  for(int i =0;i<guestLength;i++){
    if(guest[i]!=temp[i]) check=false;
  }
  
  return check;
}
//reset key buffer method
void resetKeys(){
  keyCount=0;
  temp[4]={0};
}
//MQTT callback method
void messageReceived(String &topic, String &payload) {
  client.publish("received_Message", "OK");
  Serial.print("incoming: ");
  Serial.print(topic);
  Serial.print(" - ");
  Serial.print(payload);
  Serial.println();
  if (topic == "door_lock/" + String(MQTTClient_topic) + "/open") { // 
    if (payload == "ON") toOpen = true; 
  }
  if (topic == "door_lock/" + String(MQTTClient_topic) + "/code") { // GUEST CODE TOPIC
    //Serial.println(payload.length());
    payload.toCharArray(guest,11);
    guestLength=payload.length();
    Serial.print("Got Guest Code:");
    for(int i=0;i<guestLength;i++) Serial.print(guest[i]);
    Serial.println();
  }
}

//door open method
void openTheDoor() {
  digitalWrite(doorOpener, LOW);
  delay(100);
  digitalWrite(doorOpener, HIGH);
  client.publish("door_lock/" + String(MQTTClient_topic) + "/open", "YES");
  tone(buzzer,784,300);
  delay(200);
  tone(buzzer,1047,300);
}

    

Credits

Davide Gomba
11 projects • 89 followers
Davide Gomba is an Italian maker / storyteller. Loves creating experiences about IoT STEAM Domotics Agrotech and Transformational Festival.
Contact

Comments

Please log in or sign up to comment.