Hallo Community
hi
Auch Hallo....
Sorry!! Problem beim ersten Postversuch ("message body was left empty")
Ich habe ein Problem mit einem RFID-Projekt, bei dem mehrere Tags in der richtigen Reihenfolge auf 4x MFRC522-Readern platziert werden sollen. Es werden bei jedem neu aufgelegten Tag die gelesenen UIDs mit denen in einem Array abgelegten verglichen und somit ist eine Aufgabe gelöst.
Die gute Nachricht vorneweg: das Ganze funktioniert auch schon. Der Wermutstropfen: manchmal schmiert das Auslesen der Tags ab und dann kommt von den Readern beim Auflegen eines neuen Tags entweder nur noch „0,0,0,0..“ als UID (von allen Readern!) oder ich erhalte fortlaufend „neues Tag aufgelegt“, obwohl alle Reader frei sind..
Nach einem Reset funktioniert das Ganze wieder problemlos.
Ich befürchte einen Fehler meinerseits in der richtigen Anwendung der MFRC522.h-Bibliothek. Ich steige nämlich noch nicht so richtig durch die Funktion und richtige Verwendung aller Befehle durch, die diese zur Verfügung stellt. Beginne und beende ich die Auslese-Vorgänge denn korrekt?
Könnte es weiterhin sein, daß mir die SPI-Verbindung zu den Readern irgendwie zusammenbricht? Eigentlich habe ich ja eine Debug-Funktion drin, die mir das Vorhandensein der Reader vor jedem Lesevorgang bestätigt (ob sie so funktioniert wie beabsichtigt?). Wie könnte ich eine fehlerhafte SPI-Verbindung denn erkennen und diese dann gegebenenfalls resetten, denn nach einem Neustart am Nano läuft ja alles wieder (eine unbestimmte zeitlang) normal..
Sketch folgt.. bitte paar Minuten Geduld
Mit der Verkabelung bin ich mir relativ sicher: MFRC522 über LogicLevelConverter mit Nano verbunden, gemeinsame Reset-Leitung und jeder Reader hat erstmal nur 15cm ungeschirmtes Flachband-Kabel dran. Das wird später noch geschirmt verlängert (max 40cm). Eine Zeichnung könnte ich auf Bedarf noch nachreichen.
// SPI-DECLARATION
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 10
#define SS_1_PIN 4
#define SS_2_PIN 5
#define SS_3_PIN 6
#define SS_4_PIN 7
#define NR_OF_READERS 4
byte ssPins[] = {SS_1_PIN, SS_2_PIN, SS_3_PIN, SS_4_PIN};
MFRC522 mfrc522[NR_OF_READERS]; // Create MFRC522 instance.
uint8_t reader;
byte uidreadarray[4][7]; // arrays for read UIDs
byte uidwinarray[4][7]; // arrays for comparing read UID (set by Eeprom)
boolean tagpresent[4]; // arrays for placed tag on readers
bool newtagispresent; // true, if a new tag is placed
byte atqa[4][2]; // identification of tag-type
byte atqaLen = sizeof(atqa[0]);
//MFRC522::MIFARE_Key key;
// IO-DECLARATION
#define Button A0
// global variables
bool gamewon;
// EEPROM-DECLARATION
#include <EEPROM.h>
void setup() {
Serial.begin(9600);
pinMode(Button, INPUT_PULLUP);
EEPROMreadUID(); // set uidwinarray
while (!Serial); // Do nothing if no serial port is opened
SPI.begin(); // Init SPI bus
checkReaders();
}
void loop() {
gamewon = false;
while (gamewon == false) {
newtagispresent = false;
for (reader = 0; reader < NR_OF_READERS; reader++) { // check all readers for a new tag
delay(1);
if (mfrc522[reader].PICC_IsNewCardPresent()) {
newtagispresent = true;
}
}
if (newtagispresent == true) { // new tag detected
readTags(); // read UID from all tags
checkWinUID(); // compare with correct UIDs
if (gamewon == false) {
Serial.println("Try again..."); // uid combination not correct, show it!
}
}
}
Serial.println("Game won!"); // uid combination is correct, show it!
while (digitalRead(Button) == HIGH) {
delay(1);
}
}
void readTags() {
checkReaders(); // check the readers first
for (reader = 0; reader < NR_OF_READERS; reader++) {
Serial.print(F("Reader :"));
Serial.print(reader);
Serial.print("\t");
delay(1);
//mfrc522[reader].PICC_RequestA(atqa[reader], &atqaLen); // buggy
mfrc522[reader].PICC_WakeupA(atqa[reader], &atqaLen);
if (atqa[reader][0] == 0x04 && atqa[reader][1] == 0) {
Serial.println("Mifare Classic");
//read and store UID
mfrc522[reader].PICC_Select(&(mfrc522[reader].uid), 0);
for (int n = 0; n < 4; n++) { // mfrc522[reader].uid.size
uidreadarray[reader][n] = mfrc522[reader].uid.uidByte[n]; // fill uidreadarray
}
uidreadarray[reader][4] = 0; // fill the last 3 blocks with 0 (Classic)
uidreadarray[reader][5] = 0;
uidreadarray[reader][6] = 0;
atqa[reader][0] = 0;
tagpresent[reader] = true;
}
else if (atqa[reader][0] == 0x44 && atqa[reader][1] == 0) {
Serial.println("Mifare Ultralight");
//read and store UID
mfrc522[reader].PICC_Select(&(mfrc522[reader].uid), 0);
for (int n = 0; n < 7; n++) { // mfrc522[reader].uid.size
uidreadarray[reader][n] = mfrc522[reader].uid.uidByte[n]; // fill uidreadarray
}
atqa[reader][0] = 0;
tagpresent[reader] = true;
}
else {
Serial.println("no valid tag present!"); // no Mifare Classic or Ultralight
atqa[reader][0] = 0;
tagpresent[reader] = false;
for (int n = 0; n < 7; n++) { // empty array for this reader
uidreadarray[reader][n] = 0;
}
}
mfrc522[reader].PICC_HaltA();
//mfrc522[reader].PCD_StopCrypto1(); // TEST
}
Serial.println();
outputUID();
}
void checkWinUID() { // Check if readUID is winUID
byte wincount = 0;
byte checksum = 0;
for (reader = 0; reader < NR_OF_READERS; reader++) {
for (int n = 0; n < 7; n++) {
if (uidreadarray[reader][n] == uidwinarray[reader][n]) {
wincount++;
}
checksum++;
}
}
if (wincount == checksum) {
gamewon = true;
}
}
void EEPROMreadUID() {
// read UID from Eeprom and set uidwinarray
Serial.println("Reading UIDs from Eeprom!");
for (reader = 0; reader < NR_OF_READERS; reader++) {
Serial.print("Reader: ");
Serial.print(reader);
Serial.print("\tADDR/VALUE:\t");
for (int n = 0; n < 7; n++) {
byte addresstoread = (reader * 10) + n + 1; // dynamic Eeprom-address
Serial.print(addresstoread);
Serial.print("/");
uidwinarray[reader][n] = EEPROM.read(addresstoread);
Serial.print(uidwinarray[reader][n]);
Serial.print("\t");
}
Serial.println();
}
}
void outputUID() {
Serial.println("showing read UID-arrays...");
for (reader = 0; reader < NR_OF_READERS; reader++) {
Serial.print ("Reader: ");
Serial.print (reader);
//Serial.print ("\t");
Serial.print ("\tUID:\t");
//Serial.print ("\t");
for (int n = 0; n < 7; n++) {
Serial.print (uidreadarray[reader][n]);
Serial.print ("\t");
}
Serial.println();
}
Serial.println();
}
void checkReaders() {
boolean allworking = true;
Serial.println();
Serial.println("Checking all Readers!");
for (reader = 0; reader < NR_OF_READERS; reader++) {
delay(1);
mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 tag
byte verbyte = mfrc522[reader].PCD_ReadRegister(mfrc522[reader].VersionReg);
Serial.print(F("Reader "));
Serial.print(reader);
Serial.print(F(": "));
mfrc522[reader].PCD_DumpVersionToSerial();
if (verbyte != 0x92) {
allworking = false;
}
}
if (allworking == false) {
Serial.println("There is a Problem!");
}
else {
Serial.println("Readers are working");
}
Serial.println();
}
derGeppi:
.....
Mit der Verkabelung bin ich mir relativ sicher: MFRC522 über LogicLevelConverter mit Nano verbunden, .....
Und was ist das für ein "LogicLevelConverter" ?
HotSystems:
Und was ist das für ein "LogicLevelConverter" ?
zwei davon:
einer für die SPI-Leitungen, einer für die 4 SlaveSelect.
Die Meinungen im Netz gehen ja auseinander, ob man den MFRC522 nun mit oder ohne LLC betreiben kann/soll. Ich konnte jedenfalls mehr als einen Reader nur mit fehlerfrei ansprechen.
Der Aufbau ist dann im Grunde wie hier:
..lediglich der Uno ist ein Nano und die PinBelegung ist wie im Sketch. Stromversorgung der RFID-Reader kommt von 3.3VLinearspannungsregler.
Dein Levelshifter ist für I2C gedacht und nicht unbedingt auch für SPI geeignet.
Nach meiner Erfahrung ist da ein HEF4050 besser geeignet.
Ob es auch ohne den Levelshifter geht, KA.
HotSystems:
Nach meiner Erfahrung ist da ein HEF4050 besser geeignet.
Ok, wird berücksichtigt... Gegenfrage: da der HEF4050 ja nur für 6 Channels ausgelegt ist, sollte ich mein Glück mit dem TXS0108E/TXB0108 probieren? Dann hätte ich ja alle 8 Leitungen abgedeckt...
Aber bevor ich wieder zum Basteln komme: wie könnte ich denn wieder den Anfangszustand der SPI-Verbindung bei Programmstart herstellen? Sprich: die SPI-Verbindung beenden und wieder neu herstellen, oder die Slaves (also die MFRC522) resetten? Diesen Vorgang könnte ich ja entweder in zeitlich festgelegten Abständen oder beim ständigen (erfolglosen) Ausleseversuch der Tags einstreuen, wenn sie nur noch Nuller ausspucken...
Den TXS0108E habe ich bisher noch nicht probiert, sollte aber auch funktionieren.
HotSystems:
Ob es auch ohne den Levelshifter geht, KA.
Funktioniert ohne, siehe auch MFC522 ohne Pegelwandler am UNO? - Deutsch - Arduino Forum
Wir laufen Gefahr, abzuschweifen..
Ja, es geht auch ohne. Habe ich bereits getestet. Aber: das funktioniert (bei mir) nur, solange es bei einem bis zwei Reader bleibt. Als ich vier angeschlossen hatte, bekam ich bei der Ausgabe des Versionsregisters nur einen korrekt angezeigt. Die anderen wurden als "unknown" erkannt. Bei gleichem Aufbau mit LevelShifter waren alle 4 Werte korrekt und ich konnte auch die Tags wesentlich besser auslesen.
Aber wie gesagt: wir schweifen ab.. Es sei denn: Es wird der auftretende Fehler in der Verwendung des (falschen) LevelShifters vermutet. Dann können wir das gerne weiter vertiefen
Ich befürchte ja irgendwelche äußeren Einflüsse bedingt durch das ungeschirmte Kabel zu den Readern oder weil sie zu nahe beieinander platziert sein könnten (z.Zt. wegen Test-Aufbau ca 7cm Abstand dazwischen). Aber irgendetwas kann ja beim finalen Aufbau immer wieder mal passieren, was dafür sorgt, daß sie "das Spinnen" anfangen, daher meine Frage zum Überprüfen bzw Neustarten speziell der SPI-Kommunikation und bezüglich der (Fehler einladenden?) Funktion zum Lesen der Tags wie ich sie in meinem Sketch umgesetzt habe.
Ich sehe das mal nicht als "abschweifen".
Es ist immer besser alles zu durchleuchten. Jede noch so kleine Idee kann helfen.
Und ja, du solltest die Reader schon weit genug auseinander setzen, auch in der Testphase.
Wie weit sind die später auseinander ?
Edit:
Was mir grad noch einfällt. Beim Nano ist der Pin 13 kritisch, da an dem auch die Led dran hängt.
Das könnte evtl. Probleme bereiten, ka. ob es auch bei dir so ist.
HotSystems:
Wie weit sind die später auseinander ?
ich dachte so an einen Abstand von minimum 15-20cm.
Die Anschlüsse mit Flachbandkabel würde ich dann durch RJ45-Buchsen nebst Cat-Kabeln (max 50-75cm) ersetzen. Ein ähnliches Setup wie in diesem Video zu sehen.
Zur Überlegung mit Pin13/LED: hm.. da ich ja auf keinen anderen PIN ausweichen kann, könnte ich die LED oder ihren Vorwiderstand ja einfach entfernen, oder?
Wie steht ihr denn zu meinem Ansatz, die SPI-Verbindung bei Bedarf resetten zu wollen? Es ist mein erstes Projekt mit dieser Schnittstelle, daher meine Ratlosigkeit. Wie müsste ich das formulieren, um den Zustand wie bei Arduino-Start herzustellen? Quasi einfach SPI.end() -> SPI.begin() .. oder die Slaves(Reader) durch HIGH an der SS-Leitung resetten? Ich rate grad nur ins Blaue bei der Methode..
(Ich weiß, ein stabiles System verlangt idealerweise nicht nach so einer Absicherung. Aber ich hatte zum Beispiel mal ein Projekt, bei dem mir das LCD -z.b. durch statische Aufladung des Benutzers- immer wieder mal abgeschmiert ist und zufällige Zeichen ausgegeben hatte. Ein regelmässiger Neustart des Displays sorgte aber für akzeptable Abhilfe bis das Problem in den Griff bekommen wurde)
Zu dem SPI-Problem, (SPI.end bzw. SPI.begin) kann ich nichts sagen, da fehlt mir die Erfahrung.
Aber der PIN13 macht kein Problem, habe nochmal deine Schaltung angesehen, der gehört ja mit zum SPI und ist nur Ausgang. Da flackert halt die LED.
Dann danke dir schonmal für die Hilfe und Tipps bis hierhin:)
Habe übers Wochenende mal ein paar Versuche zur besseren Stabilität unternommen:
- die Reader etwas weiter auseinander gesetzt
- statt der bisherigen einen TXS0108e Pegelwandler eingesetzt. Ich habe gelesen, man ist sich uneins, ob der TXS (mit internen Pullups) oder nun der TXB (ohne) geeigneter ist. Leider habe ich grad nur einen davon zur Hand. Eine Verbesser- oder -schlechterung konnte ich nicht feststellen.
- in den Sketch ein SPI.end() mit folgendem SPI-begin() eingestreut.
- die SSpins der Reader zwischendurch auf HIGH gesetzt.
All das hat das Ergebnis in keine Richtung verändert
Zur Fehlereingrenzung:
- die Funktion "checkReaders()" spuckt vor jedem Lesevorgang immer die korrekte Chip-Version des Readers aus.
- der Reader erkennt und meldet die Anwesenheit eines aufgelegten Tags.
- eine (funktionierende?) SPI-Vervbindung scheint also zu bestehen
- lediglich das Auslesen der UIDs führt (und wenn, dann bei allen 4!) bei meiner Methode nur zu Nullern. BZW bereits das Auslesen das Tag-Typs (atqa[0]=0 atqa[1]=0)!
- wenn ich die Tagwechsel "langsam" durchführe, taucht der Fehler eher selten auf. Fange ich allerdings an, die Tags sehr schnell auszutauschen, kommen die Reader mit irgendwas anscheinend durcheinander und fangen an sich dann bis zum Reset des Nano so komisch und unrettbar zu verhalten.
Wie bekomme ich also diesen Ursprungszustand nach Systemstart bei den Readern wieder hin, ohne den Nano selbst zu resetten?
Ok,.. was bewirkt der Befehl mfrc522[reader].PCD_StopCrypto1();?
Seitdem ich nämlich diesen im Sketch benutze, scheint das die Lösung zu sein... Zumindest konnte ich den Fehler im Schnelltest jetzt noch nicht reproduzieren...
Ich bitte um Nachsicht, wenn ich die ganzen Funktionen der Library nur stückchenweise begreife,.. aber wie gesagt, die ganze SPI-Thematik ist mir noch etwas kompliziert, aber ich bleibe neugierig...
Es wird besser... aber der Fehler ist noch immer reproduzierbar..
(Zur Erinnerung: häufiges und schnelles Wechseln der Tags führt dazu, daß auf allen Readern weder Tag-Typ noch UID ausgelesen werden. Es wird zwar in jedem Durchlauf wiederholt ein neu aufgelegtes Tag erkannt, aber weitere Leseversuche scheitern bis zum Reset des Nano)
Man empfahl mir den Einsatz von PCD_Reset(), den ich nach jedem erfolglosen Ausleseversuch des Tags ausgeführt habe. Dieser Befehl soll den Reader neu starten. Das klang gut.. aber schafft leider keine Abhilfe..
Hier im Code mal die veränderte Funktion zum Auslesen der Tags:
void readTags() {
checkReaders(); // check the readers first
for (reader = 0; reader < NR_OF_READERS; reader++) {
Serial.print(F("Reader :"));
Serial.print(reader);
Serial.print("\t");
delay(5);
//mfrc522[reader].PICC_RequestA(atqa[reader], &atqaLen); // which one to use?
mfrc522[reader].PICC_WakeupA(atqa[reader], &atqaLen); // which one to use?
if (atqa[reader][0] == 0x04 && atqa[reader][1] == 0) {
Serial.println("Mifare Classic");
//read and store UID
mfrc522[reader].PICC_Select(&(mfrc522[reader].uid), 0);
for (int n = 0; n < 4; n++) { // mfrc522[reader].uid.size
uidreadarray[reader][n] = mfrc522[reader].uid.uidByte[n]; // fill uidreadarray
}
uidreadarray[reader][4] = 0; // fill the last 3 blocks with 0 (Classic)
uidreadarray[reader][5] = 0;
uidreadarray[reader][6] = 0;
atqa[reader][0] = 0;
tagpresent[reader] = true;
}
else if (atqa[reader][0] == 0x44 && atqa[reader][1] == 0) {
Serial.println("Mifare Ultralight");
//read and store UID
mfrc522[reader].PICC_Select(&(mfrc522[reader].uid), 0);
for (int n = 0; n < 7; n++) { // mfrc522[reader].uid.size
uidreadarray[reader][n] = mfrc522[reader].uid.uidByte[n]; // fill uidreadarray
}
atqa[reader][0] = 0;
tagpresent[reader] = true;
}
else {
Serial.print ("no valid tag present!\t"); // no Mifare Classic or Ultralight
Serial.print ("atqa[0]=");
Serial.print (atqa[reader][0]);
Serial.print ("\atqa[1]=");
Serial.println(atqa[reader][1]);
atqa[reader][0] = 0;
tagpresent[reader] = false;
for (int n = 0; n < 7; n++) { // empty array for this reader
uidreadarray[reader][n] = 0;
}
mfrc522[reader].PCD_Reset(); // reset MFRC522
delay(50);
mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // init MFRC522
delay(50);
}
mfrc522[reader].PICC_HaltA();
mfrc522[reader].PCD_StopCrypto1();
}
Serial.println();
outputUID();
}
Wie gesagt: ich bin mir auch nicht zu 100% sicher, ob alle Befehle zur Kommunikation mit den MFRC522 so richtig eingesetzt sind...
Geschafft
Nachdem ich mich unrettbar in meinem Sketch verrannt hatte, habe ich das Ganze wieder von vorn (Beispiele der Library) begonnen und geschaut, wo die Probleme denn nun anfangen.
Der Fehler lag in den Abfragen .PICC_RequestA() oder .PICC_WakeUpA() mit denen ich aufliegende Tags auslesen wollte (zumindest in der Art wie ich sie eingesetzt hatte). Einmal "verlesen" haben diese beiden Befehle nämlich nur noch Nuller ausgespuckt und waren bis zum Neustart unbrauchbar.
Hätte ich direkt nach .PICC_IsNewCardPresent() ein .PICC_ReadCardSerial() gesetzt, hätte ich gesehen, daß die UID noch immer fehlerfrei gelesen wurde..
Also vor jedem Auslesevorgang lediglich die Reader neu initialisiert und schon werden auch noch immer aufliegende Tags als neu erkannt und gelesen, bzw das Entfernen eines Tags registriert und dementsprechend behandelt.. PUH!
Vielen Dank an alle Hilfesteller für die gegebenen Tipps
Hier nochmal das funktionierende Kernkonstrukt
#include <SPI.h>
#include <MFRC522.h>
#define RST_PIN 10
#define SS_1_PIN 4
#define SS_2_PIN 5
#define SS_3_PIN 6
#define SS_4_PIN 7
#define NR_OF_READERS 4
byte ssPins[] = {SS_1_PIN, SS_2_PIN, SS_3_PIN, SS_4_PIN};
MFRC522 mfrc522[NR_OF_READERS]; // Create MFRC522 instance.
uint8_t reader;
void setup() {
Serial.begin(9600);
while (!Serial); // Do nothing if no serial port is opened
SPI.begin(); // Init SPI bus
checkReaders(); // Init the readers
}
void loop() {
for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 reader
delay(1); // necessary delay to detect mifare ultralight
// Look for new cards
if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {
Serial.print(F("Reader "));
Serial.print(reader);
// Show some details of the PICC (that is: the tag/card)
Serial.print(F(": Card UID:"));
dump_byte_array(mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size);
Serial.print("\tPICC type: ");
MFRC522::PICC_Type piccType = mfrc522[reader].PICC_GetType(mfrc522[reader].uid.sak);
Serial.println(mfrc522[reader].PICC_GetTypeName(piccType));
} //if (mfrc522[reader].PICC_IsNewC
else {
// no new card found and read
Serial.println("no valid tag present!");
}
// Halt PICC
mfrc522[reader].PICC_HaltA();
// Stop encryption on PCD
mfrc522[reader].PCD_StopCrypto1();
} //for(uint8_t reader
}
void dump_byte_array(byte *buffer, byte bufferSize) {
for (byte i = 0; i < bufferSize; i++) {
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
void checkReaders() {
boolean allworking = true;
Serial.println();
Serial.println("Checking all Readers!");
for (reader = 0; reader < NR_OF_READERS; reader++) {
delay(1);
mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 reader
byte verbyte = mfrc522[reader].PCD_ReadRegister(mfrc522[reader].VersionReg);
Serial.print(F("Reader "));
Serial.print(reader);
Serial.print(F(": "));
mfrc522[reader].PCD_DumpVersionToSerial();
if (verbyte != 0x92) {
allworking = false;
}
mfrc522[reader].PICC_HaltA();
mfrc522[reader].PCD_StopCrypto1();
}
if (allworking == false) {
Serial.println("There is a Problem!");
}
else {
Serial.println("Readers are working");
}
Serial.println();
}
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.