Zeit­er­fas­sung mit RFID-Modul

Lese­zeit: 7 Minu­ten

Lösung
Seite als PDF

Mit einem RFID-Modul, einem RTC-Modul und einer SD-Kar­te sol­len Datum, Zeit und der Name der Mitarbeiterin/des Mit­ar­bei­ters erfasst wer­den und auf einer SD-Kar­te gespei­chert werden.

Außer­dem wer­den die Daten im Seri­el­len Moni­tor und auf einem OLED-Dis­play angezeigt.

So sieht es aus:

Ein RFID-Modul (radio-fre­quen­cy iden­ti­fi­ca­ti­on) besteht aus soge­nann­ten „Tags“, und einem Lesegerät.

Ein Daten­log­ger-Shield ver­ein­facht die Ver­ka­be­lung. Das Shield bie­tet ein Modul zur Zeit­er­fas­sung (RTC-Modul: Real Time Clock) und eine SD-Kar­te. Es wird ein­fach auf den Ardui­no aufgesteckt.

Die Daten wer­den im CSV-Format(Comma-separated values) gespei­chert. Die Daten – hier der Name der Mitarbeiterin/des Mit­ar­bei­ters, das Datum und die Uhr­zeit wer­den durch Kom­mas getrennt, anschlie­ßend folgt ein Zei­len­vor­schub (println). Jede Tabel­len­kal­ku­la­ti­on kann die Daten lesen. Beim Öff­nen der Datei wird gefragt, wel­ches Trenn­zei­chen ver­wen­det wer­den soll:
Bei­spiel: Import Libre­Of­fice Calc

Benö­tig­te Bauteile:

  • RFID-Modul
  • Daten­log­ger-Shield
  • OLED-Dis­play
  • kodier­te Karten
  • Lei­tungs­dräh­te

Baue die Schal­tung auf.

(Fah­re mit der Maus über das Bild, um die Bezeich­nun­gen der Bau­tei­le zu sehen)

Benö­tig­te Bibliotheken:

Sketch → Biblio­thek ein­bin­den → Biblio­the­ken verwalten

Zunächst musst du die indi­vi­du­el­le Ken­nung der Kar­te mit die­sem Pro­gramm herausfinden.

Die Ken­nung wird im Seri­el­len Moni­tor angezeigt.

// RFID-Bibiothek hinzufügen
# include "MFRC522.h"

// Anschlüsse definieren
# define SDA 7
# define RST 9

// RFID-Empfänger benennen
MFRC522 mfrc522(SDA, RST);

void setup()
{
  Serial.begin(9600);
  SPI.begin();

  // Initialisierung des RFID-Empfängers
  mfrc522.PCD_Init();
}

void loop()
{
  String WertDEZ;

  // 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!"));

  // Dezimal-Werte in String schreiben
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    WertDEZ = WertDEZ + String(mfrc522.uid.uidByte[i], DEC) + " ";
  }

  // Kennung dezimal anzeigen
  Serial.println("Wert in dezimal: " + WertDEZ);

  delay(1000);
}

Das eigent­li­che Pro­gramm

Um den knap­pen Spei­cher­platz im ➨SRAM des Ardui­no UNO zu spa­ren, wird jede Serial.print() oder Serial.println() Anwei­sung, die unver­än­der­li­chen, in Anfüh­rungs­zei­chen ein­ge­schlos­se­nen Text ent­hält, mit dem F-Makro aus­ge­führt. Das F-Makro sorgt dafür, dass der Text im Pro­gramm­spei­cher (➨Flash) abge­legt wird und so mehr Spei­cher­platz im SRAM zur Ver­fü­gung stellt.

// benötigte Bibliotheken einbinden
# include "MFRC522.h"
# include "SPI.h"
# include "SdFat.h"
# include "RTClib.h"
# include "SSD1306Ascii.h"
# include "SSD1306AsciiWire.h"

// Name des RTC-Moduls (rtc)
RTC_DS3231 rtc; 

// Adresse des OLED-Displays
# define I2C_ADDRESS 0x3C

// Name des OLED-Displays festlegen
SSD1306AsciiWire oled;

// Bezeichnung der SD-Karte
SdFat SD;

// Bezeichnung der CSV-Datei
File Zeiterfassung;

// Anschlüsse RFID definieren
# define SDA 7
# define RST 9

// RFID-Empfänger benennen und Datenpins zuordnen
MFRC522 mfrc522(SDA, RST);

// Daten-Pin SD-Karte
int DatenPin = 10;

// Trennzeichen für die CSV-Datei
const String TrennZeichen = ",";

String Mitarbeiter;

Der set­up-Teil. Beach­te die Kommentare:

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("Zeiterfassung"));

  // Initialisierung des RFID-Empfängers
  mfrc522.PCD_Init();

  /*
    wenn Datum und Zeit nicht korrekt -> Datum/Zeit setzen
    Jahr, Monat, Tag, Stunde, Minute, Sekunde
    Beispiel:  2022 August 31. 10 Uhr 30 Minuten 30 Sekunden
    rtc.adjust(DateTime(2022, 8, 31, 10, 31, 30));
 */
  // RTC-Modul starten
  rtc.begin();

  // 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 Zeichenkette (String) umwandeln und anzeigen
  Serial.print(aktuell.toString(Datum));

  // Format der Zeitangabe festlegen
  char Zeit[] = "hh:mm:ss";

  // Zeitangabe in Zeichenkette (String) umwandeln und anzeigen
  Serial.print(aktuell.toString(Zeit));
}

Der loop-Teil. Beach­te die Kommentare.

void loop() 
{  
  // 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!"));

  // 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 die eigenen Werte ersetzen
  */  
  if (WertDEZ == "195 106 18 23") Mitarbeiter = "Klaus Drolshagen";
  if (WertDEZ == "227 77 233 22") Mitarbeiter = "Eva Hilger";
  if (WertDEZ == "131 125 21 23") Mitarbeiter = "Claudia Kruse";

  /*
    Namen abfragen
    wenn (if) Mitarbeiter == Klaus Drolshagen oder (||) Mitarbeiter == Eva Hilger || . . 
    werden Die Daten angezeigt und in die Datei geschrieben
  */ 
  if (Mitarbeiter == "Klaus Drolshagen" || Mitarbeiter == "Eva Hilger" || Mitarbeiter == "Claudia Kruse") 
  {
    // Daten in die Datei schreiben
    DatenSchreiben();
  }

  // falsche Karte
  else 
  {
    Serial.println(F("Falsche Karte!"));
    oled.clear();
    oled.print(F("Falsche Karte!"));
  } 
  
  // Pause, damit die Daten nicht mehrfach in die Datei geschrieben werden
  delay(1000);
}

Jetzt fehlt noch die ➨Funk­ti­on Daten­Schrei­ben(). Beach­te die Kommentare.

void DatenSchreiben() 
{
  // Meldungen im Seriellen Monitor
  Serial.println(F("Schreibe Daten in Zeiterfassung.csv ... "));

  // Name der Mitarbeiterin/des Mitarbeiters
  Serial.println("Mitarbeiter*in: " + Mitarbeiter);
  Serial.println(F("-----------------------------"));

  // rtc.now() -> aktuelle Zeit holen
  DateTime aktuell = rtc.now();
  char Datum[] = "DD.MM.YYYY ";

  // Datum in Zeichenkette (String) umwandeln und anzeigen
  Serial.print(aktuell.toString(Datum));

  // Format der Zeitangabe festlegen
  char Zeit[] = "hh:mm:ss";

  // Zeitangabe in Zeichenkette (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));
  
  /*
    Zeiterfassung ist das Datei-Objekt
    FILE_WRITE -> Datei zum Schreiben öffnen
    wenn die Datei noch nicht existiert, wird sie neu erstellt
    ansonsten werden die neuen Daten ans Ende angehängt
  */
  Zeiterfassung = SD.open("Zeiterfassung.csv", FILE_WRITE);
  if (Zeiterfassung) 
  {
    // Überschrift nach jedem Datensatzwiederholen 
    Zeiterfassung.print(F("Mitarbeiter*in:"));
    Zeiterfassung.print(TrennZeichen);
    Zeiterfassung.print(F("Datum:"));
    Zeiterfassung.print(TrennZeichen);
    Zeiterfassung.print(F("Zeit"));
    Zeiterfassung.println();

    // Daten in die Datei schreiben: Mitarbeiter*in, Datum und Zeit
    // Werte durch Trennzeichen (,) trennen
    Zeiterfassung.print(Mitarbeiter);
    Zeiterfassung.print(TrennZeichen);
    Zeiterfassung.print(Datum);
    Zeiterfassung.print(TrennZeichen);
    Zeiterfassung.print(Zeit);
    Zeiterfassung.println();
    Zeiterfassung.println();
  }

  // Datei schließen
  Zeiterfassung.close();
  Serial.println(F("Speichern abgeschlossen."));
  Serial.println();
}

Bei­spiel: Bil­der und Beschrif­tung der Kar­ten (Quel­le: https://​open​clip​art​.org/​d​e​t​a​i​l​/​2​0​6​9​8​/​s​m​o​o​t​h​-​f​a​ces abge­ru­fen am 26.06.23)


Startseite
Aufgaben A-Z
Suchen
Downloads
Fehlermeldungen
Seite als PDF

Ver­wand­te Aufgaben:



Letzte Aktualisierung: 4. Okt 2023 @ 18:29