Author: Olteanu Robert
Master: AAC2
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.
For the hardware parts I used:
I attached below a diagram generated using circuito.io, but I used a version that involved less wires.
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:
#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();
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
Down below I created a small logical workflow for the code described in the previous chapter to be easily understood.
[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