Pages: 1 2 [3] 4   Go Down
Author Topic: 125khz rfid Reader - char* / char[]  (Read 3365 times)
0 Members and 1 Guest are viewing this topic.
Germany
Offline Offline
Faraday Member
**
Karma: 49
Posts: 2741
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

1)  0 .. 12 sind 13 Elemente
Deine zwei char arrays sind also etwas zu kurz. Wenn eine Variable die andere überschreibt, ist es schwer vorherzusagen, was passiert.


2) lastRead[1] = 0; // resetten
Arrays fangen mit Index 0 an:  lastRead[0] = 0; ist also ein echtes Reset  ( aber das nur am Rande, dir kommt es ja nur drauf an, dass lastRead unterschiedlich wird )

3) char* lastRead = msg;
dieser temporäre char* ist eine andere Variable als dein char array gleichen Namens, wird aber sofort wieder ungültig, mit der geschweiften Klammer zu in der nächsten Zeile.

lastRead soll der zuletzt gelesene Tag sein, richtig? Dann brauchst du auf jeden Fall eine Kopie ( strcpy oder mit deiner for-Schleife )
 
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 2
Posts: 285
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

1) Warum sollte es denn da Probleme geben ? Weil der Tag + die Endkennung sind genau 12 ! Habe es aber auch mal mit 13 probiert, hat aber nichts verändert...

2) ups...habe ich ganz übersehen ! Habe ich mal einfach so verändert ! Schadet ja nicht !

3) char* lastRead = msg;      Ich dachte diese Gleichsetzung übergibt auch den Inhalt ! Anscheinend nur den Speicherbereich (12 oder 13) ?!

Zuletzt habe ich dann halt doch nochmal die for schleife dort eingebracht, nur funktioniert es wieder nicht !
Irgendwas hat die Anlage gegen den FALSCHEN Tag....

Grüße Lorenz

Code:
Code:
#include <SoftwareSerial.h>

char msg[13];
char lastRead[13];
char inChar;
int x;
SoftwareSerial Rfid(2, 3); // RX als pin 2

int rot = 11;
int gruen = 10;

long lastMillis;


void setup()
{
  pinMode(rot, OUTPUT);
  pinMode(gruen, OUTPUT);
  digitalWrite(rot, HIGH);
  digitalWrite(gruen, HIGH);
  Serial.begin(9600);
  Rfid.begin(9600);

}

void loop()

  unsigned long currentMillis = millis();

  while (inChar = Rfid.read() != 2)   
  {
  } 

  for (x = 0; x < 12; x++)
  {
    delay(10); 
    inChar = Rfid.read();
    msg[x] = inChar;
  }
  msg[x] = 0;

  if(strcmp("05003E22627B", msg)== 0)
  {

    if(strcmp(msg, lastRead)== 0 )
    {
      if(millis() - lastMillis > 5000) {
        lastMillis = currentMillis;
        lastRead[0] = 0;
      } //Lastread "Resetten"   
    }

    else
    {

      Serial.println("Zutritt genehmigt");
      Serial.println( msg);   
      digitalWrite(gruen, LOW);
      delay(400);
      digitalWrite(gruen, HIGH);
      delay(400);             
      lastMillis = currentMillis;
      for(int i = 0; i < 13; i++)
      {
        msg[i] = lastRead[i];
      }
      msg[13] = 0;
     
    }
  }
  else
  {   
    if(strcmp(msg, lastRead)== 0 )
    {
      if(millis() - lastMillis > 5000) {
        lastMillis = currentMillis;
        lastRead[0] = 0;
      } //Lastread "Resetten"   
    }
    else
    {
      Serial.println("Zutritt verweigert");
      Serial.println( msg);
      digitalWrite(rot, LOW);
      delay(400);
      digitalWrite(rot, HIGH);
      delay(400);
      lastMillis = currentMillis;
      for(int i = 0; i < 13; i++)
      {
        msg[i] = lastRead[i];
      }
      msg[13] = 0;   
    }

  }
}
Logged

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2448
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

char msg[13];
...
msg[13] = 0;  

Du hast das vorausgegangene Posting von michael_x offenbar noch nicht so ganz verinnerlicht und schreibst hier immer noch über das Array-Ende hinaus in andere Variablen rein.

Mit msg[13] definierst Du tatsächlich ein Array mit 13 Elementen, dies sind
msg[0], msg[1], msg[2], msg[3], msg[4], msg[5], msg[6], msg[7], msg[8], msg[9], msg[10], msg[11], msg[12] = 13 Stück!

Da der Index mit null anfängt zu zählen, ist der höchste Index im Array immer "Arraygröße minus eins", also hier 12 als maximaler Index.

Das bedeutet: Mit "msg[13]=0" setzt Du eine Speicherstelle HINTER dem definierten Array auf Null! Das ist erstens nicht das, was Du möchtest und zweitens überschreibst Du damit eine andere Variable Deines Programms mit einem ungewollten Wert. Ein klassischer http://de.wikipedia.org/wiki/Puffer%C3%BCberlauf

Ein C-String von 12 Zeichen belegt msg[0] bis msg[11] plus msg[12] mit einem abschließenden Null-Zeichen.
msg[13] gibt es in einem Array mit der Deklaration "char msg[13];" definitiv nicht!

BTW: Im Thread http://arduino.cc/forum/index.php/topic,145244.0.html habe ich heute mal eine Leseroutine für RFID RDM6300 Reader gepostet, die so ziemlich dasselbe Protokoll senden, was Dein Reader auch zu senden scheint. Da bräuchtest Du in dem von mir geposteten Sketch vermutlich zunächst mal nur die "Serial.read()" Befehle durch "Rfid.read()" ersetzen (und Deine Rfid Deklaration einfügen), um ein Grundgerüst für Deine Zwecke zu erhalten und dann noch ein Timeout dranstricken, damit Du Deinen mehrfach schnell hintereinander feuernden Reader ausbremst. Aber wozu schreibe ich eigentlich soviel, denn wie schriebst Du hier schon vor 10 Tagen am 17.01. als Antwort: "Wenn du mal auf der 1. Seite lesen würdest !, dann wüsstest du, dass ich das Problem eigentlich schln fasst erledigt habe!!!". Schon klar, ich weiß. Werde wohl nochmal die 1. Seite dieses Threads lesen.
« Last Edit: January 27, 2013, 05:20:45 pm by jurs » Logged

Germany
Offline Offline
Sr. Member
****
Karma: 2
Posts: 285
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Danke ! Oh maaan ! Das habe ich sowas mal übersehen, geht ja mal gar nicht ! :/
Naja...werde das später mal ausprobieren, mal schauen ob das wirklich der Fehler war !

BTW Schön und gut aber wofür soll ich das bitte gebrauchen wenn ich das schon längst, aber wirklich längst gelöst habe ?!
Es wär wirklich besser wenn du mal die erste Seite von dem Thread liest ! Das würde einiges leichter machen ! Naja....du hast es zum mindest schonmal erkannt.

Grüße
Lorenz
Logged

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2448
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Naja...werde das später mal ausprobieren, mal schauen ob das wirklich der Fehler war !

Der zu große Index in "msg[13] = 0;" ist zwar ein Fehler, aber wenn Du stattdessen "msg[12] = 0;" schreibst, ist es wohl immer noch falsch.

Denn die ganze Kopierreihenfolge zwischen msg und lastRead ist meiner Meinung nach genau vertauscht für den Zweck, für den Du es benötigst.

Statt:
Code:
for(int i = 0; i < 13; i++)
{
  msg[i] = lastRead[i];
}
msg[13] = 0;
sollte es wohl eher heißen:
Code:
for(int i = 0; i < 13; i++)
{
  lastRead[i]=msg[i];
}
lastRead[12] = 0;   // diese Zeile ist doppelt gemoppelt, das \0 Zeichen wird schon in der Schleife kopiert
oder wenn ich es geschrieben hätte mit weniger Code ohne Schleife:
Code:
strcpy(lastRead,msg);

Soweit ich den Code überblicke, sollte er dann wenigstens so funktionieren, wie Du es wohl beabsichtigst.
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 2
Posts: 285
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vielen Dank jurs, dass du den Fehler entdeckt hast ! Ist auch wieder so ein Flüchtigkeitsfehler, die mir irgendwie oft passieren...

Naja, auf jedenfall, habe ich das mit dem Kopieren der beiden msg und lastRead jetzt mit strcpy erledigt, ist einfach bequemer..

Aber mittlerweile kotzt mich dieses Problem echt an ! Es ist immer noch das gleiche, wie es mal am Anfang war ! Ich glaube ich brauch das jetzt nicht nochmal hier zu beschreiben ! Aber wooooorran liegt das ? Ich dreh echt durch....der Code ist doch jetzt mittlerweile einwandfrei ?!

Aktueller Code:
Code:
#include <SoftwareSerial.h>

char msg[13];
char lastRead[13];
char inChar;
int x;
SoftwareSerial Rfid(2, 3); // RX als pin 2

int rot = 11;
int gruen = 10;

long lastMillis;


void setup()
{
  pinMode(rot, OUTPUT);
  pinMode(gruen, OUTPUT);
  digitalWrite(rot, HIGH);
  digitalWrite(gruen, HIGH);
  Serial.begin(9600);
  Rfid.begin(9600);

}

void loop()

  unsigned long currentMillis = millis();

  while (inChar = Rfid.read() != 2)   
  {
  } 

  for (x = 0; x < 12; x++)
  {
    delay(10); 
    inChar = Rfid.read();
    msg[x] = inChar;
  }
  msg[12] = 0;

  if(strcmp("05003E22627B", msg)== 0)
  {

    if(strcmp(msg, lastRead)== 0 )
    {
      if(millis() - lastMillis > 5000) {
        lastMillis = currentMillis;
        lastRead[0] = 0;
      } //Lastread "Resetten"   
    }

    else
    {

      Serial.println("Zutritt genehmigt");
      Serial.println( msg);   
      digitalWrite(gruen, LOW);
      delay(400);
      digitalWrite(gruen, HIGH);
      delay(400);             
      lastMillis = currentMillis;
      strcpy(lastRead, msg);
     
    }
  }
  else
  {   
    if(strcmp(msg, lastRead)== 0 )
    {
      if(millis() - lastMillis > 5000) {
        lastMillis = currentMillis;
        lastRead[0] = 0;
      } //Lastread "Resetten"   
    }
    else
    {
      Serial.println("Zutritt verweigert");
      Serial.println( msg);
      digitalWrite(rot, LOW);
      delay(400);
      digitalWrite(rot, HIGH);
      delay(400);
      lastMillis = currentMillis;
      strcpy(lastRead, msg); 
    }

  }
}

Grüße
Lorenz
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Ich dreh echt durch....der Code ist doch jetzt mittlerweile einwandfrei ?!

Einwandfrei ist anders:

Code:
  for (x = 0; x < 12; x++)
  {
    delay(10); 
    inChar = Rfid.read();
    msg[x] = inChar;
  }

Du liest von der SoftwareSerial ohne zu überprüfen, ob überhaupt ein Zeichen empfangen wurde. Wenn Du das machen würdest, wäre dafür der delay() komplett überflüssig.

Zudem: überall, wo in Deinem Code "int" steht, sollte "byte" oder "uint8_t" stehen.

Quote
Es ist immer noch das gleiche, wie es mal am Anfang war !

Heisst das, wenn Du den Tag 2 Sekunden an den Reader hältst, wird der Blinkcode mehrfach ausgegeben? Falls Du ihn länger als 5 Sekunden hin hältst, soll er mehrfach ausgegeben werden (steht so in Deinem Code).
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 2
Posts: 285
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Du liest von der SoftwareSerial ohne zu überprüfen, ob überhaupt ein Zeichen empfangen wurde. Wenn Du das machen würdest, wäre dafür der delay() komplett überflüssig.

Ich habe das einfach aus einem Code vom Internet so übernommen...

Quote
Zudem: überall, wo in Deinem Code "int" steht, sollte "byte" oder "uint8_t" stehen.

Warum das ? Was ändert das ?

Quote
Heisst das, wenn Du den Tag 2 Sekunden an den Reader hältst, wird der Blinkcode mehrfach ausgegeben? Falls Du ihn länger als 5 Sekunden hin hältst, soll er mehrfach ausgegeben werden (steht so in Deinem Code).

Ja es heisst, dass ich den Tag 2 Sekunden an den Reader halte und der Blinkcode wird mehrfach ausgefürht !
Das es öfters ausgeführt wird, wenn ich den länger als 5 Sekunden dranhalte war mir schon von vornrein klar, wird ja auch so definiert...

Grüße Lorenz

EDIT: Auch byte ändert nichts
« Last Edit: January 28, 2013, 12:53:37 pm by lgrube96 » Logged

Germany
Offline Offline
Faraday Member
**
Karma: 49
Posts: 2741
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

... und es ist immer genau derselbe (falsche) Code ?

Und wenn du den richtigen Tag beliebig lang dranhältst, siehst du die grüne LED und den "genehmigt" - Text  nur einmal ?

( Ich seh's auch nicht, falls dir das hilft )


Ein byte ist nur halb so groß wie ein int, aber solang der Arduino schnell genug ist und genug Platz hat, ist das nicht soo wichtig, solang du es nur für dieses Projekt brauchst.
Das delay(10) ist auch nicht wirklich entscheidend.

"einwandfrei" ist halt ein dehnbarer Begriff smiley-wink
 
Logged

Germany S-H
Offline Offline
Edison Member
*
Karma: 117
Posts: 2448
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ja es heisst, dass ich den Tag 2 Sekunden an den Reader halte und der Blinkcode wird mehrfach ausgefürht !
Das es öfters ausgeführt wird, wenn ich den länger als 5 Sekunden dranhalte war mir schon von vornrein klar, wird ja auch so definiert...

Hast Du mal ausgemessen, mit wieviel "Bytes pro Sekunde" Dein RFID-Reader die Zeichen rausfeuert, wenn er feuert?

Weil, Du hast ja eine schnarchlangsame Verarbeitung mit 12 * 10 ms delay beim Einlesen plus 2 * 400 ms delay beim Blinken, d.h. wenn der erste Code verarbeitet wird, wird der zweite Code danach erst nach 120 + 800 = 920 ms = 0,92 s aus dem seriellen Eingangspuffer ausgelesen.

Die Größe des seriellen Eingangspuffers beträgt (wenn es wie bei der Hardware-Serial ist) 64 Zeichen, ein Code mit Start- und Endezeichen sind 14 Zeichen, d.h. es passen 4 ganze und ein zerhackter Code in den Eingangspuffer.

Wenn die Zeichen so schnell reinkommen, dass der serielle Eingangspuffer wegen Deiner langsamen Verarbeitung überläuft, solltest Du den Puffer zumindest immer dann leeren, wenn Du vorher die langen delays beim Blinken aufgerufen hast, also nach jedem:
delay(400);
den seriellen Eingangspuffer leeren mit:
while (Rfid.available()) Rfid.read();

Macht das einen Unterschied?
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 2
Posts: 285
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Ein byte ist nur halb so groß wie ein int, aber solang der Arduino schnell genug ist und genug Platz hat, ist das nicht soo wichtig, solang du es nur für dieses Projekt brauchst.
Das delay(10) ist auch nicht wirklich entscheidend.

Ah ok, vielen Dank !
Und wenn delay(10) weglasse, dann funktioniert da absolut nichts ! Dann wird der Tag immer nur als falsch erkannt. Warum das so ist kann ich nicht sagen, aber es macht einen Unterschied.

Und jurs du hast meinen Tag echt gerade irgendwie gerettet !
Es funktioniert ! ^^
Schöne Vorrechnung mit Zeiten und bla...wüsste nicht so was man da so wirklich mit Anfangen sollte...aber passt !

Aber warum macht while (Rfid.available()) Rfid.read(); alles gleich funktionsfähig ?
"nur" weil der cache wieder geleert wird ?! 
Hier jetzt der endgültige Code (bis jetzt):
Code:
#include <SoftwareSerial.h>

char msg[13];
char lastRead[13];
char inChar;
byte x;
SoftwareSerial Rfid(2, 3); // RX als pin 2

byte rot = 11;
byte gruen = 10;

long lastMillis;


void setup()
{
  pinMode(rot, OUTPUT);
  pinMode(gruen, OUTPUT);
  digitalWrite(rot, HIGH);
  digitalWrite(gruen, HIGH);
  Serial.begin(9600);
  Rfid.begin(9600);

}

void loop()

  unsigned long currentMillis = millis();

  while (inChar = Rfid.read() != 2)   
  {
  } 

  for (x = 0; x < 12; x++)
  { 
    delay(10);
    inChar = Rfid.read();
    msg[x] = inChar;
  }
  msg[12] = 0;

  if(strcmp("05003E22627B", msg)== 0)
  {

    if(strcmp(msg, lastRead)== 0 )
    {
      if(millis() - lastMillis > 5000) {
        lastMillis = currentMillis;
        lastRead[0] = 0;
      } //Lastread "Resetten"   
    }

    else
    {

      Serial.println("Zutritt genehmigt");
      Serial.println( msg);   
      digitalWrite(gruen, LOW);
      delay(400);
      while(Rfid.available()) Rfid.read();
      digitalWrite(gruen, HIGH);
      delay(400);
      while(Rfid.available()) Rfid.read();       
      lastMillis = currentMillis;
      strcpy(lastRead, msg);
     
     
     
    }
  }
  else
  {   
    if(strcmp(msg, lastRead)== 0 )
    {
      if(millis() - lastMillis > 5000) {
        lastMillis = currentMillis;
        lastRead[0] = 0;
      } //Lastread "Resetten"   
    }
    else
    {
      Serial.println("Zutritt verweigert");
      Serial.println( msg);
      digitalWrite(rot, LOW);
      delay(400);
      while(Rfid.available()) Rfid.read();
      digitalWrite(rot, HIGH);
      delay(400);
      while(Rfid.available()) Rfid.read();
      lastMillis = currentMillis;
      strcpy(lastRead, msg);
     
    }

  }
}

Ist vielleicht nicht alles so schön, aber es funktioniert !
Morgen werde ich das ganze dann mal mit meinem MEGA ausprobieren, weil da gab es "früher" ein paar Probleme bezüglich der Arbeit mit dem RFID Reader !

Grüße
Lorenz
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Ja es heisst, dass ich den Tag 2 Sekunden an den Reader halte und der Blinkcode wird mehrfach ausgefürht !

Einfach, damit das klar ist: wir reden von der grünen LED, die blinkt? Wie oft die rote blinkt, ist mir egal, das kann gut an meinem Einwand mit dem falschen Auslesen des seriellen Puffers liegen.

Quote
Warum das ? Was ändert das ?

Es ändert, dass nicht unnötig Speicherplatz verschwendet wird. Einwandfrei heisst bei mir, dass daran nichts rumzumeckern ist. Verschwendung von Speicher ist ein Grund zu meckern.

Hast Du die Routine mal so angepasst?

Code:
unsigned long timeout = millis();
for (x = 0; x < 12; x++)
  {
    while (Rfid.available() < 1 && millis() - timeout < 200);
    if (millis() - timeout >= 200) {
      Serial.println(F("Error receiving RFID tag!"));
      msg[x] = 0;
      break;
    }
    msg[x] = Rfid.read();
  }
Logged

Germany
Offline Offline
Sr. Member
****
Karma: 2
Posts: 285
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Einfach, damit das klar ist: wir reden von der grünen LED, die blinkt? Wie oft die rote blinkt, ist mir egal, das kann gut an meinem Einwand mit dem falschen Auslesen des seriellen Puffers liegen.

Also eigentlich rede ich die ganze Zeit von der roten die zu oft blinkt ! Hat sich ja jetzt aber eh erledigt !

Deinen Vorschlag mit der neuen Routin, werde ich morgen mal kurz ausprobieren !
Was genau sollte diese verbessern ? Einfach weniger speicher verbrauch ?!

Grüße
Lorenz
Logged

Germany
Offline Offline
Faraday Member
**
Karma: 49
Posts: 2741
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Na dann ist ja alles gut.

Quote
Warum das so ist kann ich nicht sagen, aber es macht einen Unterschied.
Dann kannst du auch nicht wissen, ob dein Code "einwandfrei" ist.
Was pylons Modifikation mit dem verräterischen Wort timeout für eine Startzeit (?) soll, solltest du verstehen, während du es einbaust.
Es ist nur ein Schnipsel, der nicht überall hin passt smiley-wink


Noch ein Nachtrag:

Eine Zugangskontrolle darf übrigens gar nicht so schnell sein, wenn sie ernst genommen werden will.
"Schnarchlangsam" solltest du zu keinem Security, Zöllner oder ähnlichen sagen, wenn du nicht lernen willst, wie langsam alles gehen kann  smiley-wink  

Ungenutzer RAM verbraucht übrigens genausoviel Strom wie verschwendeter ...
Allerdings gebe ich dir recht, pylon, dass die Verwendung von int für kleine vorzeichenlose Zahlen im Prinzip eine schlechte Angewohnheit ist.
Bin nicht sicher, ob avrgcc das wirklich immer richtig wegoptimiert.
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Bin nicht sicher, ob avrgcc das wirklich immer richtig wegoptimiert.

In vielen Fällen kann er das gar nicht, weil er nicht den ganzen Wertbereich kennt, der möglich ist.
Ich habe auch nicht behauptet, meine Modifikation sei notwendig, aber einwandfreier Code darf solche Sachen nicht enthalten.

Quote
Was pylons Modifikation mit dem verräterischen Wort timeout für eine Startzeit (?) soll, solltest du verstehen, während du es einbaust.

Korrekter Einwand, aber ich wollte dem OP einen Hinweis geben, wofür die Variable verwendet wird. Und wenn ich das übliche lastMillis genommen hätte, wäre der Konflikt programmiert gewesen.

Quote
Was genau sollte diese verbessern ? Einfach weniger speicher verbrauch ?!

Nein, sie eliminiert einen Fehler in Deinem Code. Du liest einfach 12 Zeichen von der SoftwareSerial ein, ohne zu wissen, dass die dort überhaupt angekommen sind. Da Du das überaus langsam machst (und damit Deinen ganzen Sketch blockierst), funktioniert es in den meisten Fällen, trotzdem ist es sehr unschön und kann zu Race-Conditions führen. Der Timeout ist eingebaut, damit der Sketch nicht gleich stehen bleibt, wenn Dein Reader, aus welchen Gründen auch immer, mal nicht die gewünschten 12 Zeichen liefert.
Logged

Pages: 1 2 [3] 4   Go Up
Jump to: