MFRC522 RFID Reader mit Micropython

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
SeppelDeppel
User
Beiträge: 5
Registriert: Montag 20. April 2020, 06:41

Hallo alle zusammen,

ich bin absoluter Anfänger in Sachen Programmierung und stehe jetzt vor meinem ersten größeren Problem.
Ich verwende das ESP32 Node MCU. Jetzt versuche ich Daten auf eine RFID Karte zu schreiben.
Die Library dafür habe ich mir bei github heruntergeladen:
https://github.com/Tasm-Devil/micropython-mfrc522-esp32
Jetzt habe ich die beiden Samples getestet (read.py und write.py).
Bei beiden Programmen wird mir die UID der Karten richtig ausgegeben.
So wie ich das sehe, sollen beim write Programm die Zahlen von 1-16 auf die Karte geschrieben werden.
Es wird auch eine Meldung ausgegeben, dass der Schreibvorgang erfolgreich war. Aber ich schaffe es einfach nicht die Werte, die geschrieben wurden auszulesen.
Nachdem ich mich jetzt mehrere Tage an diesem Problem abgearbeitet habe und ich absolut keine Ahnung habe wie ich weiter vorgehen soll,
hoffe ich dass mir einer von euch helfen kann.

Vielen Dank schon mal an alle die sich die Zeit nehmen mir zu helfen.

LG
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was heißt du schaffst das nicht? Das angegebene read.py liest die schonmal nicht. Hast du das geändert, und wenn, wie?
SeppelDeppel
User
Beiträge: 5
Registriert: Montag 20. April 2020, 06:41

Das einzige was nicht funktioniert hat war, dass ich "import mfrc522" in "from mfrc533 import MFRC522" geändert habe.
Anschließend habe ich die files mfrc522.py, read.py und write.py downgeloaded. Anschließend habe ich in der Kommandozeile der Idle folgendes eingegeben:
import read
read.do_read()
Wenn ich jetzt die Karte an den Leser halte wird mir die UID der Karte ausgegeben.
Danach habe ich folgendes eingegeben:
import write
write.do_write()
Nun werde ich aufgefordert die Karte ans Lesegerät zu halten.
Wenn ich das tue werden TAG Nr. und UID der Karte ausgegeben.
Außerdem erscheint eine Meldung, dass der Schreibvorgang erfolgreich war.
In der Datei write.py befindet sich folgende Zeile:

stat = rdr.write(8, b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f")

Für mich bedeutet das, dass die Zahlen von 1-16 auf Speicherstelle 8 geschrieben werden und anschließend der Rückgabewert der Funktion write in der Variable stat gespeichert wird. Ist der Wert "OK" dann soll die Meldung ausgegeben werden, dass der Vorgang erfolgreich war.
In der Beschreibung bei GitHub steht, dass bei der read.py Speicheradresse 8 ausgelesen wird, also die Adresse auf die die Funktion write schreibt.
Also müsste doch die Ausgabe dann 0123456789101112131415 sein und nicht mehr die ID die vorher gespeichert war, oder sehe ich das falsch?

Vielen Dank, schon mal für deine Hilfe!!!!
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du siehst das falsch. Nirgendwo in deinem read.py wird etwas anderes als die ID gelesen. Woher sollte also eine andere Ausgabe kommen?
SeppelDeppel
User
Beiträge: 5
Registriert: Montag 20. April 2020, 06:41

Ok, jetzt habe ich mir nochmal alles angesehen und das Datenblatt runtergeladen um zu sehen wann da in welche Register geschrieben wird um irgendwie den genauen Ablauf zu verstehen. Aber warum bei anticoll die ID rauskommt habe ich nicht kapiert. Bisher habe ich nur das übliche Schleifengedöns gemacht und ein paar Ausgaben und das typische LED Blink Programm. Also entschuldige bitte wenn ich ein paar blöde Fragen stelle.
Zumindest habe ich jetzt entdeckt, dass es auch explizit einen read Befehl gibt, bei dem man auch eine Adresse eingeben kann. Also einfach mal ausprobiert.
Den Anfang habe ich gelassen:

from time import sleep_ms
from machine import Pin, SPI
from mfrc522 import MFRC522

sck = Pin(18, Pin.OUT)
mosi = Pin(23, Pin.OUT)
miso = Pin(19, Pin.OUT)
spi = SPI(baudrate=100000, polarity=0, phase=0, sck=sck, mosi=mosi, miso=miso)

sda = Pin(5, Pin.OUT)

def do_read():
try:
while True:
rdr = MFRC522(spi, sda)
uid = ""
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:

So wie ich das sehe passiert bis hier nichts ausser der Übergabe der Parameter für die Schnittstelle.und die initialisierung des RFID Lesers.
Jetzt habe ich versucht den Lesebefehl einzubauen:

(stat, newdata) = rdr.read(8)
if stat == rdr.OK:
uid = ("0x%02x%02x%02x%02x" % (newdata[0], newdata[1], newdata[2], newdata[3]))
print(uid)
sleep_ms(100)
except KeyboardInterrupt:
print("Bye")

rdr.read(8) sollte eigentlich passen. Aber in der Library sieht man dass es eigentlich 3 Rückgabewerte gibt. Stat wird wohl wieder der Status sein, rcv wohl die empfangenen Daten. Aber was soll bits sein? Damit konnte ich nichts anfangen. Aus diesem Grund habe ich versucht mit derselben Routine des Ursprünglichen Programms die Daten auszugeben.
Beim Download gibt es schon mal keine Fehlermeldung. Soweit so gut. Wenn ich die Karte auf den Leser lege erhalte ich eine Fehlermeldung:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "read.py", line 19, in do_read
Type Error: 'NoneType' object isn´t iterable

liegt das jetzt daran, dass ich für den letzten Übergabeparameter keine Variable definiert habe?

Und noch wichtiger: Bin ich jetzt auf dem richtigen Weg? :)

Danke für deine Geduld
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@SeppelDeppel: rdr.read liest entweder direkt ein Byte oder liefert None zurück, falls das nicht geklappt hat; kein stat! Bei Dir hat es offensichtlich nicht geklappt. Wahrscheinlich weil die Initialisierung falsch ist. Man braucht den anticoll-Aufruf, und wahrscheinlich noch einen select_tag und auth, wie beim Schreiben auch, nur dass halt statt write, read aufgerufen wird.
SeppelDeppel
User
Beiträge: 5
Registriert: Montag 20. April 2020, 06:41

Hallo Sirius3,

oh Mann da habe ich mich aber ganz schön verhauen. Anscheinend habe ich auf die Rückgabewerte von Tocard geschielt und nicht auf read. Das ist schon mal peinlich...
Sobald ich heute daheim bin werde ich mal versuchen die Initialisierung an die von write.py anzupassen.
SeppelDeppel
User
Beiträge: 5
Registriert: Montag 20. April 2020, 06:41

Ich habe das Programm folgendermaßen geändert:

from machine import Pin, SPI
from mfrc522 import MFRC522
sck = Pin(18, Pin.OUT)
mosi = Pin(23, Pin.OUT)
miso = Pin(19, Pin.OUT)
spi = SPI(baudrate=100000, polarity=0, phase=0, sck=sck, mosi=mosi, miso=miso)

sda = Pin(5, Pin.OUT)

def do_read():
rdr = MFRC522(spi, sda)

try:
while True:

(stat, tag_type) = rdr.request(rdr.REQIDL)

if stat == rdr.OK:

(stat, raw_uid) = rdr.anticoll()

if stat == rdr.OK:
print("New card detected")
print(" - tag type: 0x%02x" % tag_type)
print(" - uid : 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
print("")

if rdr.select_tag(raw_uid) == rdr.OK:

key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]

if rdr.auth(rdr.AUTHENT1A, 8, key, raw_uid) == rdr.OK:
newdata = rdr.read(8)
print(newdata)
else:
print("Authentication error")
else:
print("Failed to select tag")

except KeyboardInterrupt:
print("Bye")

Jetzt funktioniert es und ich bekomme die richtige Ausgabe.

Vielen Dank für eure Unterstützung!!!!
whiterabbit
User
Beiträge: 5
Registriert: Samstag 10. April 2021, 15:32

Hallo.
Ich habe hier einen esp32 & micropython zusammen mit einem MFRC522 laufen. Das Scannen der UIDs funktiioniert soweit -- doch ich verstehe leider nicht, wie die UID (die im Hex-Format ausgegeben wird) mit dem übereinstimmt, was ich z.B. von dem RFID-Tag sehe, wenn ich es mit dem Smartphone und den NFC-Tools scanne. Also konkret:
Der mfrc522-Scanner liefert "0x880419ee" wohingegen ich auf dem Smartphone (mit der App "NFC-Tools") als UID "04:19:EE:B2:75:71:81" sehe. Wie kann man das eine in das andere konvertieren?
Die andere Frage ist, wie man read.py erweitern muss, damit auch der Datensatz, der bereits auf dem RFID-Tag geschrieben wurde, ausgelesen werden kann?
Bin neu dabei -- daher sorry, falls das Anfängerfragen sind...
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Drei der Bytes sind doch schon mal gleich. Ob man an die anderen Bytes rankommt, kann man ohne Kenntnis des Codes nicht beurteilen. Was auch für deine zweite Frage gilt.
whiterabbit
User
Beiträge: 5
Registriert: Samstag 10. April 2021, 15:32

Hi. Der Code ist doch hier:
https://github.com/Tasm-Devil/micropython-mfrc522-esp32 unter mfrc522.py
und unter den examples read.py
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Natürlich kennen wir allen Code im Internet und was Du verwendest.
Die ID ist eine 32bit Zahl, da sind die 56 bit, die Du angeblich von Deinem Smartphone bekommst 24 Bit zu viel.
whiterabbit
User
Beiträge: 5
Registriert: Samstag 10. April 2021, 15:32

hm -- das würde bedeuten, dass die App auf dem Smartphone es falsch macht??!
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Beispiel read sollte das eigentlich laut Doku zeigen. Tut es nicht. Aber es müsste wie in https://github.com/Tasm-Devil/micropyth ... ite.py#L36 gehen, nur das man read statt write benutzt.
whiterabbit
User
Beiträge: 5
Registriert: Samstag 10. April 2021, 15:32

Ok, bei write.py wird ja auch diese Zeile geschrieben:
stat = rdr.write(8, b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f")
während bei read.py nur diese Zeile gelesen wird:
uid = ("0x %02x %02x %02x %02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
print(uid)

Ich habe da schon versucht, diese Einträge mit %02x und raw_uid[ ] bis 7 zu erweitern -- hat bisher nicht funktioniert. Das müsste aber die Stelle sein, um die es geht?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@whiterabbit: Du kannst nicht einfach die uid auf mehr Bytes erweitern, die ist und bleibt 32bit, jedenfalls in Deiner Implementierung. Und zum Lesen der ID braucht man auch keine Authentifizierung, wie in dem Write-Beispiel. Denn da ist ja die entscheidende Zeile auch die Zeile 24.

Ich hab nochmal nachgelesen, es gibt 32Bit, 56Bit und 80Bit UIDs. Es scheint aber in den Beispielen zu Python keine Beispiele zu geben, die etwas anderes Lesen als 32bit.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

whiterabbit hat geschrieben: Montag 12. April 2021, 07:17 Ok, bei write.py wird ja auch diese Zeile geschrieben:
stat = rdr.write(8, b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f")
während bei read.py nur diese Zeile gelesen wird:
uid = ("0x %02x %02x %02x %02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
print(uid)

Ich habe da schon versucht, diese Einträge mit %02x und raw_uid[ ] bis 7 zu erweitern -- hat bisher nicht funktioniert. Das müsste aber die Stelle sein, um die es geht?
Nein, das ist NICHT die Stelle, um die es geht. Das ist schon die Stelle die ich markiert habe, und die kommt doch sehr offensichtlich nach der äquavilenten Stelle, an der in beiden Programmen erstmal die ID geholt wird.

An der Stelle, wo write steht, muss eben read rein. Auch mit Angabe der Adresse des Blockes. Ohne Angabe der zu schreibenden Daten natürlich. Das diese Methode existiert, kann man dem Code des MFRC522-Klasse entnehmen.
whiterabbit
User
Beiträge: 5
Registriert: Samstag 10. April 2021, 15:32

Sirius3 hat geschrieben: Montag 12. April 2021, 07:52 Ich hab nochmal nachgelesen, es gibt 32Bit, 56Bit und 80Bit UIDs. Es scheint aber in den Beispielen zu Python keine Beispiele zu geben, die etwas anderes Lesen als 32bit.
Ok, dann wird auch klar, warum das unterschiedlich gehandhabt wird :wink: . Alle RFID-Tags, die ich hier habe, sind Mifare-Aufkleber, -Schlüsselanhänger, -Karten. Bei denen war es bisher immer so, dass die UIDs 56 Bit lang waren. Ich denke, dass das hardwareseitig so vorgegeben ist und nicht (ohne weiteres) verändert werden kann, so dass ich für meine Versuche die 56 Bit UID auslesen können müsste, um sie eindeutig erfassen zu können, richtig?

Was die Veränderung des Codes angeht: Da bin ich leider (noch?) nicht weit genug drin, um die notwendigen Änderungen überblicken zu können. Dabei gefällt mir micropython bisher wirklich gut.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Laut spec ist das nicht änderbar, nein. Der jetzige Code kann damit nicht umgehen. Das ist nicht schwer dem das beizubringen, weil das am Ende einfach Daten des ersten Blocks im ersten Sektor sind. Aber man muss sich in die Spec einarbeiten. Und es natürlich programmieren.
Antworten