Table of Contents

Home Security System

Author: Olteanu Robert

Master: AAC2

Project Description

The main goal for this project was to develop a security system based on IoT devices, mainly based on ESP32 development board and an RFID module and a RFID card and also a Tag which have a unique identifier to which I added some programming logic using a security keycode that user can type in using a 3×4 keypad, and for a good user experience I decided to add a small LCD 16×2 so the user can actually see if the keycode was wrong, or the card/tag he/she scanned is invalid.

Another good thing about the ESP32 is the fact that it has a built in WiFi module that allowed me to build a small dashboard in Adafruit.io where there are displayed a few information like, the current keycode, a log containing a small history and some status widgets.

Hardware Description

For the hardware parts I used:

I attached below a diagram generated using circuito.io, but I used a version that involved less wires.

Software Description

In the table below I described all the libraries used to develop the project.

Library Description
SPI.h Serial Peripheral Interface is a synchronous serial data protocol used for communicating with one ore more devices quickly
MFRC522.h Standard library to interact with the MFRC522 module to read/write different types of RFID cards
Keypad.h Standard library for using matrix style keypads with Arduino
LiquidCrystal_I2C.h Offers a few functions to interact easily with the LCD display for displaying characters or erasing them
Wire.h Allows you to communicate with I2C/TWI devices
Adafruit_MQTT.h Arduino library for MQTT support, including accessing the Adafruit.io
Adafruit_MQTT_Client.h Part of the Adafruit_MQTT library suite

Next thing the software is split in two main parts:

  1. Initial setup - this is where all the components / modules are getting initialized
    • WiFi - The ESP32 tries to connect to the configured network until succeed and it gets the IP address
    • MQTT - The Adafruit.io supports data transfer using MQTT, and on this initial setup there is needed to subscribe to all topics needed while the publishers doesn't need to.
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
 
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish hs_log = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/HS_Log");
Adafruit_MQTT_Publish hs_door = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/HS_DoorStatus");
Adafruit_MQTT_Subscribe hs_code = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/HS_DoorCode");
...
mqtt.subscribe(&hs_code);
#include <Keypad.h>
#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
 
// Keypad
#define ROW_NUM     4 
#define COLUMN_NUM  3
char keys[ROW_NUM][COLUMN_NUM] = {
  {'#', '0', '*'},
  {'9', '8', '7'},
  {'6', '5', '4'},
  {'3', '2', '1'}
};
 
byte pin_rows[ROW_NUM] = {0, 2, 15, 13}; 
byte pin_column[COLUMN_NUM] = {17, 16, 4};
Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );
 
// MFRC522
#define SS_PIN  5  // ESP32 pin GIOP5 
#define RST_PIN 27 // ESP32 pin GIOP27 
MFRC522 rfid(SS_PIN, RST_PIN);
 
// LCD
int lcdColumns = 16;
int lcdRows = 2;
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows); 
 
...
 
SPI.begin(); // init SPI bus
rfid.PCD_Init(); // init MFRC522
 
lcd.init();
lcd.backlight();
  1. Loop - this is looping until the ESP32 is stopped by user.
    • Connect to MQTT - this is done on each iteration to ensure a good connectivity
    • Read code subscription - first time after initial setup the user must insert his/her keycode of 4 characters inside Adafruit.io dashboard
MQTT_connect();
Adafruit_MQTT_Subscribe *subscription;
 
// Await code to be set from dashboard
while(code.equals("####")){
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Awaiting code...");
    while((subscription = mqtt.readSubscription(5000))) {
        if(subscription == &hs_code) {
        Serial.print(F("Got: "));
        Serial.println((char*)hs_code.lastread);
        code = (char*)hs_code.lastread;
        }
    }
}
if(rfid.PICC_IsNewCardPresent()) {
Serial.println("Card present");
if(rfid.PICC_ReadCardSerial()) {
    Serial.println("Read Serial");
    for (int i=0; i<rfid.uid.size; i++) {
    if(rfid.uid.uidByte[i] != availableCard[i]) {
        char msg[] = "Invalid card scanned";
        hs_log.publish(msg); // publish message 
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Invalid card");
        delay(3000); // wait to be able to see the message from lcd
bool scannedCard() {
  int idx = 0;
 
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Insert code:");
  lcd.setCursor(0,1);
 
  do {
    do{
      keyp = keypad.getKey();
    }while(!keyp);
    kcode[idx] = keyp;
    idx++;
    lcd.print("*");
  }while(idx < 4);
 
  for(int i=0; i<4;i++){
    if(kcode[i] != code.charAt(i)) { // code is the variable containing the current keycode
      return false;
    }
  }
  return true;
}
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Door opened");
char msg[] = "Door opened";
hs_log.publish(msg); // publish message to logs
delay(7000); // open door / disable alarm etc.
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Door closed");
char msg2[] = "Door closed";
hs_log.publish(msg2); // publish message to logs
delay(3000); // wait to be able to read the lcd message

Software logical workflow

Down below I created a small logical workflow for the code described in the previous chapter to be easily understood.

References

[1] - http://esp32.net/
[2] - https://lastminuteengineers.com/how-rfid-works-rc522-arduino-tutorial/
[3] - https://esp32io.com/tutorials/esp32-rfid-nfc
[4] - https://randomnerdtutorials.com/esp32-esp8266-i2c-lcd-arduino-ide/
[5] - https://esp32io.com/tutorials/esp32-keypad
[6] - https://io.adafruit.com/api/docs/mqtt.html#adafruit-io-mqtt-api
[7] - https://raw.githubusercontent.com/AchimPieters/esp32-homekit-camera/master/Images/ESP32-38%20PIN-DEVBOARD.png