Skip to content

Commit 7cc6d3f

Browse files
Merge pull request #4 from FHNW-IP5-IP6/feat/rfid
Feature: RFID Component
2 parents 9065f8c + 4c47c3a commit 7cc6d3f

File tree

3 files changed

+120
-16
lines changed

3 files changed

+120
-16
lines changed

code

Submodule code updated 40 files

content/german/basics/crowpi.md

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,6 @@ angesprochen werden können. Es kommen hierbei unterschiedliche Protokolle und S
4545
entsprechenden Komponenten-Klassen dieses Tutorials abstrahiert und vereinfacht werden. Nachfolgend ist eine Übersicht aller vorhandenen
4646
Komponenten aufgeführt:
4747

48-
| Komponente | Einsatzzweck | Schnittstelle | Position von DIP Switches |
49-
|:-------------------------------------------------------------------------|:---------------------------------------------------------------|:--------------|:--------------------------|
50-
| [7-Segment Anzeige]({{< ref "components/seven-segment" >}}) | Anzeigen von bis zu 4 Ziffern | I²C | {{< dip-switches >}} |
51-
| [Buzzer]({{< ref "components/buzzer" >}}) | Abspielen von verschiedenen Tönen | PWM | {{< dip-switches >}} |
52-
| [LCD Display]({{< ref "components/lcd-display" >}}) | Anzeige von Text und Zahlen | I²C, GPIO | {{< dip-switches >}} |
53-
| [LED Matrix]({{< ref "components/led-matrix" >}}) | Darstellen von beliebigen Symbolen | SPI | {{< dip-switches >}} |
54-
| [Lichtsensor]({{< ref "components/light-sensor" >}}) | Erkennen von aktueller Lichtstärke | I²C | {{< dip-switches >}} |
55-
| [PIR Motion Sensor]({{< ref "components/pir-motion-sensor" >}}) | Erkennen von Bewegung mit passivem Infrarot | GPIO | {{< dip-switches >}} |
56-
| [Relay]({{< ref "components/relay" >}}) | Schaltung eines elektrischen Kontakts | GPIO | {{< dip-switches >}} |
57-
| [Tilt Sensor]({{< ref "components/tilt-sensor" >}}) | Erkennt aktuelle Neigung (links/rechts) von CrowPi | GPIO | {{< dip-switches 10 >}} |
58-
| [Touch Sensor]({{< ref "components/touch-sensor" >}}) | Erkennen von Berührungen | GPIO | {{< dip-switches >}} |
59-
| [Ultraschall Distanz Sensor]({{< ref "components/ultrasonic-sensor" >}}) | Messung von Distanzen mit Ultraschall | GPIO | {{< dip-switches >}} |
60-
| [Vibrationsmotor]({{< ref "components/vibration-motor" >}}) | Ein Motor welcher ein Vibrieren wie beim Mobiltelefon auslöst. | GPIO | {{< dip-switches 9 >}} |
61-
6248
| Komponente | Einsatzzweck | Schnittstelle | Position von DIP Switches |
6349
|:-------------------------------------------------------------------------|:---------------------------------------------------|:--------------|:-------------------------------------|
6450
| [7-Segment Anzeige]({{< ref "components/seven-segment" >}}) | Anzeigen von bis zu 4 Ziffern | I²C | {{< dip-switches >}} |
@@ -68,11 +54,13 @@ Komponenten aufgeführt:
6854
| [LCD Display]({{< ref "components/lcd-display" >}}) | Anzeige von Text und Zahlen | I²C, GPIO | {{< dip-switches >}} |
6955
| [LED Matrix]({{< ref "components/led-matrix" >}}) | Darstellen von beliebigen Symbolen | SPI | {{< dip-switches >}} |
7056
| [Lichtsensor]({{< ref "components/light-sensor" >}}) | Erkennen von aktueller Lichtstärke | I²C | {{< dip-switches >}} |
71-
| [Relay]({{< ref "components/relay" >}}) | Schaltung eines elektrischen Kontakts | GPIO | {{< dip-switches >}} |
7257
| [PIR Motion Sensor]({{< ref "components/pir-motion-sensor" >}}) | Erkennen von Bewegung mit passivem Infrarot | GPIO | {{< dip-switches >}} |
58+
| [Relais]({{< ref "components/relay" >}}) | Schaltung eines elektrischen Kontakts | GPIO | {{< dip-switches >}} |
59+
| [RFID]({{< ref "components/rfid" >}}) | Kontaktloses Lesen und Schreiben von Karten | SPI | {{< dip-switches >}} |
7360
| [Tilt Sensor]({{< ref "components/tilt-sensor" >}}) | Erkennt aktuelle Neigung (links/rechts) von CrowPi | GPIO | {{< dip-switches 10 >}} |
7461
| [Touch Sensor]({{< ref "components/touch-sensor" >}}) | Erkennen von Berührungen | GPIO | {{< dip-switches >}} |
7562
| [Ultraschall Distanz Sensor]({{< ref "components/ultrasonic-sensor" >}}) | Messung von Distanzen mit Ultraschall | GPIO | {{< dip-switches >}} |
63+
| [Vibrationsmotor]({{< ref "components/vibration-motor" >}}) | Erzeugen eines Vibrationsalarms | GPIO | {{< dip-switches 9 >}} |
7664

7765
## Weitere Ressourcen
7866

content/german/components/rfid.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
---
2+
title: RFID
3+
tags: ["spi"]
4+
---
5+
6+
## Funktionsweise
7+
8+
Bei RFID, abgekürzt für Radio Frequency Identification, handelt es sich um eine Technologie, welche es ermöglicht automatisch und kontaktlos
9+
mit einer Karte entsprechende Informationen auszutauschen. Dies wird zum Beispiel bei weit bekannten NFC Tags verwendet, jedoch auch für
10+
Anwendungen wie das kontaktlose Zahlen per Kreditkarte.
11+
12+
Ein grosser Vorteil ist hierbei, dass die jeweiligen Karten/Tags, auch Transponder genannt, so klein wie ein Reiskorn sein können und keine
13+
eigene Stromversorgung benötigen. Im CrowPi ist die Komponente `MFRC522` verbaut, welche ein hochfrequentes elektronisches Wechselfeld bei
14+
13.56 MHz erzeugt, um damit einerseits die Karte mit Strom zu versorgen und andererseits mit dieser zu kommunizieren. Somit können
15+
beispielsweise die beiden beigelegten Tags des CrowPi ausgelesen und beschrieben werden. Dies funktioniert dabei mit beliebigen Daten.
16+
17+
Die Technologie dahinter ist sehr komplex und die entsprechenden Informationen dazu sind auf mehrere Standards aufgeteilt, hauptsächlich
18+
ISO-14443 für den allgemeinen Aufbau und die Kommunikation sowie die entsprechenden Spezifikationen von NXP Semiconductors, dem Hersteller
19+
des Lese- und Schreibgeräts sowie von den meisten RFID Karten. Die Einhaltung dieser Standards ist hierbei sehr wichtig, da eine RFID Karte
20+
bei falschen Schreiboperationen auch permanent beschädigt werden kann. Im Fachjargon wird das Lese- und Schreibgerät "Proximity Coupling
21+
Device" (PCD) genannt, während die verschiedenen Karten "Proximity Integrated Circuit Card" (PICC) heissen.
22+
23+
Es besteht hier jedoch kein Grund zur Sorge, da sich diese Komponente um all die komplexen Aufgaben im Hintergrund kümmert und eine einfache
24+
sowie zuverlässige Schnittstelle bietet, um mit solchen RFID Karten zu interagieren. So bietet `RfidComponent` die Möglichkeit an, Karten zu
25+
erkennen und ein beliebiges Java-Objekt darauf zu speichern oder wieder zu lesen.
26+
27+
## Voraussetzungen
28+
29+
### DIP Switches
30+
31+
Für diese Komponente werden keine spezifischen DIP-Switches benötigt, sodass diese in der Standardkonfiguration belassen werden können:
32+
33+
{{< dip-switches >}}
34+
35+
## Verwendung
36+
37+
Nachfolgend wird die Verwendung der Klasse {{< javadoc class="com.pi4j.crowpi.components.RfidComponent" >}} beschrieben.
38+
39+
### Konstruktoren
40+
41+
| Konstruktor | Bemerkung |
42+
|:--------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
43+
| `RfidComponent(com.pi4j.context.Context pi4j)` | Initialisiert einen RFID Reader/Writer mit der Standard Reset-Pin und SPI Adresse sowie SPI Bandbreite für den CrowPi. |
44+
| `RfidComponent(com.pi4j.context.Context pi4j, int spiChannel, int spiBaud)` | Initialisiert einen RFID Reader/Writer mit einer benutzerdefinierten SPI Adresse und Bandbreite ohne Reset-Pin. |
45+
| `RfidComponent(com.pi4j.context.Context pi4j, Integer gpioResetPin, int spiChannel, int spiBaud)` | Initialisiert einen RFID Reader/Writer mit einem benutzerdefinierten Reset-Pin, SPI-Adresse sowie Bandbreite. |
46+
47+
### Methoden
48+
49+
| Methode | Bemerkung |
50+
|:------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
51+
| `boolean isNewCardPresent()` | Gibt einen boolschen Wert zurück, ob eine neue Karte erkannt wurde, welche noch nicht gelesen wurde. |
52+
| `boolean isAnyCardPresent()` | Gibt einen boolschen Wert zurück, ob irgendeine Karte erkannt wurde. Diese Methode erkennt im Gegensatz zu `isNewCardPresent()` auch bereits gelesene Karten. |
53+
| `RfidCard initializeCard()` | Erzeugt eine neue Instanz von `RfidCard`, welche anschliessend zur Interaktion mit der Karte verwendet werden kann. Erfordert dass `isNewCardPresent` oder `isAnyCardPresent` vorher aufgerufen wurde und `true` zurückgab. |
54+
| `void uninitializeCard()` | Muss zwingend nach dem Abschliessen aller Aktionen mit einer Karte aufgerufen werden, um die Kommunikation mit der Karte sauber zu beenden und neue Karten erkennen zu können. |
55+
| `void onCardDetected(EventHandler<RfidCard> handler)` | Definiert einen Event Handler, welcher jedes Mal aufgerufen wird wenn eine neue Karte erkennt wird. Als erster Parameter wird hierbei die erkannte Karte übergeben. |
56+
| `void waitForNewCard(EventHandler<RfidCard> handler)` | Gleiche Funktionsweise wie `onCardDetected`, blockiert jedoch den aktuellen Thread und wartet bis eine neue Karte erkannt wird, um dann einmalig einen Handler aufzurufen. Diese Methode deaktiviert den aktuellen Event Listener für `onCardDetected`. |
57+
| `void waitForAnyCard(EventHandler<RfidCard> handler)` | Gleiche Funktionsweise wie `waitForNewCard`, akzeptiert jedoch auch eine Karte welche bereits gelesen oder beschrieben wurde und führt auf dieser die Aktion durch. Diese Methode deaktiviert den aktuellen Event Listener für `onCardDetected`. |
58+
| `void reset()` | Setzt die Komponente auf den Ausgangszustand zurück, was bei allfälligen Problemen Abhilfe schaffen kann. Normalerweise nicht erforderlich für den normalen Betrieb. |
59+
60+
### Karten-Methoden
61+
62+
Die Klasse {{< javadoc class="com.pi4j.crowpi.components.internal.rfid.RfidCard" >}} welche als Rückgabewert bei `initializeCard()` oder als
63+
Parameter bei den Event Handlern `onCardDetected()`, `waitForNewCard()` sowie `waitForAnyCard` verwendet wird, bietet verschiedene Methoden
64+
um mit der erkannten Karte zu interagieren. Wichtig zu beachten ist, dass nach Ausführung eines Event Handlers automatisch
65+
`uninitializeCard()` aufgerufen wird, sodass sich die erkannte Karte nicht weiter nutzen lässt.
66+
67+
| Methode | Bemerkung |
68+
|:--------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
69+
| `String getSerial()` | Gibt die Seriennummer der aktuellen Karte als String zurück. |
70+
| `int getCapacity()` | Gibt die maximale Kapazität der aktuellen Karte in Bytes zurück. |
71+
| `void writeObject(Object data)` | Schreibt das übergebene Objekt in die Karte. Wird dieser Befehl mehrfach aufgerufen, so wird dieses jeweils überschrieben. Das Objekt muss das Interface `Serializable` implementieren. Wirft eine `RfidException` falls die Operation nicht erfolgreich war. |
72+
| `Object readObject()` | Liest das auf der Karte gespeicherte Objekt aus und gibt dieses als generischen `Object`-Typ zurück. Wirft eine `RfidException` falls die Operation nicht erfolgreich war. |
73+
| `T readObject(Class<T> type)` | Gleiche Funktionsweise wie `readObject()`, aber gibt das Objekt gleich mit dem gewünschten Typ zurück. Wurde zum Beispiel mit `writeObject` vorher ein `Animal` gespeichert, so gibt `readObject(Animal.class)` direkt die `Animal`-Instanz zurück. |
74+
75+
## Beispielapplikation
76+
77+
Die nachfolgende Beispielapplikation definiert eine Klasse namens `Person`, um von einer beliebigen Person den Vornamen und Nachnamen, die
78+
Adresse sowie das Geburtsdatum zusammen mit einer zufällig generierten ID zu speichern. Nun werden zuerst zwei Personen generiert und in den
79+
Variablen `personA` sowie `personB` gespeichert, welche beide über verschiedene Daten verfügen.
80+
81+
Anschliessend wird mit der `waitForNewCard` Methode die Anwendung so lange blockiert, bis eine neue Karte vom RFID Gerät erkannt wurde.
82+
Sobald dies der Fall ist, wird die übergebene Funktion ausgeführt, welche die Instanz `personA` von der `Person`-Klasse auf der Karte mit
83+
`writeObject` speichert. Es kann jedes beliebige Java-Objekt gespeichert werden, solange dieses das `Serializable` mit `implements
84+
Serializable` implementiert. Wichtig ist hierbei zu beachten, dass diese Methode eine `RfidException` werfen kann, welche abgefangen werden
85+
muss. Diese tritt auf, wenn die Karte nicht ordnungsgemäss beschrieben werden konnte.
86+
87+
Nachdem die erste Karte beschrieben wurde, wird der gleiche Prozess für die zweite Karte wiederholt. Da mit `waitForNewCard` grundsätzlich
88+
nur neue Karten erkannt werden und eine Karte nach erfolgter Interaktion in einen Schlafzustand geht, kann hier garantiert werden dass nicht
89+
sofort die zweite Person auf die gleiche Karte geschrieben wird, sondern sich eine neue Karte annähern oder die bestehende Karte kurzfristig
90+
entfernt werden muss.
91+
92+
Sobald beide Karten beschrieben wurden, wird ein Event Handler mit `onCardDetected` registriert, welcher asynchron jedes Mal aufgerufen wird
93+
wenn eine neue Karte erkannt wurde. Da der RFID-Standard ein Verfahren gegen Kollisionen besitzt, können sich sogar mehrere Karten
94+
gleichzeitig auf dem Lese- und Schreibgerät befinden. Bei jeder ermittelten Karte wird mit `readObject(Person.class)` versucht, eine vorher
95+
gespeicherte Instanz der `Person`-Klasse auszulesen und in die Variable `person` zu speichern. Wenn dies gelingt, so wird die Person auf der
96+
Konsole ausgegeben. Auch hier muss eine allfällige `RfidException` aufgefangen werden, welche zum Beispiel auftritt, wenn die Daten nicht
97+
gelesen werden können oder korrupt sind.
98+
99+
Nach der Registrierung des Event Handlers schläft die Applikation für 30 Sekunden, um genug Zeit zu geben, die zwei verwendeten Karten
100+
auszuprobieren. Nach Ablauf der Zeit wird der Event Handler wieder sauber entfernt und die Applikation beendet sich.
101+
102+
{{< code file="src/main/java/com/pi4j/crowpi/applications/RfidApp.java" language="java" >}}
103+
104+
## Weitere Möglichkeiten
105+
106+
- Das Beispiel zu einer Art Zutrittskontrolle ausbauen und beispielsweise nur Personen mit einem bestimmten Attribut zulassen.
107+
108+
- Statt dem Speichern von Personen könnten auch andere Daten auf einer Karte abgelegt werden, zum Beispiel eine (nicht sehr sichere)
109+
Implementation einer Bank wo auf jeder Karte der Inhaber sowie der aktuelle Kontostand gespeichert wird. Hierfür wäre die Methode
110+
`waitForAnyCard` praktisch, um eine bereits aufgelegte Karte erneut zu beschreiben.
111+
112+
113+
## Zusätzliche Links
114+
- [NXP Semiconductors: ISO/IEC 14443 PICC Selection](https://www.nxp.com/docs/en/application-note/AN10834.pdf)
115+
- [NXP Semiconductors: Spezifikation zu MFRC522](https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf)
116+
- [NXP Semiconductors: Spezifikation zu MIFARE Classic 1K](https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf)

0 commit comments

Comments
 (0)