RFID based attendance system using ESP32 with OLED display connected to Firebase and Google Sheets

RFID Based Attendance System Using ESP32 with Firebase and Google Sheets

What You’ll Build in This Project:

The system reads RFID tags and uploads attendance data instantly to Firebase and Google Sheets, offering secure storage and easy reporting. It’s beginner-friendly with clear steps, making it simple to build.

The user selects ESP32 for its low cost (about 350 rupees) and built-in Wi-Fi, which supports real-time cloud syncing. Its powerful dual-core processor and Arduino IDE support make it ideal for affordable, scalable RFID attendance projects.

How the system tracks attendance

The ESP32 reads each RFID scan and sent in real time to both cloud databases, stamped with date and time. The system auto-retries if Wi-Fi drops, blocks unauthorized scans, and lets admins view up-to-date attendance from anywhere.

Components and Tools Required

Hardware list (ESP32, MFRC522 RFID module, etc.)

  • ESP32 microcontroller board
  • MFRC522 RFID reader module
  • RFID cards or tags
  • Jumper wires
  • Breadboard or PCB for connections
  • Optional: OLED or LCD display for feedback

All components are low-cost and available online or at electronics stores, letting you build this system on a student budget.

Software list (Arduino IDE, libraries)

  • Arduino IDE (free download)
  • ESP32 board support via Board Manager
  • MFRC522 library for RFID
  • WiFi and HTTPClient libraries for networking
  • Optionally, Adafruit SSD1306 or LCD library for display

These libraries are free, well-supported, and make coding much faster and easier for all levels of users.

Cloud accounts (Firebase, Google Sheets)

  • Free Firebase account for realtime database storage
  • Free Google Sheets account via Google
  • Both accounts are easy to set up and provide secure cloud hosting for attendance logs

No paid service needed, and setup can be completed in minutes with a standard Google login.

System Circuit Design and Wiring

ESP32 RFID RC522 attendance system on vertical breadboard with OLED display showing RFID system ready.

MFRC522 RFID Module to ESP32 NodeMCU 30-Pin

RFID Module PinESP32 Pin LabelDescription
VCC3V3Power (3.3V only)
GNDGNDGround
RSTD4Reset pin
IRQNot connectedLeave empty
MISOD19Master In Slave Out
MOSID23Master Out Slave In
SCKD18Serial Clock
SDA/SSD5Slave Select

0.96″ OLED Display (I2C) to ESP32 NodeMCU

OLED PinESP32 Pin LabelDescription
GNDGNDGround
VDD3V3Power (3.3V)
SCKD22I2C Clock
SDAD21I2C Data

Visual Wiring Diagram:

ESP32 NodeMCU 30-Pin

├── 3V3 ──┬── RFID VCC
│         └── OLED VDD

├── GND ──┬── RFID GND
│         └── OLED GND

├── D4 ─────── RFID RST
├── D5 ─────── RFID SDA/SS
├── D18 ────── RFID SCK
├── D19 ────── RFID MISO
├── D21 ────── OLED SDA
├── D22 ────── OLED SCK
└── D23 ────── RFID MOSI

Pin Definitions for Arduino Code:

// RFID pins
#define RST_PIN 4    // D4
#define SS_PIN 5     // D5
// MISO = D19 (GPIO19)
// MOSI = D23 (GPIO23)
// SCK = D18 (GPIO18)

// OLED pins (I2C)
#define OLED_SDA 21  // D21
#define OLED_SCL 22  // D22

Double-Check Your Connections

Before powering on, verify:

  • ✅ RFID VCC and OLED VDD both go to 3V3 (NOT 5V)
  • ✅ All GND pins are connected together
  • ✅ RFID RST is on D4 (separate from OLED)
  • ✅ OLED SCK on D22, SDA on D21
  • ✅ RFID SPI pins: D5, D18, D19, D23
  • ✅ All wires are firmly inserted (wiggle test them)

Check Our ESP32 Pinout Guide: https://learniot.in/esp32-pinout-reference/

Setting Up Arduino IDE and ESP32

Adding ESP32 board to Arduino IDE

Adding ESP32 board to Arduino IDE:

  1. Open Arduino IDE
  2. Go to File → Preferences
  3. Add this URL to “Additional Board Manager URLs”: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  4. Go to Tools → Board → Board Manager
  5. Search “ESP32” and install “ESP32 by Espressif Systems
  6. Select Tools → Board → ESP32 Arduino → ESP32 Dev Module

Installing required libraries (MFRC522, WiFi, HTTPClient)

Go to Sketch → Include Library → Manage Libraries, then install:

  • MFRC522 (for RFID)
  • Adafruit GFX Library (for OLED)
  • Adafruit SSD1306 (for OLED)
  • WiFi (built-in with ESP32)
  • HTTPClient (built-in with ESP32)
  • ArduinoJson (for Firebase/Sheets data formatting)

Common setup issues and fixes

If you don’t see the ESP32 board in the list, double-check the Board Manager URL and install updates. If the COM port isn’t detected or uploads fail, install the CP2102 or CH340 driver (depending on your ESP32 model). Press and hold the “BOOT” button during upload if you see a “Timeout” or “Failed to connect” error. A quick IDE restart often solves library issues—it’s usually something small!.

Firebase and Google Sheets Integration

Creating Firebase Realtime Database

  1. Go to firebase.google.com
  2. Create new project
  3. Enable Realtime Database
  4. Set rules to test mode (for now)
  5. Copy your Database URL and API Key

Setting up Google Sheets API:

Step 1: Prepare Google Sheet

  • Create new Google Sheet with columns in Row 1:

| Name | Card ID | Date | Time |

Step 2: Add Apps Script:

function doGet(e) {
  return handleRequest(e);
}

function doPost(e) {
  return handleRequest(e);
}

function handleRequest(e) {
  try {
    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
    var params = e.parameter;
    
    var name = params.name || "Unknown";
    var uid = params.uid || "Unknown";
    var timestamp = params.time || new Date().toLocaleTimeString();
    var date = new Date().toLocaleDateString();
    
    // Append new row: Name, Card ID, Date, Time
    sheet.appendRow([name, uid, date, timestamp]);
    
    return ContentService.createTextOutput(
      JSON.stringify({"result": "Success"})
    ).setMimeType(ContentService.MimeType.JSON);
  }
  catch(error) {
    return ContentService.createTextOutput(
      JSON.stringify({"result": "Error", "message": error.toString()})
    ).setMimeType(ContentService.MimeType.JSON);
  }
}

Step 3: Deploy Web App

  1. Click Deploy → New deployment
  2. Choose “Web app” as deployment type
  3. Set Execute as: Me (your Google account)
  4. Set Who has access: Anyone
  5. Click Deploy
  6. Copy the Web App URL

Step 4: Use Deployment URL in ESP32 Code

Example HTTP GET request from ESP32 to Google Sheets:

https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec?uid=A1B2C3D4&time=12:45pm&name=John%20Doe

Replace ESP32 code with your URL (remember to URL-encode names if needed). The webhook will automatically append data into the Google Sheet.

Coding the ESP32 for RFID Attendance

Full Arduino Sketch (Copy-Paste Ready)

#include <SPI.h>
#include <MFRC522.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ArduinoJson.h>

#define RST_PIN 4   // D4
#define SS_PIN 5    // D5

MFRC522 rfid(SS_PIN, RST_PIN);

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ===== CONFIGURE THESE =====
const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";

String firebaseUrl = "YOUR_PROJECT.firebaseio.com";
String firebaseKey = "YOUR_FIREBASE_SECRET";

String sheetsUrl = "YOUR_GOOGLE_APPS_SCRIPT_URL";

// Function prototypes
void connectWiFi();
void showReady();
void showScanning(String uid);
void showSuccess(String uid);
void showError();
void showMessage(String line1, String line2, String line3);
String getUID();
String getTime();
bool sendFirebase(String uid, String time);
bool sendSheets(String uid, String time);

void setup() {
  Serial.begin(115200);
  SPI.begin();
  rfid.PCD_Init();
  
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED failed");
    while(1);
  }
  
  connectWiFi();
  showReady();
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) connectWiFi();
  
  if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
    String uid = getUID();
    
    showScanning(uid);
    
    String time = getTime();
    
    if (sendFirebase(uid, time) && sendSheets(uid, time)) {
      showSuccess(uid);
    } else {
      showError();
    }
    
    delay(3000);
    showReady();
    
    rfid.PICC_HaltA();
  }
  delay(200);
}

String getUID() {
  String uid = "";
  for (byte i = 0; i < rfid.uid.size; i++) {
    uid += rfid.uid.uidByte[i] < 0x10 ? "0" : "";
    uid += String(rfid.uid.uidByte[i], HEX);
  }
  uid.toUpperCase();
  return uid;
}

String getTime() {
  return String(millis());
}

void connectWiFi() {
  WiFi.begin(ssid, password);
  showMessage("Connecting WiFi", "...", "");
  
  int i = 0;
  while (WiFi.status() != WL_CONNECTED && i < 20) {
    delay(500);
    Serial.print(".");
    i++;
  }
  Serial.println();
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
}

bool sendFirebase(String uid, String time) {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    String url = "https://" + firebaseUrl + "/attendance.json?auth=" + firebaseKey;
    
    StaticJsonDocument<200> doc;
    doc["uid"] = uid;
    doc["time"] = time;
    
    String json;
    serializeJson(doc, json);
    
    http.begin(url);
    http.addHeader("Content-Type", "application/json");
    int code = http.POST(json);
    http.end();
    
    Serial.print("Firebase: ");
    Serial.println(code);
    
    return (code == 200 || code == 201);
  }
  return false;
}

bool sendSheets(String uid, String time) {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    String url = sheetsUrl + "?uid=" + uid + "&time=" + time;
    http.begin(url);
    int code = http.GET();
    http.end();
    
    Serial.print("Sheets: ");
    Serial.println(code);
    
    return (code == 200 || code == 302);
  }
  return false;
}

void showReady() {
  showMessage("Attendance Ready", "Scan Card", "");
}

void showScanning(String uid) {
  showMessage("Scanning", uid, "Processing...");
}

void showSuccess(String uid) {
  showMessage("SUCCESS", uid, "Saved!");
}

void showError() {
  showMessage("ERROR", "Check WiFi", "or Cloud");
}

void showMessage(String line1, String line2, String line3) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 15);
  display.println(line1);
  display.setCursor(0, 35);
  display.println(line2);
  if (line3 != "") {
    display.setCursor(0, 50);
    display.println(line3);
  }
  display.display();
}

BEFORE UPLOADING – UPDATE THESE 3 LINES:

Line 22-23: WiFi credentials

const char* ssid = "YourHomeWiFi";
const char* password = "YourWiFiPassword";

Line 25-26: Firebase config

String firebaseUrl = "yourproject.firebaseio.com";
String firebaseKey = "your_api_key_here";

Line 28: Google Sheets URL

String sheetsUrl = "https://script.google.com/macros/s/YOUR_SCRIPT_ID/exec";

Uploading, Testing & Debugging

Uploading your code to ESP32

  1. Select BoardTools → Board → ESP32 Arduino → ESP32 Dev Module
  2. Select PortTools → Port → COM6 (your ESP32 port)
  3. Click Verify → Should show: 291KB (22%) of program storage
  4. Click Upload (→ arrow icon)
  5. If stuck at “Connecting…” → Hold BOOT button 3 seconds during upload
  6. Success messageHard resetting via RTS pin...
Expected output:
esptool v5.1.0 Serial port COM6
Chip type: ESP32-D0WD-V3
Writing at 0x00010000 [==========================] 100%
Hard resetting via RTS pin...

First RFID card scan

After upload, watch OLED sequence:

1. "Connecting WiFi..." + dots (10 seconds)
2. "Attendance Ready"  
   "Scan Card" 
3. Scan RFID card"Scanning" + UID
4. "ERROR" (normal - no Firebase yet)

Serial Monitor (115200 baud) shows:

IP: 192.168.1.100
Card scanned: A1B2C3D4
Firebase: -1
Sheets: -1

Viewing attendance in cloud

Firebase Console:

  1. Go to console.firebase.google.com
  2. Select your project → Realtime Database
  3. Path: /attendance → See JSON entries appear

Google Sheets:

  1. Open your Google Sheet
  2. New rows auto-appear: [UID, Time, Date]
Firebase shows:
{
  "-N123abc": {
    "uid": "A1B2C3D4",
    "time": "12345678"
  }
}

Debugging common errors

ErrorOLED/Serial ShowsFix
Upload failsConnecting.... (stuck)Hold BOOT button 3 sec during upload
No WiFiNo dots, stays on WiFi screenCheck SSID/password spelling (case-sensitive)
No RFID“Attendance Ready” but no scanCheck wiring: D4(RST), D5(SS), D18,19,23
OLED blankNothing displaysCheck D21(SDA), D22(SCK), 3.3V power
“Firebase: -1”Normal (no config yet)Setup Firebase later
Random charsGarbage in Serial MonitorWrong baud rate → Set 115200

Quick fixes:

No Serial outputToolsSerial Monitor115200 baud
OLED shows garbagePower cycle ESP32
Multiple card readsIncrease delay(3000) to delay(5000)

Test checklist:

  •  Upload successful
  •  WiFi connects (IP in Serial Monitor)
  •  OLED shows “Attendance Ready”
  •  RFID card detected on scan
  •  “ERROR” message appears (expected)

Enhancing the System

Making a web dashboard

Firebase Console = Your INSTANT Live Dashboard! (No extra hosting needed)

Step 1: Access Firebase Live Dashboard

1. Go to console.firebase.google.com
2. Select your project
3. Click "Realtime Database""Data" tab
4. LIVE attendance appears instantly!

Your data shows LIVE:

yourproject.firebaseio.com/attendance/
├── -N123abc: { "uid": "A1B2C3D4", "time": "123456" }
├── -N456def: { "uid": "B2C3D4E5", "time": "123789" }
└── Updates every card scan! 👇

Step 2: Shareable Mobile Dashboard

Direct link: https://yourproject.firebaseio.com/attendance.json

Phone browserLive JSON data
Bookmark for teachers
No app install needed
Works offline (cached)

Step 3: Google Sheets Dashboard (Automatic Reports)

Your Sheet auto-updates:
| UID       | Time     | Date        |
|-----------|----------|-------------|
| A1B2C3D4  | 23:14:23 | 27-Nov-2025 |
| B2C3D4E5  | 23:15:01 | 27-Nov-2025 |

Share: sheets.google.com"Anyone with link"

Complete Dashboard System:

ESP32Firebase (Live JSON) + Google Sheets (Excel)
         ↓                           ↓
Firebase Console (Live)     Google Sheets (Reports)

Dashboard URLs ready to share:

🔴 Live: yourproject.firebaseio.com/attendance.json
📊 Reports: docs.google.com/spreadsheets/YOUR_SHEET_ID

Real Project Experience & Troubleshooting

Wiring mistakes I actually made

RFID VCC to 5VModule fried instantly (use 3.3V only)
MISO/MOSI swappedNo card detection
Forgot common GNDRandom resets
OLED SDA to D20Blank screen (use D21)

RFID reader troubles & solutions

"No card detected"Check D4(RST), D5(SS), 3.3V wiring
"Card read failed"Add 10 pullup on RST pin
Multiple readsIncrease delay(3000) → delay(5000)
Weak rangeAdd 100uF capacitor across RFID VCC/GND

Preventing WiFi dropouts

unsigned long lastCheck = 0;
void loop() {
  if(millis() - lastCheck > 30000) {  // Check every 30s
    if(WiFi.status() != WL_CONNECTED) connectWiFi();
    lastCheck = millis();
  }
}

Frequently Asked Questions

What is the maximum number of cards supported?

The ESP32 can handle over 65,000 unique RFID card UIDs—ideal for classrooms or offices.

Will it work if the WiFi goes down?

The card scan data appears on the Serial Monitor, so you don’t lose local records. For true offline storage, code could be extended to save to SD card.

Can NFC phones act as RFID cards?

 Yes, using NFC stickers or compatible apps, you can register phones as valid RFID tags.

How do I add another ESP32 scanner at a different door?

Use the same Firebase and Google Sheets URLs—multiple devices will sync attendance records.

What wiring problems are most common?

Mistakes like swapping MISO/MOSI, using 5V instead of 3.3V for the RFID module, or leaving out a common ground.

Leave a Reply

Your email address will not be published. Required fields are marked *