Community project

RFID-Triggered Timed Alarm System

katumbaianoff

Published July 14, 2026

Arduino5 components7 assembly steps
Remix this project

This project combines RFID card authentication with precise timekeeping to create a timed alarm system that triggers a 240V AC siren when an authorized card is scanned. The Arduino Uno coordinates an MFRC522 RFID reader, DS3231 real-time clock, I2C LCD display, and relay module to manage both the logic and high-voltage switching safely.

Builders will receive a complete wiring diagram showing all component connections, a detailed parts list with recommended suppliers, Arduino firmware with RFID authorization logic and alarm timing, and step-by-step assembly instructions. The guide emphasizes safe handling of high-voltage AC circuits and includes configuration steps for programming authorized card UIDs and alarm duration.

Wiring diagram

Interactive · read-only
Wiring diagram for RFID-Triggered Timed Alarm System

Pan and zoom to explore the wiring. Remix the project to edit it in your own workspace.

Parts list

Bill of materials
ComponentQtyNotes
MFRC522 RFID Module113.56 MHz RFID reader/writer module based on the NXP MFRC522 IC. Communicates over SPI and is commonly sold as an RC522 breakout with an onboard antenna.
Adafruit DS3231 Precision RTC Breakout1DS3231 precision real-time clock breakout with integrated TCXO and crystal for accurate timekeeping over I2C.
Relay Module (5V, 250V AC rated)1Single-channel 5V relay module with optocoupler isolation. DC control side: VCC, GND, IN. AC switched side: COM (Common), NO (Normally Open), NC (Normally Closed). Rated 10A/250V AC.
AC Siren Alarm (240V)1Mains-powered 240V AC siren alarm. Switched via relay module COM/NO terminals. Live mains feed enters relay COM; NO connects to siren Live terminal. Neutral connects directly to siren.
LCD 16x2 I2C116x2 character LCD display with I2C backpack

Assembly

7 steps
  1. Gather components and tools

    Collect all components: Arduino Uno, MFRC522 RFID module, DS3231 RTC breakout, 5V relay module (250V AC / 10A rated), 16x2 I2C LCD module, 240V AC siren alarm, breadboard or PCB, jumper wires, and a separate 12V or mains-rated enclosure for the AC side.

    • Tip: Check that your relay module is rated for at least 250V AC / 10A before connecting any mains wiring.
    • Never connect mains AC wiring until all low-voltage wiring is complete and verified.
  2. Power rails on breadboard

    Connect the Arduino Uno 5V pin to the breadboard positive rail and GND to the negative rail. Also run a separate wire from the Uno 3.3V pin — this is used exclusively for the RFID module VCC.

    • Tip: Label or colour-code your 3.3V and 5V rails to avoid accidentally powering the RFID module from 5V.
  3. Wire the MFRC522 RFID module

    Connect the RFID module using the SPI bus: - VCC → Uno 3.3V (NOT 5V — the MFRC522 is a 3.3V device) - GND → GND rail - SCK → D13 - MOSI → D11 - MISO → D12 - SDA (CS) → D10 - RST → D9

    • Tip: For best reliability, add a bidirectional logic-level converter on the 5 SPI lines (D9–D13) between the 5V Uno and the 3.3V RFID module.
    • Do NOT connect RFID VCC to 5V — it will damage the module.
  4. Wire the DS3231 RTC module

    Connect the RTC to the I2C bus: - VIN → 5V rail - GND → GND rail - SDA → A4 - SCL → A5

    • Tip: The DS3231 has a CR2032 coin cell slot — insert a fresh battery so it keeps time when the Uno is unpowered.
  5. Wire the I2C LCD (16x2)

    Connect the LCD I2C backpack to the same I2C bus as the RTC: - VCC → 5V rail - GND → GND rail - SDA → A4 (shared with RTC — just connect both to the same A4 wire/node) - SCL → A5 (shared with RTC — same node) The LCD default I2C address is 0x27. If the display shows nothing after power-on, adjust the contrast pot on the back of the I2C backpack with a small screwdriver.

    • Tip: Both the LCD and the RTC sit on the I2C bus simultaneously — this is normal and expected.
    • Tip: If your LCD has a different I2C address (e.g. 0x3F), change the address in the firmware: LiquidCrystal_I2C lcd(0x3F, 16, 2).
  6. Wire the relay module (low-voltage side)

    Connect the relay control side to the Uno: - VCC → 5V rail - GND → GND rail - IN → D8 Do NOT connect any AC wiring yet.

    • Tip: Most relay modules have an active-LOW or active-HIGH input — the firmware drives D8 HIGH to energise. Test with a multimeter across NO/COM before connecting AC.
  7. Wire the 240V AC siren (HIGH VOLTAGE — qualified personnel only)

    ⚠️ This step involves lethal mains voltage. Have a qualified electrician perform or inspect all AC wiring. With mains COMPLETELY DISCONNECTED: 1. Run the Mains LIVE wire into the relay's COM screw terminal. 2. Run a wire from the relay NO screw terminal to the Siren LIVE terminal. 3. Run the Mains NEUTRAL wire directly to the Siren NEUTRAL terminal (neutral is NOT switched through the relay). 4. Connect Mains EARTH (green-yellow) to the siren's earth terminal if present. 5. Enclose ALL AC terminals in an insulated, non-conductive enclosure — no bare mains wiring should be accessible. 6. Fit a fused mains inlet (rated for the siren's current draw) upstream of the relay COM terminal.

    • 240V AC is lethal. Never work on AC terminals with the mains plug connected.
    • Use relay module rated ≥ 10A / 250V AC (e.g. SRD-05VDC-SL-C).
    • Neutral goes DIRECTLY to the siren — only Live is switched by the relay.
    • All mains wiring must be enclosed in an approved insulated enclosure.
    • Never power on the AC side until the enclosure is fully closed and inspected.

Firmware

Arduino
firmware.cppDeploy to device
#include <Arduino.h>
// =====================================================================
//  RFID + RTC + Relay Siren Alarm + I2C LCD — Arduino Uno
//
//  LCD (16x2 I2C, address 0x27)  → A4 (SDA), A5 (SCL)  [shared with RTC]
//  RTC (DS3231, address 0x68)    → A4 (SDA), A5 (SCL)
//  RFID (MFRC522)                → SPI  D10/D11/D12/D13, RST D9
//  Relay                         → D8   (NO → 240V AC siren Live)
// =====================================================================

#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>

// ---- Pin Definitions ------------------------------------------------
#define RFID_SS_PIN   10
#define RFID_RST_PIN   9
#define RELAY_PIN      8

// ---- I2C Devices ----------------------------------------------------
// LCD  : 0x27  (PCF8574 I2C backpack, standard address)
// RTC  : 0x68  (DS3231 fixed address)
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS3231        rtc;
MFRC522           rfid(RFID_SS_PIN, RFID_RST_PIN);

// ---- Authorised UIDs ------------------------------------------------
// Replace the example UID with your card's actual UID (read from Serial Monitor)
const byte authorisedUID[][4] = {
  {0xDE, 0xAD, 0xBE, 0xEF}
};
const int numAuthorised = sizeof(authorisedUID) / sizeof(authorisedUID[0]);

// ---- Alarm timing ---------------------------------------------------
const unsigned long ALARM_DURATION_MS = 5000;
unsigned long alarmStartTime = 0;
bool alarmActive = false;

// ---- Forward declarations -------------------------------------------
bool isAuthorised(byte *uid, byte size);
void printDateTimeSerial();
void showDateTimeLCD();
void triggerAlarm();
void stopAlarm();
String uidString(byte *uid, byte size);

// =====================================================================
//  Helpers
// =====================================================================

String uidString(byte *uid, byte size) {
  String s = "";
  for (byte i = 0; i < size; i++) {
    if (uid[i] < 0x10) s += "0";
    s += String(uid[i], HEX);
    if (i < size - 1) s += ":";
  }
  s.toUpperCase();
  return s;
}

bool isAuthorised(byte *uid, byte size) {
  if (size != 4) return false;
  for (int i = 0; i < numAuthorised; i++) {
    if (memcmp(uid, authorisedUID[i], 4) == 0) return true;
  }
  return false;
}

void printDateTimeSerial() {
  DateTime now = rtc.now();
  Serial.print(now.year(),  DEC); Serial.print('/');
  Serial.print(now.month(), DEC); Serial.print('/');
  Serial.print(now.day(),   DEC); Serial.print("  ");
  Serial.print(now.hour(),  DEC); Serial.print(':');
  if (now.minute() < 10) Serial.print('0');
  Serial.print(now.minute(), DEC); Serial.print(':');
  if (now.second() < 10) Serial.print('0');
  Serial.print(now.second(), DEC);
}

// Show current date on LCD row 0, time on LCD row 1
void showDateTimeLCD() {
  DateTime now = rtc.now();

  // Row 0: DD/MM/YYYY
  lcd.setCursor(0, 0);
  if (now.day()   < 10) lcd.print('0'); lcd.print(now.day());
  lcd.print('/');
  if (now.month() < 10) lcd.print('0'); lcd.print(now.month());
  lcd.print('/');
  lcd.print(now.year());
  lcd.print("      ");   // clear trailing chars

  // Row 1: HH:MM:SS
  lcd.setCursor(0, 1);
  if (now.hour()   < 10) lcd.print('0'); lcd.print(now.hour());
  lcd.print(':');
  if (now.minute() < 10) lcd.print('0'); lcd.print(now.minute());
  lcd.print(':');
  if (now.second() < 10) lcd.print('0'); lcd.print(now.second());
  lcd.print("  Ready ");
}

void triggerAlarm() {
  Serial.print("[ALARM] Unauthorised card at ");
  printDateTimeSerial();
  Serial.println();

  digitalWrite(RELAY_PIN, HIGH);   // Energise relay → 240V siren ON
  alarmActive    = true;
  alarmStartTime = millis();

  // LCD: show alarm message
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("!! ALARM ACTIVE !!");
  lcd.setCursor(0, 1);
  lcd.print("ACCESS  DENIED  ");
}

void stopAlarm() {
  digitalWrite(RELAY_PIN, LOW);    // De-energise relay → siren OFF
  alarmActive = false;
  Serial.println("[ALARM] Alarm stopped. RFID reader ready.");

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Alarm Stopped   ");
  lcd.setCursor(0, 1);
  lcd.print("Scan Card...    ");
  delay(2000);
}

// =====================================================================
//  Setup
// =====================================================================
void setup() {
  Serial.begin(9600);
  while (!Serial);

  // Relay — start LOW (siren off)
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);

  // I2C
  Wire.begin();

  // LCD
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("RFID Alarm Sys  ");
  lcd.setCursor(0, 1);
  lcd.print("Initialising... ");
  delay(1500);

  // RTC
  if (!rtc.begin()) {
    Serial.println("ERROR: DS3231 RTC not found!");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("RTC ERROR!      ");
    lcd.setCursor(0, 1);
    lcd.print("Check I2C wiring");
    while (1);
  }
  if (rtc.lostPower()) {
    Serial.println("RTC lost power - setting to compile time.");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  // SPI & RFID
  SPI.begin();
  rfid.PCD_Init();
  Serial.print("RFID firmware: ");
  rfid.PCD_DumpVersionToSerial();

  // Ready
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("System  Ready   ");
  lcd.setCursor(0, 1);
  lcd.print("Scan Card...    ");
  delay(1000);

  Serial.println("System ready. Waiting for RFID card...");
}

// =====================================================================
//  Loop
// =====================================================================

// Update LCD clock every second
unsigned long lastClockUpdate = 0;

void loop() {
  // ---- Manage active alarm ----------------------------------------
  if (alarmActive) {
    if (millis() - alarmStartTime >= ALARM_DURATION_MS) {
      stopAlarm();
    }
    return;
  }

  // ---- Refresh clock on LCD every second --------------------------
  if (millis() - lastClockUpdate >= 1000) {
    showDateTimeLCD();
    lastClockUpdate = millis();
  }

  // ---- Poll for RFID card -----------------------------------------
  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) {
    return;
  }

  // Print UID to Serial
  String uid = uidString(rfid.uid.uidByte, rfid.uid.size);
  Serial.print("Card UID: ");
  Serial.print(uid);
  Serial.print("  at ");
  printDateTimeSerial();
  Serial.println();

  if (isAuthorised(rfid.uid.uidByte, rfid.uid.size)) {
    Serial.println("Access GRANTED.");

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Access GRANTED  ");
    lcd.setCursor(0, 1);
    lcd.print(uid);
    delay(2000);

  } else {
    Serial.println("Access DENIED - triggering siren alarm!");
    triggerAlarm();
  }

  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
}

“Deploy to device” opens this project in Schematik, where you can flash it to your board over USB.

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik