Daten berührungslos auf Funkchips speichern zu können ist ein alter Hut. Beispielsweise gibt es seit Mitte der 1990er die weit verbreiteten Mifare NFC-Tags mit unterschiedlichsten Speichergrößen, Sicherheitsmerkmalen und Preiskategorien.
Für ein Unterrichtsprojekt möchte ich Daten aus NFC-Tags mit einem Calliope auslesen. Mein Anspruch war, möglichst günstige NFC-Tags einzusetzen, die mit einem Smartphone beschrieben werden und mit dem Grove NFC Modul ausgelesen werden können. Ich habe daher erstmal für knapp 4 Euro ein 5er-Set NFC-Sticker bestellt vom Typ Mifare Ultralight C. Das C steht für Cryptofunktion (3DES), die ich allerdings nichts verwende, da man beim Speicher auslesen die (ASCII-)Zeichencodierung besser nachvollziehen kann. Es wären also auch Tags vom Typ Mifare Ultralight (ohne C) möglich, noch allgemeiner: Tags mit Typ-2-Spezifikation sowie ISO/IEC-Norm 14443-3A, nicht B. Wem jetzt noch nicht schwindelig geworden ist, darf weiterlesen...
Das richtige Protokoll cutternAuf dem Grove NFC ist der PN532-Chip von NXP verbaut, der eine Vielzahl an Drahtloskarten auslesen, beschreiben und selbst emulieren kann. Die Kommunikation ist per Highspeed UART, SPI und I2C möglich. Da ich den seriellen Port zum Auslesen am PC benötige und I2C sowieso "eleganter" ist, musste ich jedoch drei Lötkontakte auf der Rückseite der Grove Platine mit einem Scalpell durchtrennen und neu zusammenlöten:
Zum Auslesen der Daten aus einem Mifare-Tag per NFC sind zusammengefasst folgende Schritte notwendig:
- PN532-Chip aufwecken
- Bestätigung abwarten
- PN532-Chip nach Tag suchen lassen
- Bestätigung und Antwort annehmen
- PN532-Chip Daten aus Tag auslesen lassen
- Bestätigung und Antwort annehmen
Dabei muss bei jedem Schritt einiges beachtet werden:
Jedes Datenpaket (frame), das übertragen wird, besteht aus einer Folge von Bytes, die mit 0x00 0x00 0xFF
als Präambel und 0x00
als Postambel umschlossen wird. Dazwischen stehen die Nutzdaten (payload). Zusätzlich enthält die Folge Angaben zur Nutzdatenlänge sowie Prüfsummen, um Übertragungsfehler erkennen zu können.
Beim Aufwecken wird der Sicherheitschip nicht aktiviert (normal mode).
Jeder Antwort, auch der Bestätigung, geht ein Byte 0x01
voraus (RDY), wenn die vorherige Anfrage problemlos ausgeführt werden konnte.
Jede Bestätigung besteht aus der Byte-Folge 0x01 0x00 0x00 0xFF 0x00 0xFF 0x00
(ACK frame mit vorangestelltem, erfolgreichen RDY).
Beim Suchen nach Tags (targets) wird mit angegeben, nach welchen Funkchipkarten man genau suchen will. In diesem Projekt suche ich nach Karten vom Typ ISO14443-3A beziehungweise Mifare Typ 2, mit einer Baudrate von 106 kbps. Wer andere Chips verwenden möchte, muss die Baudrate im Code laut Handbuch entsprechend anpassen.
Die Tag-Suche initialisiert bei Erfolg die zum NFC-Chip passenden Kommunikationseinstellungen an eine "target number", hier: 1. Wenn das nicht geklappt hat, ist die Nummer gleich Null. Daran erkennt man, dass etwas nicht geklappt hat. Der Beispielcode unten gibt dann einen traurigen Smiley aus.
Um die Daten aus dem Tag auszulesen, wird der Mifare-spezifische Befehl 0x30
(16 bytes reading) an den PN532 geschickt plus die Information, an welchem Speicherblock mit dem Auslesen begonnen werden soll. Im Code unten wird Block 4 verwendet, da ab dort üblicherweise Mifare-Tags die Nutzerdaten ablegen.
Im Beispielcode werden nur die Blöcke 4-7 ausgelesen (16 Bytes), damit sind längere Texte nicht möglich. Der Code kann natürlich erweitert werden, da beim Auslesen und Decodieren nur bis zu einem Terminator-Symbol (0xFE
) gesucht werden muss. Entsprechend können weitere Blöcke mit 0x30
und deren Blockadresse abgefragt werden. Falls jemand Zeit hat...
Wer noch tiefer eintauchen möchte, findet hier das Handbuch mit weiteren Informationen.
Daten decodierenDie ausgelesenen Bytes werden vom Calliope nun nach einem NDEF text record durchsucht. Das NFC Data Exchange Format (kurz: NDEF) beschreibt, wie gängige Records mit URI-Angaben, MIME-Typen, aber auch reine Textnachrichten in Mifare-Tags gespeichert werden. Eine gute Einführung gibt es hier. (Die genauen technischen Spezifikationen zu den einzelnen messages sind nach Registrierung im NFC Forum erhältlich.)
Da der Code nur die Blöcke 4-7 ausliest, bin ich etwas faul beim Decodieren. (Don't bother yourself! ) Der Code sucht nach dem ersten Auftreten des Tag Blocks 0x03
(NDEF message), gefolgt von einem 0x54
("T" => text record) im Abstand von 5 Blöcken. Gibt es einen Treffer, wird alles nach den folgenden Informationen zur Zeichenkodierung und zur Sprache übersprungen und alle Bytes bis zum Terminator Block 0xFE
ausgelesen, alternativ bis zum Ende der ausgelesenen Daten. Damit sind mit dem Code unten Wörter von 5-10 Zeichen Länge möglich, zum Grund dafür später mehr.
Die Bytes werden anschließend mit String.fromCharCode()
in darstellbare ASCII-Zeichen umgewandelt und von der Funktion readNDEFText()
als String zurückgegeben. Im Beispielcode unten gibt ein Druck auf Button B den gespeicherten Text auf der 5x5-Matrix aus.
Der Calliope könnte auch über den Grove NFC Daten auf den Mifare-Tag schreiben. Für Messwerte ist das sicherlich interessant, für Textnachrichten jedoch zu umständlich. Daher verwende ich Apps unter Android. Getestet sind NFC Tools Pro von wakdev (Pro=kostenpflichtig. Nicht Pro kann ich nicht mehr testen, da ich sie bereits gekauft habe.) und NFC TagWriter von NXP. Während die NXP App eigentlich ausreichend ist, habe ich bei NFC Tools Pro das direkte Auslesen des NFC-Speichers schätzen gelernt. Gerade für das Decodieren der Daten war es sehr hilfreich zu wissen, wo die Bytes in den Blöcken genau liegen.
NFC TagWriter
Die App finde ich für Unterrichtsprojekte gut geeignet, da sie nicht zu überladen ist mit Funktionen.
Nach Öffnen von Schreiben
wählt man Neuer Datensatz
, dann Text
aus, gibt die gewünschte Zeichenfolge ein und klickt auf Schreiben
.
Aufpassen: Ist Schutz
einmal aktiviert und mit auf die Karte geschrieben, dann kann sie nur noch gelesen werden. Das ist für andere Projekte wie interaktive Hilfekärtchen sicherlich sinnvoll, kann aber beim Rumspielen doch schnell teuer werden.
Die weiteren Funktionen im Hauptmenü sind selbsterklärend, die Lesefunktion ahmen wir mit dem Code unten auf dem Calliope nach, allerdings nur für Textnachrichten (text records).
Die Sache mit der WortlängeEtwas nervig und für mich noch nicht ganz nachvollziehbar ist folgendes Verhalten des Mifare-Tags: Formatiere ich den Speicher mit Hilfe der NXP App unter Löschen
, Löschen und NDEF formatieren
, so wird der erste neue NDEF text record im ersten Byte des vierten Blocks gespeichert. Damit sind mit dem Code unten Wörter mit bis zu 10 Zeichen möglich. (Der Rest würde abgeschnitten, da Block 8 nicht mehr ausgelesen wird.) Überschreibe ich den text record aber wie oben beschrieben, landet der neue Eintrag nicht im ersten Byte des viertens Blocks, sondern ein paar Bytes weiter hinten. Dann sind es maximal 5 Zeichen.
Deshalb durchsuche ich mit dem Code auch erst die empfangene Byte-Folge nach einem Teil der Signatur eines vollständigen text records (0x00
, 0x54
usw.). Die Position der records wird im Mifare Application Directory (MAD) gespeichert, welches in Block 0x00
steht. Das war mir zeitlich zu aufwändig, da die NFC-Tags bald im Unterricht zum Einsatz kommen sollen. Falls jemand Zeit hat mir zu erklären, wie man die Position auslesen kann, freue ich mich sehr! Dann kann dieser Abschnitt ganz verschwinden.
- Wörter für Hilfekärtchen, die nicht sofort lesbar oder aus der Ferne abrufbar sind, wie bei QRCodes möglich
- Im Fremdsprachenunterricht Bilderbücher mit Tags bekleben und Übersetzungen darin als Lernkontrolle verstecken
- Lostrommel
- URI record implementieren und der AR/VR-Spaß geht los :-)
- Überlange text records implementieren für noch mehr Wortwitz
Comments