Friday, 23 May 2025

🎯 Build Your Own RFID Attendance System Using Arduino + ESP32 + Google Sheets

 

🎯 Build Your Own RFID Attendance System Using Arduino + ESP32 + Google Sheets

📅 By Dinesh | Tech DIY Projects | May 2025




 

 

🚀 Introduction

Have you ever wanted to build a smart attendance system that logs student or staff attendance directly into Google Sheets in real time?

In this tutorial, I’ll show you how I created a WiFi-connected RFID attendance system using:

  • ✅ Arduino UNO (for RFID + DFPlayer)

  • ✅ ESP32 (for WiFi + Google Sheet logging)

  • ✅ Google Apps Script (to act as a cloud database)

Let’s dive in!


🧠 Project Concept

Here’s how the system works:

  1. User scans an RFID card.

  2. Arduino detects the card, plays a welcome sound using DFPlayer, and sends the name to ESP32.

  3. ESP32 receives the name via serial and logs it to a Google Sheet using a webhook.

  4. Done! The name and timestamp are saved in the cloud.


🧰 Components Used

Component
Quantity
Arduino UNO
1
ESP32 (DevKit v1)
1
MFRC522 RFID Reader
1
RFID Tags/Cards
2+
DFPlayer Mini + Speaker
1
I2C LCD 16x2 Display
1
Jumper Wires
-
Voltage Regulator (if needed for 3.3V logic level)
1
Breadboard
1

🔌 Connections

RFID & DFPlayer to Arduino UNO:

  • RFID SDA → D10

  • RFID RST → D9

  • DFPlayer TX → D4

  • DFPlayer RX → D5

  • LCD I2C → A4 (SDA), A5 (SCL)

Arduino to ESP32:

  • Arduino TX (D1) → ESP32 RX (GPIO 16)

  • IMPORTANT: Use voltage divider or level shifter to avoid 5V-to-3.3V damage to ESP32.


📟 Arduino Code

The Arduino reads the card, displays info, and plays sound:

cpp
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <SPI.h>
#include <MFRC522.h>

// LCD I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // Adjust address if needed

// DFPlayer Mini on pins 4 (RX), 5 (TX) Arduino side
SoftwareSerial dfSerial(4, 5);
DFRobotDFPlayerMini myDFPlayer;

// RFID pins
#define RST_PIN 9
#define SS_PIN 10
MFRC522 rfid(SS_PIN, RST_PIN);

// DFPlayer Reset pin (optional)
#define DFPLAYER_RESET_PIN 8

// Known RFID UIDs and names
String knownUIDs[] = {
  "EA514D63"
};
String names[] = {
  "Dinesh"
};

// Retry DFPlayer initialization
bool initDFPlayer() {
  for (int i = 0; i < 5; i++) {
    if (myDFPlayer.begin(dfSerial)) {
      return true;
    }
    delay(1000); // Wait 1 sec before retry
  }
  return false;
}

void setup() {
  delay(3000); // Let power stabilize

  pinMode(DFPLAYER_RESET_PIN, OUTPUT);
  digitalWrite(DFPLAYER_RESET_PIN, LOW);  // Hold DFPlayer in reset
  delay(100);  // Reset pulse
  digitalWrite(DFPLAYER_RESET_PIN, HIGH); // Release reset
  delay(1000); // Wait for DFPlayer to boot

  Serial.begin(9600);   // Serial to ESP32
  dfSerial.begin(9600); // DFPlayer serial
  SPI.begin();
  rfid.PCD_Init();

  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Scan your ID...");

  if (!initDFPlayer()) {
    lcd.setCursor(0, 1);
    lcd.print("DFPlayer Error");
    Serial.println("Unable to initialize DFPlayer Mini!");
    while (true); // Halt
  }

  myDFPlayer.volume(30); // Set volume (0-30)
}

void loop() {
  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) {
    return;
  }

  // Read UID and convert to uppercase hex string
  String uid = "";
  for (byte i = 0; i < rfid.uid.size; i++) {
    if (rfid.uid.uidByte[i] < 0x10) uid += "0";
    uid += String(rfid.uid.uidByte[i], HEX);
  }
  uid.toUpperCase();
  Serial.println("UID: " + uid);

  bool matchFound = false;
  for (int i = 0; i < 6; i++) {
    if (uid == knownUIDs[i]) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Welcome,");
      lcd.setCursor(0, 1);
      lcd.print(names[i]);
      Serial.println("Attendance marked for " + names[i]);

      // Send matched UID and name to ESP32
      Serial.print("MATCH:");
      Serial.print(uid);
      Serial.print(",");
      Serial.println(names[i]);

      myDFPlayer.play(1); // Play welcome sound
      matchFound = true;
      break;
    }
  }

  if (!matchFound) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Unknown card");
    Serial.println("Unknown UID");

    // Send unknown info to ESP32
    Serial.println("UNKNOWN");

    myDFPlayer.play(2); // Play error sound (optional)
  }

  delay(3000); // Wait before next scan
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Scan your ID...");
}

📡 ESP32 Code (Receives & Sends to Google Sheet)

cpp
#include <WiFi.h>
#include <HTTPClient.h>

#define RXD2 16  // Arduino TX to ESP32 RX
#define TXD2 17  // Not used, but required for Serial2 init

const char* ssid = "*****";         // 🔁 Replace with your WiFi SSID
const char* password = "****";       // 🔁 Replace with your WiFi password

const char* serverName = "*****"; // 🔁 Replace with excelsheet link

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);  // Serial2 from Arduino

  Serial.println("Connecting to WiFi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("\nWiFi connected!");
}

void loop() {
  if (Serial2.available()) {
    String name = Serial2.readStringUntil('\n');
    name.trim(); // Remove leading/trailing whitespace

    Serial.println("Received from Arduino: " + name);

    // Remove "MATCH:" prefix if present
    if (name.startsWith("MATCH:")) {
      name = name.substring(6);
    }

    // Remove everything before the first comma, including the comma
    int commaIndex = name.indexOf(',');
    if (commaIndex != -1) {
      name = name.substring(commaIndex + 1);
    }

    Serial.println("Cleaned name: " + name);

    if (WiFi.status() == WL_CONNECTED) {
      HTTPClient http;

      String url = String(serverName) + name;
      http.begin(url);
      int httpResponseCode = http.GET();

      if (httpResponseCode > 0) {
        Serial.println("Data sent to Google Sheet!");
      } else {
        Serial.print("Error sending data: ");
        Serial.println(httpResponseCode);
      }

      http.end();
    } else {
      Serial.println("WiFi disconnected!");
    }
  }
}


🎉 Final Result

✅ RFID card scanned
✅ Welcome message on LCD
✅ Sound plays via DFPlayer
✅ Name logged in Google Sheet

No need for SD cards or Excel files — everything is real-time in the cloud 🌐.


❤️ Let’s Connect

Have doubts or want to build your own version?

📧 Contact me on: dtrendchannel@gmail.com






Friday, 9 May 2025

🌞 DIY Arduino Solar Tracker with Motor Control – Complete Guide

 

🌞 DIY Arduino Solar Tracker with Motor Control – Complete Guide



🔧 Overview:

This project uses Light Dependent Resistors (LDRs) to track the sun's position and adjust the orientation of a solar panel using two servo motors. Additionally, based on the sunlight intensity, it controls a motor using two buttons – ideal for automating a solar-powered device like a water pump.


🧰 Components Required:

Component
Quantity
Description
Arduino Uno
1
Microcontroller board
Servo Motor (SG90/MG90)
2
For horizontal and vertical rotation
LDR (Light Sensor)
5
For detecting sunlight intensity and direction
10kΩ Resistors
5
Pull-down resistors for each LDR
Push Buttons
2
For controlling motor direction
DC Motor
1
Can be used for pumping or rotation purposes
NPN Transistor (optional)
1
For driving higher power motors
Diode (1N4007)
1
For back EMF protection
Power Supply (9V/12V)
1
To power the motor
      Breadboard + Jumper Wires                      As needed    For circuit connections

🔌 Pin Configuration:

Arduino PinConnected Component
A1LDR Top Left
A2LDR Top Right
A3LDR Bottom Left
A4LDR Bottom Right
A5LDR Middle Top (Sunlight Detection)
D5Horizontal Servo Signal
D6Vertical Servo Signal
D7Motor Control A
D8Motor Control B
D9Button 1 (Forward)
D10Button 2 (Reverse)
GNDAll GND connections
5VPower supply for LDRs and buttons

⚙️ How It Works:

  • LDRs detect light intensity. The 4 corner LDRs determine the direction of sunlight, and the middle LDR checks whether there is enough light.

  • The Arduino calculates the average light values and adjusts the horizontal and vertical servo angles accordingly.

  • If sunlight is detected and button 1 is pressed, the motor rotates in one direction.

  • If no sunlight is present and button 2 is pressed, the motor rotates in the opposite direction.

  • If neither condition is met, the motor stops.


🖼️ Circuit Diagram:

📟 Arduino Code:

#include <Servo.h>


Servo horizontal; // horizontal servo

Servo vertical; // vertical servo
// LDR analog pins
const int button1 = 9;
int pos = 0;
void setup() {
  pinMode(motorA, OUTPUT);
  delay(2500); // Give servos time to initialize
void loop() {
    int lt = analogRead(ldrlt);
    int avt = (lt + rt) / 2;
    if (abs(dvert) > tol) {
    if (abs(dhoriz) > tol) {
    delay(dtime);
    for (pos = oldvalue; pos <= 180; pos++) {
    buttonStateB = digitalRead(button2);


int servoh = 180;

int servohLimitHigh = 175;

int servohLimitLow = 5;



int servov = 0;

int servovLimitHigh = 60;

int servovLimitLow = 0;



int ldrlt = A1; // Top Left

int ldrrt = A2; // Top Right

int ldrld = A3; // Bottom Left

int ldrrd = A4; // Bottom Right

int ldrmt = A5; // Middle Top LDR



const int button2 = 10;

const int motorA = 7;

const int motorB = 8;

int buttonStateA = 0;

int buttonStateB = 0;



int pos2 = 0;

int oldvalue, oldvalue2;



  horizontal.attach(5);

  vertical.attach(6);

  horizontal.write(180);

  vertical.write(0);



  pinMode(motorB, OUTPUT);

  pinMode(button1, INPUT);

  pinMode(button2, INPUT);



}



  int ldrStatus = analogRead(ldrmt);

  

  if (ldrStatus > 30) {

    buttonStateA = digitalRead(button1);

    if (buttonStateA == LOW) {

      digitalWrite(motorA, HIGH);

      digitalWrite(motorB, LOW); // Motor rotates in one direction

    } else {

      digitalWrite(motorA, LOW);

      digitalWrite(motorB, LOW); // Stop motor

    }



    int rt = analogRead(ldrrt);

    int ld = analogRead(ldrld);

    int rd = analogRead(ldrrd);

    int dtime = 10;

    int tol = 90;



    int avd = (ld + rd) / 2;

    int avl = (lt + ld) / 2;

    int avr = (rt + rd) / 2;

    int dvert = avt - avd;

    int dhoriz = avl - avr;



      if (avt > avd) {

        servov++;

        if (servov > servovLimitHigh) servov = servovLimitHigh;

      } else {

        servov--;

        if (servov < servovLimitLow) servov = servovLimitLow;

      }

      vertical.write(servov);

    }



      if (avl > avr) {

        servoh--;

        if (servoh < servohLimitLow) servoh = servohLimitLow;

      } else {

        servoh++;

        if (servoh > servohLimitHigh) servoh = servohLimitHigh;

      }

      horizontal.write(servoh);

    }



  }

  else {

    oldvalue = horizontal.read();

    oldvalue2 = vertical.read();



      horizontal.write(pos);

      delay(15);

    }

    for (pos2 = oldvalue2; pos2 >= 0; pos2--) {

      vertical.write(pos2);

      delay(15);

    }



    if (buttonStateB == LOW) {

      digitalWrite(motorA, LOW);

      digitalWrite(motorB, HIGH); // Reverse motor

    } else {

      digitalWrite(motorA, LOW);

      digitalWrite(motorB, LOW);

    }

  }

}

🔔 DON’T FORGET TO SUBSCRIBE TO D TREND FOR MORE AWESOME PROJECTS AND TECH CONTENT! 🔔


🎯 Build Your Own RFID Attendance System Using Arduino + ESP32 + Google Sheets

  🎯 Build Your Own RFID Attendance System Using Arduino + ESP32 + Google Sheets 📅 By Dinesh | Tech DIY Projects | May 2025     🚀 Intro...