RFID time clock with an LCD and a DS1307 on an Arduino Uno
Swipe a card on an RC522 (SS 10, RST A1) to clock in: the LCD names the person, a DS1307 stamps the time, and a line goes to the serial monitor. A button on A0 enrolls cards. The whole build, an Arduino Uno and 5 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Advanced Runs in your browser. Free, and no account needed.
The parts retail for about $40. On Mokxi they're free.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// RFID time clock: swipe a card to clock in, and the board logs who and when.
//
// LCD RS -> pin 2 E -> A3 D4 -> pin 8 D5 -> pin 7 D6 -> A2 D7 -> pin 4
// RC522 SDA (SS) -> pin 10 SCK -> 13 MOSI -> 11 MISO -> 12
// RST -> A1 3.3V -> 3.3V GND -> GND
// DS1307 clock SDA -> A4, SCL -> A5
// mode button -> A0, to GND (INPUT_PULLUP) passive buzzer -> pin 3
//
// The LCD shows the date and the time. Press the button to switch to
// enrolling: each new card you hold to the reader takes the next name from
// the list below. Press it again to go back. From then on, a known card shows
// its name and sends a line to the serial monitor:
//
// $card,name,date,time%
//
// The $ and % mark where each record starts and ends, so a program on the
// computer can pick them out of the stream and save them as a spreadsheet.
// Change the names before you upload it to your own board.
#include <Wire.h>
#include <SPI.h>
#include <MFRC522.h>
#include <RTClib.h>
#include <LiquidCrystal.h>
const int SS_PIN = 10;
const int RST_PIN = A1;
const int BUTTON = A0;
const int BUZZER = 3;
const int PEOPLE = 6;
const char *NAMES[PEOPLE] = {"Ada", "Ben", "Cleo", "Dev", "Esme", "Femi"};
MFRC522 reader(SS_PIN, RST_PIN);
RTC_DS1307 rtc;
LiquidCrystal lcd(2, A3, 8, 7, A2, 4); // RS, E, D4, D5, D6, D7
unsigned long cards[PEOPLE];
int enrolled = 0;
bool enrolling = false;
bool buttonWas = false;
unsigned long buttonAt = 0;
unsigned long lastShown = 0;
unsigned long messageUntil = 0;
void print2(Print &out, int value) {
if (value < 10) out.print('0');
out.print(value);
}
void printDate(Print &out, const DateTime &t) {
out.print(t.year());
out.print('-');
print2(out, t.month());
out.print('-');
print2(out, t.day());
}
void printTime(Print &out, const DateTime &t) {
print2(out, t.hour());
out.print(':');
print2(out, t.minute());
out.print(':');
print2(out, t.second());
}
// The card's first four ID bytes as one number.
unsigned long cardId() {
unsigned long id = 0;
for (byte i = 0; i < 4 && i < reader.uid.size; i++) id = id << 8 | reader.uid.uidByte[i];
return id;
}
int personOf(unsigned long id) {
for (int i = 0; i < enrolled; i++) {
if (cards[i] == id) return i;
}
return -1;
}
void message(const char *top, const char *bottom) {
lcd.clear();
lcd.print(top);
lcd.setCursor(0, 1);
lcd.print(bottom);
messageUntil = millis() + 2000;
}
void showMode() {
if (enrolling) {
message("Enrolling", "Hold up a card");
messageUntil = 0;
Serial.println("enrolling: hold up a card");
} else {
Serial.println("clocking: hold up a card");
lastShown = 0;
}
}
void showClock() {
DateTime now = rtc.now();
lcd.clear();
printDate(lcd, now);
lcd.setCursor(0, 1);
printTime(lcd, now);
}
void swiped(unsigned long id) {
int who = personOf(id);
if (enrolling) {
if (who >= 0) {
message(NAMES[who], "already enrolled");
} else if (enrolled < PEOPLE) {
cards[enrolled] = id;
message(NAMES[enrolled], "enrolled");
Serial.print("enrolled ");
Serial.println(NAMES[enrolled]);
enrolled++;
tone(BUZZER, 880, 200);
} else {
message("The list is full", "");
}
return;
}
if (who < 0) {
message("Unknown card", "Enroll it first");
Serial.println("unknown card");
tone(BUZZER, 110, 400);
return;
}
DateTime now = rtc.now();
message(NAMES[who], "clocked in");
tone(BUZZER, 1047, 150);
Serial.print('$');
Serial.print(id, HEX);
Serial.print(',');
Serial.print(NAMES[who]);
Serial.print(',');
printDate(Serial, now);
Serial.print(',');
printTime(Serial, now);
Serial.println('%');
}
void setup() {
pinMode(BUTTON, INPUT_PULLUP);
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("Starting up..");
SPI.begin();
reader.PCD_Init();
if (!rtc.begin()) Serial.println("no clock found: check SDA and SCL");
if (!rtc.isrunning()) rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
Serial.println("Mokxi Uno: RFID time clock. The button on A0 switches to enrolling.");
showMode();
}
void loop() {
bool down = digitalRead(BUTTON) == LOW;
if (down != buttonWas && millis() - buttonAt > 30) {
buttonWas = down;
buttonAt = millis();
if (down) {
enrolling = !enrolling;
showMode();
}
}
if (reader.PICC_IsNewCardPresent() && reader.PICC_ReadCardSerial()) {
swiped(cardId());
reader.PICC_HaltA();
}
if (!enrolling && millis() > messageUntil && millis() - lastShown >= 1000) {
lastShown = millis();
showClock();
}
}
Parts list
7 parts, plus the jumper wires. They retail for about $40; on Mokxi they're free.
How it is wired
18 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Arduino Uno R3 pin 13; RFID reader, MFRC522 pin SCK
- Arduino Uno R3 pin 12; RFID reader, MFRC522 pin MISO
- Arduino Uno R3 pin 11; RFID reader, MFRC522 pin MOSI
- Arduino Uno R3 pin 10; RFID reader, MFRC522 pin SDA
- Arduino Uno R3 pin 8; Character LCD, 16x2 pin D4
- Arduino Uno R3 pin 7; Character LCD, 16x2 pin D5
- Arduino Uno R3 pin 4; Character LCD, 16x2 pin D7
- Arduino Uno R3 pin 3; Piezo speaker pin 1
- Arduino Uno R3 pin 2; Character LCD, 16x2 pin RS
- Arduino Uno R3 pin 3V3; RFID reader, MFRC522 pin 3.3V
- Arduino Uno R3 pin 5V; Character LCD, 16x2 pin VDD; Character LCD, 16x2 pin A; Real-time clock, DS1307 pin VCC
- Ground: Arduino Uno R3 pin GND; Character LCD, 16x2 pin VSS; Character LCD, 16x2 pin V0; Character LCD, 16x2 pin RW; Character LCD, 16x2 pin K; RFID reader, MFRC522 pin GND; Real-time clock, DS1307 pin GND; Pushbutton pin 2a; Piezo speaker pin 2
- Arduino Uno R3 pin A0; Pushbutton pin 1a
- Arduino Uno R3 pin A1; RFID reader, MFRC522 pin RST
- Arduino Uno R3 pin A2; Character LCD, 16x2 pin D6
- Arduino Uno R3 pin A3; Character LCD, 16x2 pin E
- Arduino Uno R3 pin A4; Real-time clock, DS1307 pin SDA
- Arduino Uno R3 pin A5; Real-time clock, DS1307 pin SCL
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.