Arduino Uno R4 Wi-Fi Based RFID Attendance System
An Arduino Uno R4 Wi-Fi-powered intelligent, automated RFID attendance system that tracks attendance, timing and summary in real-time!
Components and supplies
1
Jumper Wires (Generic)
1
20x4 I2C LCD display
1
Arduino UNO R4 WiFi LED Matrix
1
RFID Module (RC522)
Apps and platforms
1
Arduino IDE 2.0 (beta)
Project description
Code
Code
c
1* Beginner-friendly RFID Attendance (RC522 + 20x4 I2C LCD) 2 For Arduino Uno R4 Wi-Fi (pinout same as UNO-compatible boards) 3 Wiring (Arduino UNO/R4): 4 RC522: SDA(SS)=D10, SCK=D13, MOSI=D11, MISO=D12, RST=D9, 3.3V, GND 5 I2C LCD: SDA=A4, SCL=A5, VCC=5V, GND=GND 6 7 Changes in this version: 8 - Removed duplicate UID entry. 9 - Updated student names list to new names. 10*/ 11 12#include <Wire.h> 13#include <SPI.h> 14#include <MFRC522.h> 15#include <LiquidCrystal_I2C.h> 16 17#define SS_PIN 10 // SDA/SS for RC522 18#define RST_PIN 9 // RST for RC522 19 20#define LCD_ADDR 0x27 21#define LCD_COLS 20 22#define LCD_ROWS 4 23 24MFRC522 rfid(SS_PIN, RST_PIN); 25LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLS, LCD_ROWS); 26 27// teacher UID (uppercase, no spaces) 28const char TEACHER_UID[] = "2A7E17B1"; 29 30// 10 minutes = 10 * 60 * 1000 milliseconds 31const unsigned long ATTENDANCE_LENGTH = 10UL * 60UL * 1000UL; 32 33// debounce time to avoid reading same card many times quickly 34const unsigned long DEBOUNCE = 1000UL; 35 36// how long to show a student's info (ms) 37const unsigned long SHOW_MS = 1500UL; 38 39// small refresh rate for live timer (ms) 40const unsigned long REFRESH_MS = 500UL; 41 42// --- Student UID list and matching names --- 43// Duplicate UID removed — ensure all UIDs here are unique (uppercase, no spaces) 44const char* uids[] = { 45 "E2D2D500", 46 "49F1DF00", 47 "5C55D500", 48 "827ED600", 49 "310AF400", 50 "D7CFE000", 51 "23370EAA", 52 "7EB6F300", 53 "D784D500" 54}; 55 56const char* names[] = { 57 "Amanjeet Kaur", 58 "Siddharth Verma", 59 "Meera Patel", 60 "Arjun Khanna", 61 "Neha Rathi", 62 "Vikram Singh", 63 "Simran Kaur", 64 "Ritik Sharma", 65 "Kavya Menon" 66}; 67 68const int NUM = sizeof(uids) / sizeof(uids[0]); 69 70// attendance state: 0=absent, 1=on time, 2=late 71uint8_t attendance[NUM]; 72 73// timing vars 74unsigned long startTime = 0; 75bool windowStarted = false; 76 77// helpers for debounce and display refresh 78String lastUID = ""; 79unsigned long lastUIDTime = 0; 80unsigned long lastRefresh = 0; 81 82void setup() { 83 Serial.begin(9600); 84 while (!Serial) { } // waits for Serial on some boards, harmless on UNO/R4 85 86 SPI.begin(); 87 rfid.PCD_Init(); 88 89 lcd.init(); 90 lcd.backlight(); 91 lcd.clear(); 92 93 // welcome message 94 lcd.setCursor(0, 0); 95 lcd.print("Welcome to the"); 96 lcd.setCursor(0, 1); 97 lcd.print("RFID attendance"); 98 lcd.setCursor(0, 2); 99 lcd.print("system"); 100 delay(2000); 101 102 // start attendance window now 103 lcd.clear(); 104 lcd.setCursor(0,0); 105 lcd.print("Ready for attendance"); 106 startTime = millis(); 107 windowStarted = true; 108 109 // mark everyone absent initially 110 for (int i = 0; i < NUM; i++) attendance[i] = 0; 111 112 // show initial timer immediately 113 updateTimerOnLCD(); 114 Serial.println("Attendance started."); 115} 116 117void loop() { 118 unsigned long now = millis(); 119 120 // update the live countdown at intervals 121 if (now - lastRefresh >= REFRESH_MS) { 122 updateTimerOnLCD(); 123 lastRefresh = now; 124 } 125 126 // check for a new card 127 if (!rfid.PICC_IsNewCardPresent()) return; 128 if (!rfid.PICC_ReadCardSerial()) return; 129 130 // build UID string (HEX uppercase, no spaces) 131 String uid = ""; 132 for (byte i = 0; i < rfid.uid.size; i++) { 133 if (rfid.uid.uidByte[i] < 0x10) uid += "0"; 134 uid += String(rfid.uid.uidByte[i], HEX); 135 } 136 uid.toUpperCase(); 137 138 // simple debounce: ignore if same card scanned within DEBOUNCE ms 139 if (uid == lastUID && (now - lastUIDTime) < DEBOUNCE) { 140 rfid.PICC_HaltA(); 141 rfid.PCD_StopCrypto1(); 142 return; 143 } 144 lastUID = uid; 145 lastUIDTime = now; 146 147 Serial.print("Card scanned: "); 148 Serial.println(uid); 149 150 // teacher card -> show summary of all students 151 if (uid == String(TEACHER_UID)) { 152 showSummary(); 153 rfid.PICC_HaltA(); 154 rfid.PCD_StopCrypto1(); 155 updateTimerOnLCD(); 156 return; 157 } 158 159 // find student index 160 int idx = findIndex(uid.c_str()); 161 if (idx < 0) { 162 // unknown card 163 lcd.clear(); 164 lcd.setCursor(0,0); 165 lcd.print("Unknown card:"); 166 lcd.setCursor(0,1); 167 lcd.print(uid); 168 lcd.setCursor(0,3); 169 lcd.print("Not registered"); 170 Serial.println("Unknown UID - not registered."); 171 delay(SHOW_MS); 172 updateTimerOnLCD(); 173 rfid.PICC_HaltA(); 174 rfid.PCD_StopCrypto1(); 175 return; 176 } 177 178 // if already marked, just display status again 179 if (attendance[idx] != 0) { 180 showStudent(idx); 181 delay(SHOW_MS); 182 updateTimerOnLCD(); 183 rfid.PICC_HaltA(); 184 rfid.PCD_StopCrypto1(); 185 return; 186 } 187 188 // determine if scan is inside the attendance window 189 bool onTime = windowStarted && ((now - startTime) <= ATTENDANCE_LENGTH); 190 if (onTime) attendance[idx] = 1; // on time 191 else attendance[idx] = 2; // late 192 193 // show student info 194 showStudent(idx); 195 delay(SHOW_MS); 196 updateTimerOnLCD(); 197 198 rfid.PICC_HaltA(); 199 rfid.PCD_StopCrypto1(); 200} 201 202// find index of uid in uids[]; return -1 if not found 203int findIndex(const char* uid) { 204 for (int i = 0; i < NUM; i++) { 205 if (strcmp(uids[i], uid) == 0) return i; 206 } 207 return -1; 208} 209 210// show ready screen and live remaining time 211void updateTimerOnLCD() { 212 lcd.clear(); 213 lcd.setCursor(0,0); 214 lcd.print("Ready for attendance"); 215 216 if (windowStarted) { 217 long elapsed = (long)(millis() - startTime); 218 long remaining = (long)ATTENDANCE_LENGTH - elapsed; 219 if (remaining > 0) { 220 unsigned long seconds = remaining / 1000UL; 221 unsigned int mins = seconds / 60UL; 222 unsigned int secs = seconds % 60UL; 223 224 lcd.setCursor(0,1); 225 // print "Time left: mm:ss" with leading zero for seconds 226 lcd.print("Time left: "); 227 if (mins < 10) lcd.print('0'); 228 lcd.print(mins); 229 lcd.print(':'); 230 if (secs < 10) lcd.print('0'); 231 lcd.print(secs); 232 } else { 233 lcd.setCursor(0,1); 234 lcd.print("Attendance closed"); 235 } 236 } else { 237 lcd.setCursor(0,1); 238 lcd.print("Window not set"); 239 } 240 241 // clear lower lines for neatness 242 lcd.setCursor(0,2); lcd.print(" "); 243 lcd.setCursor(0,3); lcd.print(" "); 244} 245 246// show one student's info on LCD 247void showStudent(int i) { 248 lcd.clear(); 249 lcd.setCursor(0,0); 250 lcd.print(names[i]); // name 251 lcd.setCursor(0,1); 252 lcd.print("Present"); 253 lcd.setCursor(0,2); 254 if (attendance[i] == 1) { 255 lcd.print("ON time"); 256 Serial.print(names[i]); Serial.println(" -> ON time"); 257 } else { 258 lcd.print("Came late"); 259 Serial.print(names[i]); Serial.println(" -> Came late"); 260 } 261} 262 263// show one-by-one summary for teacher (Name + Present/Absent + On time/ Late) 264void showSummary() { 265 for (int i = 0; i < NUM; i++) { 266 lcd.clear(); 267 lcd.setCursor(0,0); 268 lcd.print(names[i]); 269 if (attendance[i] == 0) { 270 lcd.setCursor(0,1); 271 lcd.print("Absent"); 272 Serial.print(names[i]); Serial.println(": Absent"); 273 } else if (attendance[i] == 1) { 274 lcd.setCursor(0,1); 275 lcd.print("Present"); 276 lcd.setCursor(0,2); 277 lcd.print("ON time"); 278 Serial.print(names[i]); Serial.println(": Present (ON time)"); 279 } else { 280 lcd.setCursor(0,1); 281 lcd.print("Present"); 282 lcd.setCursor(0,2); 283 lcd.print("Late"); 284 Serial.print(names[i]); Serial.println(": Present (Late)"); 285 } 286 287 delay(2500); // pause 2.5 seconds per student 288 } 289}
Downloadable files
Connections
connection lcd.jpg

Comments
Only logged in users can leave comments