#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <MFRC522.h>
// ===== PIN =====
#define RC522_SDA 3
#define RC522_RST 14
#define RC522_SCK 2
#define RC522_MOSI 13
#define RC522_MISO 12
#define BTN_BON 5
#define BTN_SETENGAH 6
#define BTN_EXTRA 7
#define BUZZER_PIN 4
// ===== OBJEK =====
LiquidCrystal_I2C lcd(0x27, 20, 4);
MFRC522 rfid(RC522_SS, RC522_RST);
// ===== DATA KARYAWAN (hardcode) =====
struct Karyawan {
String uid;
String nama;
String pangkat;
};
Karyawan daftarKaryawan[] = {
{"A1B2C3D4", "Budi Santoso", "Staff"},
{"E5F6G7H8", "Siti Rahayu", "Manager"},
{"I9J0K1L2", "Ahmad Fauzi", "Supervisor"}
};
int jumlahKaryawan = 3;
// ===== STATUS =====
String statusHariIni = "";
// ============================================================
// HELPER
// ============================================================
void beepOK() {
digitalWrite(BUZZER_PIN, HIGH);
delay(100);
digitalWrite(BUZZER_PIN, LOW);
}
void beepError() {
for (int i = 0; i < 3; i++) {
digitalWrite(BUZZER_PIN, HIGH);
delay(100);
digitalWrite(BUZZER_PIN, LOW);
delay(100);
}
}
void beepDouble() {
digitalWrite(BUZZER_PIN, HIGH); delay(80);
digitalWrite(BUZZER_PIN, LOW); delay(80);
digitalWrite(BUZZER_PIN, HIGH); delay(80);
digitalWrite(BUZZER_PIN, LOW);
}
void lcdClear() { lcd.clear(); }
void lcdPrint(int col, int row, String text) {
lcd.setCursor(col, row);
lcd.print(text);
}
void tampilIdle() {
lcdClear();
lcdPrint(0, 0, "=== HADIR PLUS ===");
lcdPrint(0, 1, "Tap kartu untuk");
lcdPrint(0, 2, "absensi...");
lcdPrint(0, 3, "V1.0 - Simulasi");
}
void tampilPesan(String baris0, String baris1 = "", String baris2 = "", String baris3 = "") {
lcdClear();
lcdPrint(0, 0, baris0);
lcdPrint(0, 1, baris1);
lcdPrint(0, 2, baris2);
lcdPrint(0, 3, baris3);
}
String bacaUID() {
if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return "";
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();
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
return uid;
}
Karyawan* cariKaryawan(String uid) {
for (int i = 0; i < jumlahKaryawan; i++) {
if (daftarKaryawan[i].uid == uid) return &daftarKaryawan[i];
}
return nullptr;
}
String tentukanStatus(String statusLama) {
// Simulasi jam — pakai millis sebagai jam dummy
int jamSimulasi = (millis() / 10000) % 24; // setiap 10 detik = 1 jam simulasi
if (statusLama.isEmpty()) {
return (jamSimulasi >= 8) ? "terlambat" : "masuk";
}
if (statusLama == "masuk" || statusLama == "terlambat") {
return "pulang";
}
return "";
}
// ============================================================
// SETUP
// ============================================================
void setup() {
Serial.begin(115200);
// Init pin
pinMode(BUZZER_PIN, OUTPUT);
pinMode(BTN_BON, INPUT_PULLUP);
pinMode(BTN_SETENGAH, INPUT_PULLUP);
pinMode(BTN_EXTRA, INPUT_PULLUP);
digitalWrite(BUZZER_PIN, LOW);
// Init LCD
Wire.begin(21, 22);
lcd.init();
lcd.backlight();
tampilPesan("HADIR PLUS", "Inisialisasi...");
delay(1000);
// Init SPI & RFID
SPI.begin(RC522_SCK, RC522_MISO, RC522_MOSI, RC522_SS);
rfid.PCD_Init();
tampilPesan("HADIR PLUS", "RFID OK!", "LCD OK!", "Siap digunakan...");
beepOK();
delay(1500);
tampilIdle();
Serial.println("[System] Hadir Plus V1 Siap");
}
// ============================================================
// LOOP
// ============================================================
void loop() {
// ===== CEK TOMBOL =====
if (digitalRead(BTN_BON) == LOW) {
delay(200); // debounce
tampilPesan("== MODE BON ==", "Fitur ini", "belum aktif", "di V1");
beepDouble();
delay(2000);
tampilIdle();
return;
}
if (digitalRead(BTN_SETENGAH) == LOW) {
delay(200);
tampilPesan("= SETENGAH HARI =", "Fitur ini", "belum aktif", "di V1");
beepDouble();
delay(2000);
tampilIdle();
return;
}
if (digitalRead(BTN_EXTRA) == LOW) {
delay(200);
tampilPesan("=== EXTRA ===", "Fitur ini", "belum aktif", "di V1");
beepDouble();
delay(2000);
tampilIdle();
return;
}
// ===== CEK RFID =====
String uid = bacaUID();
if (uid.length() == 0) return;
Serial.println("[RFID] UID: " + uid);
beepOK();
tampilPesan("Kartu terdeteksi", uid, "Mencari data...");
delay(500);
// Cari karyawan
Karyawan* k = cariKaryawan(uid);
if (k == nullptr) {
tampilPesan("KARTU TIDAK", "TERDAFTAR!", uid, "Hubungi admin");
beepError();
Serial.println("[RFID] Kartu tidak dikenal: " + uid);
delay(3000);
tampilIdle();
return;
}
// Tentukan status
String statusBaru = tentukanStatus(statusHariIni);
if (statusBaru.isEmpty()) {
tampilPesan(k->nama, "Sudah: " + statusHariIni, "Absensi ditolak", "");
beepError();
delay(2500);
tampilIdle();
return;
}
// Simpan status
statusHariIni = statusBaru;
// Tampilkan hasil
tampilPesan(
k->nama.substring(0, 20),
k->pangkat,
"Status: " + statusBaru,
"Waktu: " + String(millis() / 1000) + "s"
);
beepOK();
Serial.println("[Absen] " + k->nama + " - " + statusBaru);
delay(3000);
tampilIdle();