Digitale Zeiterfassung mit Arduino
In diesem DIY-Projekt werden wir ein digitales Zeiterfassungssystem bauen. Mit Hilfe eines Arduino-Boards und verschiedenen Komponenten wie einem RFID-Leser, einem OLED-Display und einem Datalogger-Shield mit RTC (Echtzeituhr) können wir die An- und Abwesenheitszeiten von Mitarbeitern erfassen und speichern.
Verwendete Bauteile
- yourDroid UNO R3 Entwicklungsboard ATMEGA328P-PU arduino kompatibel
- Datalogger Shield für Arduino mit RTC
- RFID Set MFRC522 - Kartenleser + Mifare Transponder/Karte
- 1.3" OLED Display I2C/IIC/TWI 128x64 Pixel für Arduino
- Aktiver Buzzer 3,3V-5V
- Drucktaster Button Schalter Rot 12mm 250V 1A
- Drucktaster Button Schalter Grün 12mm 250V 1A
- 40 Pin Dupont / Jumper Kabel Buchse-Stecker 10 cm
- Ein 3D-gedrucktes Gehäuse TIMETRACKERPQQMQh97MkH7l
- Eine SD Karte
Aufbau
Verkabelung
1. Arduino UNO R3: Verbinden Sie das Arduino-Board mit Ihrem Computer über ein USB-Kabel.
2. Datalogger Shield: Stecken Sie das Datalogger Shield auf das Arduino-Board.
3. RFID-Leser:
- SDA -> Pin 7
- SCK -> Pin 13
- MOSI -> Pin 11
- MISO -> Pin 12
- IRQ -> Nicht verbunden
- GND -> GND
- RST -> Pin 9
- 3.3V -> 3.3V
4. OLED Display:
- VCC -> 5V
- GND -> GND
- SDA -> A4
- SCL -> A5
- VCC -> Pin 4
- GND -> GND
Drucktaster:
- Roter Taster (gehen) -> Pin 3 und GND
- Grüner Taster (kommen) -> Pin 2 und GND
Programmierung
Laden Sie den folgenden Code auf Ihr Arduino-Board: TIMETRACKER.ino
Code anzeigen / einklappen
#include "MFRC522.h"
#include "SPI.h"
#include "SdFat.h"
#include "RTClib.h"
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
// Name des RTC-Moduls
RTC_DS3231 rtc;
// Adressierung des OLED-Displays
#define I2C_ADDRESS 0x3C
// Buttons definieren
#define greenButton 2
#define redButton 3
// RFID Anschlüsse definieren
#define SDA 7
#define RST 9
// Name des OLED-Displays
SSD1306AsciiWire oled;
// Bezeichnung der SD-Karte
SdFat SD;
// Bezeichnung der CSV-Datei
File Zeiterfassung;
// RFID-Empfänger benennen und Pins zuordnen
MFRC522 mfrc522(SDA, RST);
// Pin der SD-Karte
int DatenPin = 10;
// Pin des Buzzer
int buzzer = 4;
// Wert zum Auslesen der Aktivität
int ButtonValue = 0;
// Variable zum Verfolgen der RFID-Aktivität
bool rfidGelesen = false;
// Trennzeichen für die CSV-Datei
const String TrennZeichen = ",";
String Mitarbeiter;
void setup() {
Serial.begin(9600);
SPI.begin();
// OLED mit 128x64 Pixeln starten
Wire.begin();
oled.begin(&Adafruit128x64, I2C_ADDRESS);
// Schriftart festlegen
oled.setFont(Arial14);
oled.println(F(" kommen gehen"));
oled.println(F(" "));
oled.println(F(" Zur Zeiterfassung"));
oled.println(F(" Taste druecken!"));
// Initialisierung des RFID-Empfängers
mfrc522.PCD_Init();
// Buttons als Input deklarieren
pinMode(greenButton, INPUT_PULLUP);
pinMode(redButton, INPUT_PULLUP);
// Buzzer als Output deklarieren
pinMode(buzzer, OUTPUT);
// RTC-Modul starten
if (!rtc.begin()) {
Serial.println(F("RTC Initialisierung fehlgeschlagen!"));
} else if (rtc.lostPower()) {
// Setze die Uhrzeit nur, wenn die RTC ihre Zeit verloren hat
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
Serial.println(F("RTC Uhrzeit eingestellt!"));
} else {
Serial.println(F("RTC bereit und Uhrzeit korrekt!"));
}
// SD-Karte starten
if (!SD.begin(DatenPin)) {
Serial.println(F("Initialisierung fehlgeschlagen!"));
} else {
Serial.println(F("SD-Karte gestartet!"));
}
// rtc.now() -> aktuelle Zeit holen
DateTime aktuell = rtc.now();
// Format des Datums festlegen
char Datum[] = "DD.MM.YYYY";
// Datum in String umwandeln und anzeigen
Serial.print(aktuell.toString(Datum));
// Format der Zeitangabe festlegen
char Zeit[] = "hh:mm:ss";
// Zeitangabe in String umwandeln und anzeigen
Serial.print(aktuell.toString(Zeit));
}
void loop() {
// Wenn grüner Button gedrückt wird
if (digitalRead(greenButton) == LOW) {
oled.clear();
oled.println(F(" kommen"));
oled.println(F(" "));
oled.println(F(" Karte an das"));
oled.println(F(" Lesegeraet halten!"));
ButtonValue = 1; // Setze ButtonValue auf 1
digitalWrite(buzzer, HIGH); // Ton an
delay(100);
digitalWrite(buzzer, LOW); // Ton aus
delay(1000);
rfidGelesen = true; // Erlaube das Lesen des RFID-Chips
}
// Wenn roter Button gedrückt wird
if (digitalRead(redButton) == LOW) {
oled.clear();
oled.println(F(" gehen"));
oled.println(F(" "));
oled.println(F(" Karte an das"));
oled.println(F(" Lesegeraet halten!"));
ButtonValue = 2; // Setze ButtonValue auf 2
digitalWrite(buzzer, HIGH); // Ton an
delay(100);
digitalWrite(buzzer, LOW); // Ton aus
delay(1000);
rfidGelesen = true; // Erlaube das Lesen des RFID-Chips
}
// Wenn RFID-Chip noch nicht gelesen wurde und einer der Buttons gedrückt wurde
if (rfidGelesen == false) {
return; // Warte auf Button-Druck
}
// vom RFID ermittelter Wert der Karte als Folge von Dezimalzahlen
String WertDEZ;
// String Mitarbeiter löschen, damit falsche Karte erkannt wird
Mitarbeiter = "";
// Wenn keine Karte in Reichweite ist
if (!mfrc522.PICC_IsNewCardPresent()) {
// wird die Abfrage wiederholt.
return;
}
// Wenn kein RFID-Sender ausgewählt wurde
if (!mfrc522.PICC_ReadCardSerial()) {
// wird die Abfrage wiederholt.
return;
}
Serial.println(F("Karte entdeckt!"));
digitalWrite(buzzer, HIGH); // Ton an
delay(100);
digitalWrite(buzzer, LOW); // Ton aus
delay(1000);
// Dezimal-Werte in String WertDEZ schreiben
for (byte i = 0; i < mfrc522.uid.size; i++) {
WertDEZ = WertDEZ + String(mfrc522.uid.uidByte[i], DEC) + " ";
}
// dezimalen Wert anzeigen
Serial.println("Wert in dezimal: " + WertDEZ);
// Leerzeichen am Ende entfernen
WertDEZ.trim();
/*
Karten abfragen und Namen der Mitarbeiter*innen zuordnen
Dezimal-Werte durch Namen
*/
if (WertDEZ == "227 211 219 29") Mitarbeiter = " Max Mustermann";
if (WertDEZ == "147 50 48 28") Mitarbeiter = " Maxi Musterfrau";
// Namen abfragen
if (Mitarbeiter == " Max Mustermann" || Mitarbeiter == " Maxi Musterfrau") {
// Daten in die Datei schreiben
DatenSchreiben();
}
// bei falscher Karte
else {
Serial.println(F("Falsche Karte!"));
oled.clear();
oled.print(F(" Falsche Karte!"));
delay(2000);
oled.clear();
oled.println(F(" kommen gehen"));
oled.println(F(" "));
oled.println(F(" Zur Zeiterfassung"));
oled.println(F(" Taste druecken!"));
ButtonValue = 0;
rfidGelesen = false;
}
// Pause, damit die Daten nicht mehrfach geschrieben werden
delay(2000);
}
void DatenSchreiben() {
// Meldungen im Seriellen Monitor
Serial.println(F("Schreibe Daten in Zeiterfassung.csv ... "));
// Name der Mitarbeiter*in
Serial.println("Mitarbeiter*in: " + Mitarbeiter);
Serial.println(F("-----------------------------"));
// rtc.now() -> aktuelle Zeit holen
DateTime aktuell = rtc.now();
char Datum[] = "DD.MM.YYYY ";
// Datum in String umwandeln und anzeigen
Serial.print(aktuell.toString(Datum));
// Format der Zeitangabe festlegen
char Zeit[] = "hh:mm:ss";
// Zeitangabe in String umwandeln und anzeigen
Serial.println(aktuell.toString(Zeit));
// Ausgabe OLED
oled.clear();
oled.println(Mitarbeiter);
oled.println(aktuell.toString(Datum));
oled.println(aktuell.toString(Zeit));
delay(2000);
oled.clear();
oled.print(F(" Gespeichert!"));
delay(2000);
// Reset für den nächsten Durchlauf
rfidGelesen = false;
/*
FILE_WRITE - Datei zum Schreiben öffnen
wenn die Datei noch nicht existiert, wird sie neu erstellt
ansonsten werden neuen Daten ans Ende angehängt
*/
Zeiterfassung = SD.open("Zeiterfassung.csv", FILE_WRITE);
if (Zeiterfassung) {
// Überschrift nach jedem Datensatz wiederholen
Zeiterfassung.print(F("Mitarbeiter*in:"));
Zeiterfassung.print(TrennZeichen);
Zeiterfassung.print(F("Datum:"));
Zeiterfassung.print(TrennZeichen);
Zeiterfassung.print(F("Zeit"));
Zeiterfassung.print(TrennZeichen);
Zeiterfassung.print(F("Aktion"));
Zeiterfassung.println();
// Daten in die Datei schreiben: Mitarbeiter*in, Datum, Zeit und Aktion
// Werte durch Trennzeichen (,) trennen
Zeiterfassung.print(Mitarbeiter);
Zeiterfassung.print(TrennZeichen);
Zeiterfassung.print(Datum);
Zeiterfassung.print(TrennZeichen);
Zeiterfassung.print(Zeit);
Zeiterfassung.print(TrennZeichen);
if (ButtonValue == 1) {
Zeiterfassung.print(F("kommen"));
} else if (ButtonValue == 2) {
Zeiterfassung.print(F("gehen"));
}
Zeiterfassung.println();
Zeiterfassung.println();
}
// Datei schließen
Zeiterfassung.close();
Serial.println(F("Speichern abgeschlossen."));
Serial.println();
delay(200);
// Reset für den nächsten Durchlauf
ButtonValue = 0;
oled.clear();
oled.println(F(" kommen gehen"));
oled.println(F(" "));
oled.println(F(" Zur Zeiterfassung"));
oled.println(F(" Taste druecken!"));
}
#include #include
RTC_DS3231 rtc;
void setup() { Serial.begin(9600); Wire.begin(); if (!rtc.begin()) { Serial.println("RTC konnte nicht gefunden werden!"); while (1); }
// RTC auf das Kompilierdatum und -zeit einstellen rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); Serial.println("RTC erfolgreich auf das Kompilierdatum und -zeit eingestellt!");}
void loop() { // Hier können weitere Anweisungen eingefügt werden}