Badge Check-In Station
The MFRC522v2 library, demonstrated properly. Where the Coffee Card and Arcade Token demos use the classic miguelbalboa MFRC522 API, this attendance station is written against the OSSLibraries MFRC522v2 rewrite: chip-select lives in a MFRC522DriverPinSimple, the bus in a MFRC522DriverSPI, the reader brace-initializes around the driver (no RST pin - v2 never drives reset), and the debug helpers are static MFRC522Debug:: calls. Every badge UID is packed into a 32-bit code and logged to an in-RAM roster: first tap checks you in with a green LED and a running head-count on the OLED, a repeat tap flags ALREADY IN with the red LED, and the button wipes the roster to start a fresh session.
// Badge Check-In Station - built on MFRC522v2, the modern rewrite of the
// classic miguelbalboa RFID library. The v2 API looks different on purpose:
// instead of MFRC522 rfid(SS_PIN, RST_PIN) you compose driver objects -
// a pin driver for chip-select, an SPI bus driver wrapping it, and the
// reader wrapping the bus (brace initialization, no RST pin: v2 never
// drives reset, so the module RST pin is simply tied high). All the debug
// helpers moved into the static MFRC522Debug class, which is why this
// sketch calls MFRC522Debug::PCD_DumpVersionToSerial and
// MFRC522Debug::PrintUID instead of methods on the reader object.
//
// The station keeps an attendance roster in RAM: every badge UID is packed
// into a 32-bit code, first tap checks you in (green LED + running count),
// tapping again flags a duplicate (red LED). The button starts a fresh
// session and clears the roster. Tap card A and card B to see both paths.
#include <SPI.h>
#include <MFRC522v2.h>
#include <MFRC522DriverSPI.h>
#include <MFRC522DriverPinSimple.h>
#include <MFRC522Debug.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define LED_OK 4 // green: checked in
#define LED_DUP 2 // red: already checked in / roster full
#define BTN_RESET 14 // start a new session (clears the roster)
#define ROSTER_MAX 16
MFRC522DriverPinSimple ss_pin(5); // chip-select on GPIO 5
MFRC522DriverSPI driver{ss_pin}; // v2 style: the driver owns the SPI bus
MFRC522 reader{driver}; // the reader wraps the driver
Adafruit_SSD1306 display(128, 64, &Wire, -1);
unsigned long roster[ROSTER_MAX];
int checkedIn = 0;
int lastBtn = 1;
void showScreen(const char* line1, const char* line2) {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("BADGE STATION in:");
display.print(checkedIn);
display.setTextSize(2);
display.setCursor(0, 16);
display.print(line1);
display.setTextSize(1);
display.setCursor(0, 40);
display.print(line2);
display.setCursor(0, 54);
display.print("Button = new session");
display.display();
}
void setup() {
Serial.begin(115200);
pinMode(LED_OK, OUTPUT);
pinMode(LED_DUP, OUTPUT);
pinMode(BTN_RESET, INPUT_PULLUP);
SPI.begin();
reader.PCD_Init();
MFRC522Debug::PCD_DumpVersionToSerial(reader, Serial);
Wire.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
showScreen("CHECK-IN", "Tap your badge");
Serial.println("Check-in station ready - tap a badge");
}
void loop() {
int btn = digitalRead(BTN_RESET);
if (btn == 0 && lastBtn == 1) {
checkedIn = 0;
Serial.println("Roster cleared - new session started");
showScreen("NEW SESSION", "Tap your badge");
}
lastBtn = btn;
if (!reader.PICC_IsNewCardPresent()) {
delay(50);
return;
}
if (!reader.PICC_ReadCardSerial()) {
delay(50);
return;
}
// Pack the badge UID into one 32-bit code for the roster.
unsigned long code = 0;
for (byte i = 0; i < reader.uid.size; i++) {
code = (code << 8) | reader.uid.uidByte[i];
}
Serial.print("Badge");
MFRC522Debug::PrintUID(Serial, reader.uid);
bool already = false;
for (int i = 0; i < checkedIn; i++) {
if (roster[i] == code) already = true;
}
if (already) {
digitalWrite(LED_DUP, HIGH);
Serial.println(" -> ALREADY CHECKED IN");
showScreen("ALREADY IN", "Badge seen before");
} else if (checkedIn < ROSTER_MAX) {
roster[checkedIn] = code;
checkedIn = checkedIn + 1;
digitalWrite(LED_OK, HIGH);
Serial.print(" -> CHECKED IN #");
Serial.println(checkedIn);
showScreen("WELCOME!", "You are on the list");
} else {
digitalWrite(LED_DUP, HIGH);
Serial.println(" -> ROSTER FULL - press the button");
showScreen("ROSTER FULL", "Press new session");
}
reader.PICC_HaltA();
reader.PCD_StopCrypto1();
delay(700);
digitalWrite(LED_OK, LOW);
digitalWrite(LED_DUP, LOW);
}Built with FluxBench.AI — the AI workbench for embedded projects.