Zum Hauptinhalt springen Zur Suche springen Zur Hauptnavigation springen
Menü

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

  1. yourDroid UNO R3 Entwicklungsboard ATMEGA328P-PU arduino kompatibel
  2. Datalogger Shield für Arduino mit RTC
  3. RFID Set MFRC522 - Kartenleser + Mifare Transponder/Karte
  4. 1.3" OLED Display I2C/IIC/TWI 128x64 Pixel für Arduino
  5. Aktiver Buzzer 3,3V-5V
  6. Drucktaster Button Schalter Rot 12mm 250V 1A
  7. Drucktaster Button Schalter Grün 12mm 250V 1A
  8. 40 Pin Dupont / Jumper Kabel Buchse-Stecker 10 cm
  9. Ein 3D-gedrucktes Gehäuse TIMETRACKERPQQMQh97MkH7l
  10. Eine SD Karte

Produktgalerie überspringen
UNO R3 ATMega328P CH340G UNO R3 Mega328P CH340G

Durchschnittliche Bewertung von 4.83 von 5 Sternen

(35)
UNO R3 ATMega328P CH340G
RBS10053

Sofort verfügbar

Regulärer Preis: 4,95 €
Data Logger Shield für Arduino mit RTC Data Logger Shield für Arduino mit RTC

Durchschnittliche Bewertung von 4.5 von 5 Sternen

(5)
Datalogger Shield für Arduino mit RTC
RBS10357

Sofort verfügbar

Regulärer Preis: Ab 2,95 €
RFID Set MFRC522 - Kartenleser + Mifare Transponder/Karte RFID Set MFRC522 - Kartenleser + Mifare Transponder/Karte

Durchschnittliche Bewertung von 5 von 5 Sternen

(6)
RFID Set MFRC522 - Kartenleser + Mifare Transponder/Karte
RBS10027

Derzeit nicht verfügbar

Regulärer Preis: Ab 2,49 €
OLED Display I2C/IIC/TWI 128x64 Pixel für Arduino OLED Display I2C/IIC/TWI 128x64 Pixel für Arduino

Durchschnittliche Bewertung von 4.93 von 5 Sternen

(7)
1.3" OLED Display I2C/IIC/TWI 128x64 Pixel für Arduino
RBS11084

Sofort verfügbar

Regulärer Preis: Ab 6,85 €
10 Stück Aktiver Buzzer 3,3V-5V 10 Stück Aktiver Buzzer 3,3V-5V

Durchschnittliche Bewertung von 5 von 5 Sternen

(23)
10 Stück Aktiver Buzzer 3,3V-5V
RBS12914

Sofort verfügbar

Inhalt: 10 Stück (0,26 € / 1 Stück)

Regulärer Preis: Ab 2,55 €
Drucktaster Button Schalter Rot 12mm 250V 1A Drucktaster Button Schalter Rot 12mm 250V 1A

Durchschnittliche Bewertung von 4.75 von 5 Sternen

(6)
Drucktaster Button Schalter Rot 12mm 250V 1A
RBS13866

Sofort verfügbar

Regulärer Preis: Ab 0,65 €
Drucktaster Button Schalter Grün 12mm 250V 1A Drucktaster Button Schalter Grün 12mm 250V 1A

Durchschnittliche Bewertung von 5 von 5 Sternen

(1)
Drucktaster Button Schalter Grün 12mm 250V 1A
RBS13869

Sofort verfügbar

Regulärer Preis: Ab 0,65 €
Tipp
40 Pin Dupont / Jumper Kabel Buchse-Buchse 20 cm

Durchschnittliche Bewertung von 4.97 von 5 Sternen

(35)
40 Pin Dupont / Jumper Kabel Buchse-Buchse 20 cm
RBS10136

Sofort verfügbar

Regulärer Preis: Ab 0,69 €

Aufbau
Verkabelung

1. Arduino UNO R3: Verbinde das Arduino-Board mit Ihrem Computer über ein USB-Kabel.
2. Datalogger Shield: Stecke 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


5. Buzzer:

  • VCC -> Pin 4
  • GND -> GND


Drucktaster:

  • Roter Taster (gehen) -> Pin 3 und GND
  • Grüner Taster (kommen) -> Pin 2 und GND

zum Vergrößern auf Bilder klicken

Programmierung

Lade den folgenden Code auf dein Arduino-Board: TIMETRACKER.ino

Codes anzeigen / einklappen

1. Hauptcode: RFID-Zeiterfassung

#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!"));
    while (1);
  } 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 auf Kompilierzeit eingestellt!"));
  } else {
    Serial.println(F("RTC bereit und Uhrzeit korrekt!"));
  }

  // SD-Karte starten
  if (!SD.begin(DatenPin)) {
    Serial.println(F("Initialisierung der SD-Karte 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()) {
    return;
  }

  // Wenn kein RFID-Sender ausgewählt wurde
  if (!mfrc522.PICC_ReadCardSerial()) {
    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
  */
  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
  */
  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
    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!"));
}

2. RTC-Modul separat einrichten & testen

#include <Wire.h>
#include <RTClib.h>

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
}