Final Project Overall Summary¶
Guard X is a smart and secure lock system. It works by using an RFID module to detect authorized tags. When a valid tag is scanned, it unlocks the door using a solenoid lock and turns on a Neopixel RGB light to show that access is granted. Guard X is named after the idea of a “guard” that protects your space, and it runs on the Xiao ESP32-C3 microcontroller. It also connects to Wi-Fi, so users can control the lock remotely through the Blynk app—even if they lose their RFID tag.
Final Summary Slide¶
Final Project Video¶
BOM¶
Components | Quantity | Unit Price () | Total Price ( $) |
---|---|---|---|
Rubber Wood | 1 | $54 | $54 |
Acrylic sheet | 2 | ||
Seed XIAO ESP32 C3 | 1 | $13 | $13 |
RFID Card and Reader | 1 | $6 | $6 |
Solenoid | 1 | $6 | $6 |
Relay Module (single channel) | 1 | $2.5 | $2.5 |
Buck Converter | 1 | $1.6 | $1.6 |
Neopixels | 1 strip | $17 | $17 |
Diode (1N4007) | 1 | $5 | $5 |
Resistor (330 ohm)(1kohm) | (4)(1) | $0.05 | $0.25 |
lED | 3 | $0.0035 | $0.0175 |
SWITCH TACTILE SPST-NO | 1 | $1 | $1 |
Header Pins | APR | $0.1 | |
12V USB adapter | 1 | $2.23 | $2.23 |
3D print PLA | 1 | $2.1 | $2.1 |
Vinyl | 1 | $2.1 | $2.1 |
Screws | APR |
Design and Fabrication¶
I want to design the cabinet that is of 800mm400mm400 dimension. Considering all those space for the electronics I design my cabinet in fusion 360.
Here is the final version of my cabinet
Electronics design and Production¶
For my final Project I am using the XIAO ESP32 C3 as the micro controlller
for my input devices I have: 3.3V RFID reader and cards
for my output devices I have 12V Solenoids with 0.2mA and 5V 15 Neo-Pixles
I will use a buck convertor for 12 volts to 5 volts drop as regulator could not handle 7 volts drop. Given Below is how I have planned to give power supply for the solenoid, neopixel and RFID.
Power Management
Given below is circuit connection for my final board
System Design
For my final board design, I used KiCad to develop the PCB. This version integrates an XIAO-ESP32-C3 as the microcontroller unit (MCU), along with various breakout pins. Below is the final PCB schematic from KiCad:
Here’s the final PCB layout in KiCad and finalboard:
Programming¶
Here is the flow chart of how my system is going to work.
In the input,output weeks and the network and communication week, I programmed the input and output devices that I am going to use for my final project.
Testing RFID with Neopixels and solenoid
Before designing my pcb, I tested my code on breadboard using the ESP32C3 before redesigning my final Board.You can also check the links to Input and OutPut Week and Networking week for all indivividual coding I did.
I also tested the solenoid+rfid+neopixels
To ensure uninterrupted access for authorized users—even in the absence of an RFID card—the solenoid lock was successfully integrated with and controlled remotely through the Blynk IoT platform. Given below is the video how I implemented the blynk app.
I tested the programming with the board that I fabricated and the code works.
#include <SPI.h>
#include <MFRC522.h>
#include <Adafruit_NeoPixel.h>
#define BLYNK_PRINT Serial
// Blynk credentials
#define BLYNK_TEMPLATE_ID "TMPL390VtiLXt"
#define BLYNK_TEMPLATE_NAME "Relay IOT"
#define BLYNK_AUTH_TOKEN "AXrEK2JeuEziwFHw4ZFahgrJJkdrlXSE"
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
// WiFi credentials
char ssid[] = "Fablab";
char pass[] = "#JSW@2o25";
#define PIN D2 // Pin where NeoPixel is connected
#define NUMPIXELS 30 // Change this to match your strip length
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
constexpr uint8_t RST_PIN = D0;
constexpr uint8_t SS_PIN = D7;
const int relayPin = D1;
MFRC522 rfid(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
byte nuidPICC[4];
// Authorized card UIDs
byte authorizedUID1[4] = {0xCC, 0x82, 0x36, 0x4A};
byte authorizedUID2[4] = {0xFC, 0x4D, 0x11, 0x4A};
bool flag = true;
bool blynkTriggered = false;
//---------------------------- neo pixel variables
unsigned long lastActionTime = 0;
unsigned long rainbowInterval = 5000; // 5 seconds
bool overrideColor = false;
//-------------------------------------------------
int value;
BLYNK_WRITE(V0) {
value = param.asInt(); // Get value from Blynk app
if(value == 1){
Serial.println("Opening door...");
showRhombusPattern(pixels.Color(0, 255, 0)); // Green for authorized
delay(500);
digitalWrite(relayPin, value);
}
else {
Serial.println("Closing door...");
digitalWrite(relayPin, value);
}
delay(5000);
}
void setup() {
Serial.begin(115200);
// while (!Serial);
Serial.flush();
delay(1000);
Serial.println("Starting RC522...");
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, HIGH); // Ensure relay is off initially
SPI.begin();
rfid.PCD_Init();
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xFF;
}
Serial.println(F("Ready to scan cards Bir, Here! ..."));
pixels.begin();
pixels.show(); // Turn off all pixels
// Connect to Blynk
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
}
void loop() {
Blynk.run();
if (millis() - lastActionTime > rainbowInterval && !overrideColor) {
showRainbowPattern();
lastActionTime = millis();
}
/ Reset override after showing status for a short while
if (overrideColor && millis() - lastActionTime > 3000) {
overrideColor = false;
lastActionTime = millis();
}
if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
Serial.println(F("Card detected. UID:"));
printHex(rfid.uid.uidByte, rfid.uid.size);
Serial.println();
if (isAuthorized(rfid.uid.uidByte)) {
Serial.println("Authorized card detected!");
overrideColor = true;
if (flag) {
Serial.println("Opening door...");
// showColor(pixels.Color(0, 255, 0));
showRhombusPattern(pixels.Color(0, 255, 0)); // Green for authorized
delay(500);
digitalWrite(relayPin, LOW);
} else {
Serial.println("Closing door...");
digitalWrite(relayPin, HIGH);
}
lastActionTime = millis();
flag = !flag;
delay(5000); // Keep the relay active for 5 seconds
} else {
Serial.println("Unauthorized card.");
// showColor(pixels.Color(255, 0, 0));
showRhombusPattern(pixels.Color(255, 0, 0)); // Red for unauthorized
}
// Reset RFID reader
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
rfid.PCD_Init();
delay(100);
}
// Show rhombus pattern (assuming 4 LEDs in a square configuration)
void showRhombusPattern(uint32_t color) {
// Sequence for rhombus pattern: 0, 1, 3, 2 (assuming physical layout)
int rhombusSequence[30] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29};
// First turn all LEDs off
pixels.clear();
// Light up LEDs in rhombus pattern
for (int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(rhombusSequence[i], color);
pixels.show();
delay(100); // Small delay for visible sequence
}
// Keep all rhombus LEDs on for a moment
delay(500);
}
bool isAuthorized(byte *uid) {
return compareUID(uid, authorizedUID1) || compareUID(uid, authorizedUID2);
}
bool compareUID(byte *uid, byte *authorizedUID) {
for (byte i = 0; i < 4; i++) {
if (uid[i] != authorizedUID[i]) return false;
}
return true;
}
void printHex(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
void showColor(uint32_t color) {
for (int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, color);
}
pixels.show();
}
void showRainbowPattern() {
for (int j = 0; j < 256; j++) {
for (int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, Wheel((i * 256 / NUMPIXELS + j) & 255));
}
pixels.show();
delay(10); // Small delay for visible rainbow motion
}
}
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170) {
WheelPos -= 85;
return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}