Go Down

Topic: Rfid-Reader Auswertung - Neueinsteiger von Bascom kommt nicht weiter (Read 2238 times) previous topic - next topic

Hallo Leute,
Ich habe mir mit dem Leonardo einen kleinen Rfid Reader zusammengebaut und komme an der Stelle der Auswertung der Tag´s nicht weiter. Wo habe ich den Denkfehler in der switch-case ?
Code: [Select]
#include <SoftwareSerial.h>

const byte codeLength = 14; //15 Zeichen gesammt da bei es bei 0 anfängt: Manufacturers code(2) + ID card number(10) + parity bits(3).
volatile long lastRead=0;
char code[codeLength];
int  val = 0;
int bytesread = 0;


SoftwareSerial RFID (11, 255);

void setup()
{
  Serial.begin(9600);
  while(!Serial)
    Serial.print ("Moin");
  RFID.begin(9600);
}

void loop()
{
  if (RFID.available())
  {
    lastRead = millis(); //Zeit des letzten bytes
    val = RFID.read();
    if((val == 10)||(val == 13)) //Wenn neue Zeil zb durch leseabbruch verschoben
    {
      bytesread=0;
    }
    else
    {
      code[bytesread] = val;
      bytesread++;
    }
  }


  if ((bytesread>0) && (millis()-lastRead>1000))//Wenn am lesen und zu lange kein byte empfangen = reset
  {
    bytesread = 0;
  }

  if(bytesread == codeLength) //Wenn alles empfangen
  {
    bytesread = 0;
    Serial.print("TAG code: ");   
    Serial.println(code);           
  }
  switch (code){
  case 05000604E2E5:
    Serial.print("Station 1");
    break;
  case 4F0088925E0B:
    Serial.print("Station 2");
    break;
  }
}


05000604E2E5 und 4F0088925E0B sind die mit dem Arduino ausgelesenen Codes der Tags.

Serenifly

#1
Nov 05, 2013, 01:31 am Last Edit: Nov 05, 2013, 01:40 pm by Serenifly Reason: 1
Du kannst nicht auf strings switchen. Außerdem gehören String-Literale in Anführungszeichen:
"4F0088925E0B"

Dafür gibt es strcmp():
http://www.cplusplus.com/reference/cstring/strcmp/
Die Funktion gibt 0 zurück wenn die strings gleich sind.

if(strcmp(code, "05000604E2E5") == 0)

Außerdem solltest du beachten, dass C-strings Null-terminiert sind, und das Array daher eins größer als die sichtbaren Zeichen sein muss. Du solltest daher sicherheitshalber das machen (es geht vielleicht auch ohne, da der Vergleichs-String korrekt terminiert ist):
char code[codeLength + 1];
Weil es eine globale Variable ist, steht im letzten Index dann automatisch NULL

Das mit den Indices ist genau anders herum. Ein Array der Größe 14 geht von 0-13. Wenn dein Code 2+10+3 ist musst du codeLength auf 15 setzen. Obwohl die 3 Parity Bits anscheinend gar nicht übertragen oder ausgelesen werden. Dein Vergleichs-String ist 12 Zeichen lang.

So richtig wills nicht...
owei da muss ich ncoh reichlich dazulernen^^
In Bascom wars doch leichter.... werde morgen mal weiter schaun, die Müdigkeit schlägt zu.
Danke für die schnelle Antwort, wenigstens kommen keine Fehlermeldungen mehr, nur die Richtigen Codes erkennt er immer noch nicht, sprich die Ausgabe kommt nicht zu den jeweiligen Tags.

uwefed

Du kannst den empfangenen Wert in eine Zahl umwandeln und diese dann mir Switch vergleichen.
Müßte mit atol() gehen (Habs nicht probiert darum bitte mit Vorsicht geniesen)
Grüße Uwe

jurs


Danke für die schnelle Antwort, wenigstens kommen keine Fehlermeldungen mehr, nur die Richtigen Codes erkennt er immer noch nicht, sprich die Ausgabe kommt nicht zu den jeweiligen Tags.


Kann es sein, dass Dein Reader z.B. einen 14-stelligen Code mit Hersteller-ID und/oder Prüfziffer sendet, Du aber versuchst, nur mit der 12-stelligen Karten-ID zu vergleichen?

Anbei mal ein Code zum Testen: Der gesendete Code wird eingelesen und in jedem Fall ausgegeben, entweder als "Valid" oder als "Invalid", zusammen mit der gelesenen Zeichenkette.

Wenn das nicht läuft, müßtest Du erstmal einen viel einfacheren Test-Sketch laufen lassen, der nur die Zeichen vom RFID-Reader liest und direkt auf dem Seriellen Monitor ausgibt, damit Du erstmal durchzählen kannst, wie viele Zeichen überhaupt gesendet werden.

Jedenfalls kannst Du nicht "Herstellercode+Karten-ID+Prüfziffer" oder "Karten-ID+Prüfziffer" einlesen und dann nur mit der "Karten-ID" (ohne Prüfziffer) vergleichen.  Da müßte schon genau beachtet werden, was der Reader eigentlich sendet und womit dann verglichen wird.

Nachtrag: Beispiel-Sketch zum Auslesen von Readern, die 14-stellige Werte liefern:
Code: [Select]

#include <SoftwareSerial.h>

SoftwareSerial rfidSerial (11, -1); // RX, TX

void setup() {
 // put your setup code here, to run once:
 Serial.begin(9600);
 rfidSerial.begin(9600);
 Serial.println("Started");
}

void readRfid()
#define CODESIZE 14
{
 char readbuffer[CODESIZE+1]; // Lesepuffer 1 größer als Codelänge
 int count=0; // Zeichenzähler
 if (!rfidSerial.available()) return; // Nix zu tun, return
 // Code ab hier wird nur ausgeführt, wenn ein Zeichen empfangen wurde
 memset(readbuffer,0,sizeof(readbuffer)); // Lesepuffer löschen
 while (rfidSerial.available() && count<CODESIZE)
 {
   readbuffer[count]=rfidSerial.read(); // Zeichen auslesen
   count++; // Zeichenzähler erhöhen
   delay(2); // 2 Millisekunden auf das nächste Zeichen warten
 }
 while (rfidSerial.available()) rfidSerial.read(); // ggf. abschließendes CR überlesen
 if (strcmp(readbuffer,"05001023556709")==0)
   Serial.print("Valid code ");
 else  
   Serial.print("Invalid code ");
 Serial.println(readbuffer);  
}

void loop() {
 readRfid();
}

Guten Morgen,
Danke für den Tip.
atol() bringt mir bei beide Tag´s den wert 0 , zumindest printed er ihn.


Code: [Select]

void loop()
{
 long int Co;
:
ursprünglicher Code wie oben
:
if(bytesread == codeLength) //Wenn alles empfangen
 {
   bytesread = 0;
   Co = atol(code);
   
   
   //if(strcmp(code, "05000604E2E50") == 0)  Serial.print("Station 1");

   //if(strcmp(code, "4F0088925E0B0") == 0) Serial.print("Station 2");
   
   Serial.print(Co);  
   Serial.println(code);  


 }
}

@ jurs,
Ich habe die Tags erst ausgelesen und den Code (im Programm auch "code") anzeigen lassen, da wirft er genau diese Werte aus.
Abzüglich der Null am Ende , wenn ich das richtig verstehe.

genau dieser Vergleich funktioniert ja in Bascom, also sollten die Tag-Werte doch stimmen.

jurs


@ jurs,
Ich habe die Tags erst ausgelesen und den Code (im Programm auch "code") anzeigen lassen, da wirft er genau diese Werte aus.
Abzüglich der Null am Ende , wenn ich das richtig verstehe.

genau dieser Vergleich funktioniert ja in Bascom, also sollten die Tag-Werte doch stimmen.


Ich habe in meinem Beitrag oben nochmal einen Sketch zum Testen angehängt, teste mal damit!

Ansonsten teste mit diesem ganz einfachen Test-Sketch, was eigentlich im seriellen Monitor ankommt:
Code: [Select]

#include <SoftwareSerial.h>

SoftwareSerial rfidSerial (11, -1); // RX, TX

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  rfidSerial.begin(9600);
  Serial.println("Started");
}

void loop() {
  if (rfidSerial.available()) Serial.write(rfidSerial.read());
}


Will so auch nicht funktionieren,
der spuck bei dem einem Tag 05000604E2E5 aus, und genau den Wert habe ich zum Vergleich im Programm,
kommt immer Invalid.

Muss erscht mal auf Arbeit, heute Abend gehts weiter ^^.

jurs


Will so auch nicht funktionieren,
der spuck bei dem einem Tag 05000604E2E5 aus, und genau den Wert habe ich zum Vergleich im Programm,
kommt immer Invalid.


Wenn Dein Reader 12-stellige Codes ausspuckt, dann mußt Du in meinem oben geposteten Code nicht nur den Vergleichscode anpassen, sondern auch die Codegröße durch Änderung der Definition auf:
Code: [Select]

#define CODESIZE 12


Mein Code ist so wie ich ihn oben gepostet habe für Reader, die einen 14-stelligen Code liefern (2 Zeichen Hersteller-ID plus 12 Zeichen Tag-ID = 14 lesbare Zeichen plus ggf. ein unsichtbares CR als Zeilenende-Steuerzeichen).

Wenn es auch damit nicht hinhaut, dann lasse mal ein Datenblatt zum Reader rüberwachsen, was Du da eigentlich für Hardware hast:
Manche Reader betten gesendete Codes in spezielle Steuerzeichen ein (STX= Start Text, ETX= End Text), in dem Fall wird natürlich eine Leseroutine benötigt, die (im Optimalfall) exakt auf diese Steuerzeichen reagiert oder (notfalls) wenigstens die Steuerzeichen überliest, statt sie in den Vergleichs-String für die Codeprüfung einzulesen.

Serenifly


Müßte mit atol() gehen (Habs nicht probiert darum bitte mit Vorsicht geniesen)

atol() geht nur mit reinen Dezimal-Zahlen. Nicht mit Hex.

long test = atol("1AA") liefert 1

So Feierabend und weiter gehts hier,
Also zum Lesegerät: Hier mal das Datenblatt   http://www.kibuck.com/RDM630-Spec.pdf
Der Code besteht demnach aus  10ASCII Data Characteren.


jurs


So Feierabend und weiter gehts hier,
Also zum Lesegerät: Hier mal das Datenblatt   http://www.kibuck.com/RDM630-Spec.pdf
Der Code besteht demnach aus  10ASCII Data Characteren.


Falls Du nicht das Wiegand-Interface aktiviert hast, das etwas anderes sendet, kommen über Serial von Deinem Modul insgesamt 14 Zeichen, davon 2 Steuerzeichen und 12 lesbare Zeichen, und zwar:

02 - STX (Steuerzeichen "Start of Text", unsichtbar im seriellen Monitor)
Kartennummer - 10 Zeichen
Prüfnummer - 2 Zeichen
03 - ETX (Steuerzeichen "End of Text", unsichtbar im seriellen Monitor)

Dazu kannst Du meinen Code verwenden, wenn Du die Anzahl der Zeichen auf 12 im Code setzt und die beiden Steuerzeichen am Anfang und am Ende des Codes überliest.

Code: [Select]

#include <SoftwareSerial.h>

SoftwareSerial rfidSerial (11, -1); // RX, TX

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  rfidSerial.begin(9600);
  Serial.println("Started");
}

void readRfid()
#define CODESIZE 12
{
  char readbuffer[CODESIZE+1]; // Lesepuffer 1 größer als Codelänge
  int count=0; // Zeichenzähler
  if (!rfidSerial.available()) return; // Nix zu tun, return
  // Code ab hier wird nur ausgeführt, wenn ein Zeichen empfangen wurde
  memset(readbuffer,0,sizeof(readbuffer)); // Lesepuffer löschen
  while (rfidSerial.available() && count<CODESIZE)
  {
    char c=rfidSerial.read(); // Zeichen auslesen
    if (c>=32)
    {
      readbuffer[count]=c;
      count++; // Zeichenzähler erhöhen
    } 
    delay(2); // 2 Millisekunden auf das nächste Zeichen warten
  }
  while (rfidSerial.available()) rfidSerial.read(); // ggf. abschließendes CR überlesen
  if (strcmp(readbuffer,"050010235567")==0)
    Serial.print("Valid code ");
  else 
    Serial.print("Invalid code ");
  Serial.println(readbuffer); 
}

void loop() {
  readRfid();
}


Das sollte hinhauen, aber ich kann es bei mir nicht testen.

Allerdings ist in dem Fall, dass wie bei Deinem Reader jeder Code mit einem eindeutigen Startcode beginnt, auch ein viel einfacherer Einlesecode möglich als bei meinem Code, der eigentlich für Reader mit anderem Sendeprotokoll vorgesehen ist, ohne speziellen Startcode vor der eigentlichen Kartennummer.

Ok jetzt zeigt er Invalid und Valid an, langsam kommen wir der Sache näher,
nur wie überlese ich die letzten Zeichen? 
bei 4F0088925E0B  ist glaube ich die Kartennummer 4F0088925E
also die letzten beiden Zeichen müssen wech.


Serenifly

strncmp():
http://www.cplusplus.com/reference/cstring/strncmp/

Hat einen zusätzlichen Parameter für die Anzahl der zu vergleichenden Zeichen

Go Up