DIY-Projekt zur digitalen Zeiterfassung mit Arduino
Einleitung
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 (die .stl-Datei wird bereitgestellt)
- Eine SD Karte
Aufbau
Verkabelung
- Arduino UNO R3: Verbinden Sie das Arduino-Board mit Ihrem Computer über ein USB-Kabel.
- Datalogger Shield: Stecken Sie das Datalogger Shield auf das Arduino-Board.
- 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
- OLED Display:
- VCC -> 5V
- GND -> GND
- SDA -> A4
- SCL -> A5
- Buzzer:
- VCC -> Pin 4
- GND -> GND
- Drucktaster:
- Roter Taster (gehen) -> Pin 3 und GND
- Grüner Taster (kommen) -> Pin 2 und GND
Gehäuse
Drucken Sie das Gehäuse mit einem 3D-Drucker. Die .stl-Datei können Sie hier herunterladen: TIMETRACKERPQQMQh97MkH7l
Programmierung
Laden Sie den folgenden Code auf Ihr Arduino-Board: TIMETRACKER.ino
/#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!")); }
|
Anleitungsvideo mit Funktion
#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}