Final Project Development¶
Inspiration¶
Input and the Output considered¶
Input¶
- RFID card and RFID scanner
Output¶
-
Solenoid
-
Neopixels
-
Sound
Prototyping¶
Initial rapid prototyping¶
I made my cardboard prototype using cardboard.I used the dxf file formate from the fusion and I used the Zund to cut the cardboard.The picture below is my first prototype.
Why initial prototyping?¶
This will allows me to figure out:
- What to Change: You can see what works and what doesn’t, so you know how to make your idea better.
- How Big to Make It: You can decide how big or small your project should be.
- Where to Put Things: You get to plan where each piece should go, like putting together a puzzle.
- What It Will Look Like: You get a sneak peek of how your final project might turn out, so you can focus on fixing or improving the parts that need work.
2nd Prototyping¶
I want to design cabinet with drawers that blinks the neopixels in calming pattern. When an authorized user touches the drawer door, the system detects the interaction, the decorative LEDs gently blink in a calming pattern (e.g., slow fade-in and fade-out) to indicate the system is active and ready.
I found this idea from the pinterest. I was thining of making this drawers door in modling casting week.
Here is my second version of the prototype drawer
Materials¶
Component | Price | Link |
---|---|---|
Seeeduino XIAO ESP32 C3 Microcontroller | $12.99 | Amazon Link |
RC522 RFID Module | $15.99 (pack of 5 modules) | Amazon Link |
Neopixel | ~$1 each | N/A |
Miscellaneous Components (Jumper wires, resistors, etc.) | $6.98 (120-piece kit) | Amazon Link |
Solenoid Lock | $10–$20 | Amazon Link |
Relay Module | $5–$10 | Amazon Link |
Rubber wood | $51.76 USD | Amazon Link |
3D printed PCB casing | $1.73 USD | Amazon Link |
|
Total Estimated Cost:¶
- $12.99 (microcontroller)
- $15.99 (RFID modules)
- $1 (neopixels)
- $6.98 (miscellaneous components)
- $10–$20 (solenoid lock)
- $5–$10 (relay module)
Total: $120.45 USD
Therefore, the total estimated cost ranges 9,997.35 BTN.
Week 02¶
In week two I tired making my first cabinet. I used the fusion 360 to do my designing. This is how my cabinet going to look.
Week04¶
In embeded programming week, I tired to programming using Esp32 as mcu and lcd with leds.
How it Works?
Inital Electronics design
I used the code by from here
📌
#include <LiquidCrystal.h>
// Define ESP32 GPIO pins for parallel LCD
LiquidCrystal lcd(14, 12, 27, 26, 25, 33); // LCD pins
// ✅ Define LED GPIOs BEFORE setup()
#define LED1 19
#define LED2 5
#define LED3 17
#define BACKLIGHT 21
void setup() {
// Set LCD backlight pin as output
pinMode(BACKLIGHT, OUTPUT);
digitalWrite(BACKLIGHT, HIGH); // Turn ON backlight
// Set LED pins as outputs and initialize them OFF
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
digitalWrite(LED1, LOW);
digitalWrite(LED2, LOW);
digitalWrite(LED3, LOW);
// Initialize the LCD
lcd.begin(16, 2); // Assuming a 16x2 LCD
}
void loop() {
// Blink LED1 and display message
digitalWrite(LED1, HIGH);
lcd.setCursor(0, 0);
lcd.print("Authorized ");
delay(1000);
digitalWrite(LED1, LOW);
lcd.clear();
// Blink LED2 and display message
digitalWrite(LED2, HIGH);
lcd.setCursor(0, 0);
lcd.print("Not auhorized");
delay(1000);
digitalWrite(LED2, LOW);
lcd.clear();
// Blink LED3 and display message
digitalWrite(LED3, HIGH);
lcd.setCursor(0, 0);
lcd.print("Scan Again");
delay(1000);
digitalWrite(LED3, LOW);
lcd.clear();
delay(1000); // Pause before loop repeats
}
Week 06¶
In week 06 I tired designing my board, I used the esp32 as MCU.Given below is the rough skecth of how my wiring will be
My first schematic
My first PCB
Week08.¶
In electronics production week, I tired redesign my board using XIAO RP2040. I milled and soldered my board.
My new schematic circuit design
My pcb
Week 09¶
In the input week, I tired using the RFID as the input to read the card UID
#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN D2 // Chip Select pin
#define RST_PIN D1 // Reset pin
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
void setup() {
Serial.begin(9600); // Initialize serial communication
SPI.begin(); // Initialize SPI bus
mfrc522.PCD_Init(); // Initialize MFRC522
Serial.println("RFID Scanner Ready!");
}
void loop() {
// Look for new cards
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
Serial.println("Card detected!");
// Print UID of the card
Serial.print("UID: ");
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Serial.println();
mfrc522.PICC_HaltA(); // Halt PICC
}
}
Here is rough sketch of my wiring, I am thinking of using the ESP32C3 as the for my final project. Before designing in the Kicad, I want to first try the circuit in the output week and check what are the changes to be done. after that I will make design the circuit for the PCB.
Week10¶
This week I used neopixels and solenoid to as output, as this I will be using the solenoid and neopixels for my final project.
Solenoid¶
I uploaded the code in arduino IDE, The code I used:
📌
const int relayPin = 13; // GPIO pin connected to the relay module
void setup() {
pinMode(relayPin, OUTPUT);
}
void loop() {
// Switch on the solenoid
digitalWrite(relayPin, HIGH);
delay(1000); // Solenoid remains ON for 1 second
// Switch off the solenoid
digitalWrite(relayPin, LOW);
delay(5000); // Solenoid remains OFF for 5 seconds
}
Neopixels¶
#include <SPI.h>
#include <MFRC522.h>
#include <Adafruit_NeoPixel.h>
#define RFID_SS_PIN 10
#define RFID_RST_PIN 9
#define NEOPIXEL_PIN 6
#define NUMPIXELS 8 // Number of NeoPixels
MFRC522 mfrc522(RFID_SS_PIN, RFID_RST_PIN);
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Replace with your authorized card UIDs
byte authorizedUID1[] = {0xDE, 0xAD, 0xBE, 0xEF}; // Example UID - replace with yours
byte authorizedUID2[] = {0x12, 0x34, 0x56, 0x78}; // Add more as needed
void setup() {
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
pixels.begin();
pixels.setBrightness(50); // Adjust brightness (0-255)
Serial.println("RFID + NeoPixel Ready");
}
void loop() {
// Reset the loop if no new card present
if (!mfrc522.PICC_IsNewCardPresent() || !mfrc522.PICC_ReadCardSerial()) {
delay(50);
return;
}
Serial.print("Card UID:");
for (byte i = 0; i < mfrc522.uid.size; i++) {
Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
Serial.print(mfrc522.uid.uidByte[i], HEX);
}
Serial.println();
// Check if card is authorized
bool isAuthorized = false;
if (compareUID(mfrc522.uid.uidByte, authorizedUID1, 4) ||
compareUID(mfrc522.uid.uidByte, authorizedUID2, 4)) {
isAuthorized = true;
}
// Light up NeoPixels based on authorization
if (isAuthorized) {
authorizedAnimation();
Serial.println("Authorized - Rainbow colors!");
} else {
unauthorizedRed();
Serial.println("Unauthorized - Red alert!");
}
delay(1000); // Debounce delay
mfrc522.PICC_HaltA();
}
bool compareUID(byte *a, byte *b, byte len) {
for (byte i = 0; i < len; i++) {
if (a[i] != b[i]) return false;
}
return true;
}
void authorizedAnimation() {
// Green, Yellow, Blue, Indigo, Violet sequence
uint32_t colors[] = {
pixels.Color(0, 255, 0), // Green
pixels.Color(255, 255, 0), // Yellow
pixels.Color(0, 0, 255), // Blue
pixels.Color(75, 0, 130), // Indigo
pixels.Color(148, 0, 211) // Violet
};
for (int color = 0; color < 5; color++) {
for (int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, colors[color]);
}
pixels.show();
delay(300); // Time between color changes
}
}
void unauthorizedRed() {
for (int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, pixels.Color(255, 0, 0)); // Red
}
pixels.show();
delay(1000); // Red stays on for 1 second
}
Final Code 1¶
#include <SPI.h>
#include <MFRC522.h>
#include <Adafruit_NeoPixel.h>
#define BLYNK_PRINT Serial
#include <DFRobotDFPlayerMini.h>
#include <SoftwareSerial.h>
// Initialize software serial on pins D3 (RX) and D4 (TX)
SoftwareSerial mySerial(D4, D3);
// Create DFPlayer object
DFRobotDFPlayerMini myDFPlayer;
// 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...");
myDFPlayer.play(1); // Play track 0001.mp3
showRhombusPattern(pixels.Color(0, 255, 0)); // Green for authorized
delay(500);
digitalWrite(relayPin, value);
}
else {
Serial.println("Closing door...");
myDFPlayer.play(2); // Play track 0001.mp3
digitalWrite(relayPin, value);
}
delay(5000);
}
void setup() {
Serial.begin(115200);
mySerial.begin(9600); // Start software serial for DFPlayer
Serial.println(F("Initializing DFPlayer..."));
// Initialize DFPlayer
if (!myDFPlayer.begin(mySerial)) {
Serial.println(F("DFPlayer initialization failed!"));
Serial.println(F("1. Check RX/TX connections (must be crossed)"));
Serial.println(F("2. Insert SD card with MP3 files"));
while(true); // Halt if initialization fails
}
Serial.println(F("DFPlayer Mini ready!"));
myDFPlayer.volume(30); // Set volume (0-30)
// while (!Serial);
Serial.flush();
delay(1000);
Serial.println("Starting RC522...");
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW); // 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();
showRhombusPattern(pixels.Color(255, 255, 255)); // white for ideal state
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...");
myDFPlayer.play(1); // Play track 0001.mp3
//delay(5000); // Wait 5 seconds
// showColor(pixels.Color(0, 255, 0));
showRhombusPattern(pixels.Color(0, 255, 0)); // Green for authorized
delay(500);
digitalWrite(relayPin, HIGH);
} else {
Serial.println("Closing door...");
myDFPlayer.play(2); // Play track 0002.mp3
//delay(5000); // Wait 5 seconds
digitalWrite(relayPin, LOW);
}
lastActionTime = millis();
flag = !flag;
delay(5000); // Keep the relay active for 5 seconds
} else {
Serial.println("Unauthorized card.");
myDFPlayer.play(3); // Play track 0001.mp3
//delay(5000); // Wait 5 seconds
// 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);
}