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

Ouh nein, ich dachte ich komm schnell da mit voran, aber so wie es aussieht nicht -_-
Ich nehme jetzt mal nur diesen Ausschnitt:
Quote
if (strcmp("2234553", buffer) == 0) {
  Serial.println("Got the right one!");
}
Ich habe mir mal dein Beispiel angeschaut. Soweit ich das verstanden habe, soll dort ein String und ein char Element mit einander verglichen werden. Lieg ich da richtig ?

Also ich habe das dann mal folgt ausprobiert:
Code:
#define RICHTIG "05003E22627B"
char msg;

if (strcmp(msg, RICHTIG) == 0) {
  Tue etwas bestimmtes);
}

Msg wurde natürlich vorher festgelegt:
Code:
while (inChar = Rfid.read() != 2)   
  {
  }
  for (x = 0; x < 12; x++)
  {
    delay(10); 
    inChar = Rfid.read();
    msg += inChar;

  }

Ich denke mal ich stelle mich da gerade echt dumm an :/ Habe damit noch nie so richtig gearbeitet und viel im Internet dazu gibt es auch nicht...
Hoffe mal ich bekomme da etwas Unterstützung, was ich aber denke ! smiley

Grüße
Lorenz
Logged

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

Ich denke mal ich stelle mich da gerade echt dumm an :/

Warum nennst Du einen Thread, in dem es um einen völlig einwandfrei funktionierenden RFID-Reader geht, eigentlich "125khz rfid Reader - Problem"? Der Reader funktioniert doch fehlerfrei und er sendet raus, was er raussenden soll?

Warum nicht sowas wie "serielle Schnittstelle auslesen" im Subject, wenn darin das eigentliche Problem besteht?

Hoffe mal ich bekomme da etwas Unterstützung, was ich aber denke ! smiley

Fragen zum Auslesen der seriellen Schnittstelle kommen hier im Forum alle paar Tage vor.
Bei manchen kommt sogar das Wort "seriell" im Subject vor, z.B.:
http://arduino.cc/forum/index.php/topic,136027.0.html

Hilft meine Antwort mit dem geposteten Code in diesem Thread (Reply #3) nicht, Dich auf eine Idee zu bringen, wie man nach fest vorgegebenen Begriffen fahnden kann, die über eine serielle Schnittstelle reinkommen? Wenn Du in dem von mir geposteten Code z.B. mal "Serial.available()" durch "Rfid.available()". "Serial.read" durch "Rfid.read" und "test" durch "05003E22627B" bzw. RICHTIG ersetzt?

BTW: Die unbedachte Verwendung von String-Objekten in Arduino-Sketchen ist böse (besseres Mittel: C-Strings/Char-Arrays) und das Reinmixen eines Pointers auf ein String-Objekt anstelle eines Pointers auf einen C-String in eine Funktion, die nur mit C-Strings umgehen kann, führt immer zu irregulärem Programmverhalten.
« Last Edit: January 17, 2013, 02:41:10 pm by jurs » Logged

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

Vielen Dank erstmal für deine Rückmeldung !
In letzter Zeit habe ich auch schon gemerkt das der Titel kaum passt...mir fällt einfach gerade nichts passendes ein ! Und "serielle Schnittstelle auslesen" ist auch nicht so das ganze ! Weil ich kann ja die Ths lesen usw.. Es ging eigentlich nur um das Problem das der immer je nachdem wie lange man den Tag dranhält, die Led öfters blinken lässt !
Jetzt kommt aber noch das mit "kein Sting" verwenden usw.

Ich werde mir mal deinen Vorschlag da angucken..mal schauen was sich machen lässt !

Grüße
Lorenz
Logged

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

Es ging eigentlich nur um das Problem das der immer je nachdem wie lange man den Tag dranhält, die Led öfters blinken lässt !

Wenn das ein Problem ist, braucht man sich ja nur in einer long-Variablen die Zeit zu merken, wann es zuletzt geblinkt hat, und dann ignoriert man eben so lange alle weiteren Codes wie kein wiederholtes Blinken auftreten soll.
Logged

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

Wenn du mal auf der 1. Seite lesen würdest !, dann wüsstest du, dass ich das Problem eigentlich schln fasst erledigt habe!!!

Jetzt ist halt nur noch das Problem mit dem String das ich diese weglasse !
Logged

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

1. "Dies ist kein String" . Jedenfalls kein String-Objekt.
2. ein char und ein char* sind zwei verschiedene Dinge,
    aber ein char* und ein char array, also dein char buffer[] sind fast das gleiche. Als Funktionsparameter wie in strcmp sind sie auf jeden Fall gleich verwendbar.
Logged

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

Ich habe mir mal dein Beispiel angeschaut. Soweit ich das verstanden habe, soll dort ein String und ein char Element mit einander verglichen werden. Lieg ich da richtig ?

Also ich habe das dann mal folgt ausprobiert:
Code:
#define RICHTIG "05003E22627B"
char msg;

if (strcmp(msg, RICHTIG) == 0) {
  Tue etwas bestimmtes);
}

In meinem Code ist buffer ein character array, was natürlich eine String-Konstante (à la "34533454") auch ist. Somit werden Äpfel mit Äpfeln verglichen und alles ist in Ordnung. Du definierst aber msg als einen Character (nicht Array), somit ist es nicht mehr das Gleiche.
Arrays werden in C einfach als Pointer auf das jeweilige Objekt aufgefasst, wie das michael_x bereits erklärte. Daraus resultiert dann, dass in C ein Textstring ein Character-Array (char[]) und somit ein Character-Pointer (char *) ist. Ich hoffe, das klärt Deine Verwirrung etwas.
Logged

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

Soweit ich das jetzt verstehe, muss ich jeden String einfach zu ein char* Objekt verändern ?!
Also so:
Code:
char* msg;
char* lastread;

Ich dachte das ist irgendwie viel komplizierter ?!
Wahrscheinlich habe ich da mal was falsch verstanden...

Logged

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

Soweit ich das jetzt verstehe, muss ich jeden String einfach zu ein char* Objekt verändern ?!
Also so:
Code:
char* msg;
char* lastread;

Ich dachte das ist irgendwie viel komplizierter ?!
Wahrscheinlich habe ich da mal was falsch verstanden...

viel komplizierter ist es nicht, aber ein bisschen fehlt doch noch:
Der Datentyp von msg und lastread ist schonmal gut, nur zeigen sie so nirgends hin.

Code:
char msg[81] ; // legt einen Speicherbereich für max 80 Zeichen + EndeKennung fest.
lastread = msg; // lastread zeigt jetzt auf den gleichen Speicher
lastread++; // zeigt jetzt auf den 2. Buchstaben von msg
Logged

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

Ganz ehrlich...irgendwie komme ich da mit nicht zu recht -_-

Ich weiß noch nicht ganz, wie ich das alles genau lösen soll.
Weil wenn ich Anfangs erstmal folgendes definiere:
Code:
char msg[81];
char lastRead[81];


und ich möchte dann den gelesenen Tag in msg hineinschreiben.
Code:
for (x = 0; x < 12; x++)
  {
    delay(10); 
    inChar = Rfid.read();
    msg[x] += inChar;

  }
Serial.println(msg);

Ich hoffe mal, dass das bis hier hin alles so einigermaßen richtig ausschaut ! Zum mindest wird der Tag richtig, beim ersten dranhalten,  erkannt, wenn ich dann aber nochmal lesen lasse, dann kommen da ganz komisches Gewirr von Zeichen usw. Ich müsste wahrscheinlich char irgendwie "leeren" aber da weiß ich zur Zeit noch nicht, wie ich das anstellen soll.
Nur wenn ich nun ein Vergleich tätigen möchte, hapert es leider noch:
Code:
if(strcmp("05003E22627B", msg)== 0)
  {
Serial.println("Zurtitt erlaubt");
}

Das funktioniert auch nicht !
Und auch das gleichsetzen von lastRead und dem gelesenen Tag klappt nicht so wie ich es von michael entnommen habe:
Code:
lastRead = msg;

Kann mir auch nicht vorstellen, dass das so einfach bei char array ist !

Grüße
Lorenz
Logged

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

Quote
Kann mir auch nicht vorstellen, dass das so einfach bei char array ist !

Was ich vergessen habe:
1. ein char array hat ein Endekennzeichen: eine (binär) 0 nach dem letzten Zeichen.
print, strcmp, usw. arbeiten immer bis zu dieser 0.
Code:
char msg[13]; // 0 .. 12
if (Rfid.available())
{
  for (byte x = 0; x < 12; x++)
  {
    delay(10); 
    char inChar = Rfid.read();
    msg[x] += inChar; 
  }
  msg[x]=0;  // EndeKennung in msg[12] !!!
  Serial.println(msg);
}

2. ein char array und ein char* unterscheiden sich insoweit, als ein char* eine eigene Variable ist, die auf ein char array verweist.

Code:
char* mp = msg; // mp kann jetzt genau wie msg verwendet werden, z.B. in print oder strcmp
// auch das ist alles möglich:
*mp == mp[0]; // vergleicht den ersten Buchstaben mit sich selbst
mp[0] = 'x';  // ändert den  ersten Buchstaben in msg
*(mp+1) = 'y'; // ändert den nächsten Buchstaben in msg
Man kann natürlich mp selbst auch ändern  (z.B.  mp++; ) und mit *mp jeweils einzelne Buchstaben ansprechen.
Das macht mit einem char array keinen Sinn!

Wenn du dich daran ein wenig gewöhnst, ist es wirklich einfach.
Logged

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

So...endlich habe ich mal wieder etwas Zeit gefunden mich mit Arduino weiter zu beschäftigen !
Nun habe ich es mittlerweile nach langwierigem basteln mit dem Code endlich hinbekommen, Vielen Dank bis hierhin schonmal !:
Code:
#include <SoftwareSerial.h>

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

void setup()
{
  Serial.begin(9600);
  Rfid.begin(9600);
}

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

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

Anfangs hatte ich immer folgendes:
Code:
msg[x] += inChar;
Und das hat alles meine ganzen Leseergebnisse richtig verfälscht, da kam einfach nur "Dünnschiss" raus smiley-grin.

Im laufe des Tages werde ich mich dann auch mal dransetzen, dass mit der Led einzubinden, ist ja an sich eigentlich gar nicht so eine große Sache, aber ich lasse mir gerne etwas Zeit.

Noch eine Frage am Rande:
Wahrscheinlich ist es dann auch Sinnvoll, wenn man mit der SD card arbeitet, wenn man schöne char elemente benutzt ?!
Und was genau passiert bei char elementen im Speicher, warum verbrauchen die letztendlich weniger Speicher als String ?!

Grüße
Lorenz

EDIT: Wie mache ich das eingentlich, dass, in meinem Fall lastRead, die gleichen Werte wie msg annimmt ?
Mit einem einfachen Gleich ist es wohl nicht getan. Ist dort eine Schleife anzuwenden ?
EDIT: Also so:
Code:
for(int i = 0; i <= 12; i++)
  {
   lastRead[i] = msg[i];
  }
« Last Edit: January 25, 2013, 09:03:47 am by lgrube96 » Logged

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

Quote
Wie mache ich das eingentlich, dass, in meinem Fall lastRead, die gleichen Werte wie msg annimmt ?
Mit einem einfachen Gleich ist es wohl nicht getan. Ist dort eine Schleife anzuwenden ?

Wenn msg und lastRead zwei unterschiedliche Texte sein können, ( d.h. wenn lastRead erhalten bleiben muss, während msg wieder geändert wird )
dann brauchst du zwei char arrays die du umkopierst, entweder wie in deinem Vorschlag, oder mit strcpy().
Wenn aber lastRead nur eine andere Sicht auf den gleichen Text ist, kannst du  char* lastRead = msg; schreiben.

Dein "Dünnschiss" sieht übrigens besser aus, wenn du msg[x++] = inchar; schreibst. Kleiner Unterschied in der Schreibweise, anderer Effekt.
Logged

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

Und was genau passiert bei char elementen im Speicher, warum verbrauchen die letztendlich weniger Speicher als String ?!

char-Arrays mit C-Strings sind Standard im Zusammenspiel mit der C-Standardlibrary. Die C-Standardlibraries enthalten seit Jahrzehnten bewährten und millionenfach getesteten, (so gut wie) fehlerfreien Code ohne Speicherlecks.

String-Objekte sind vergleichsweise neu. Und String-Objekte auf einer Mikrocontroller-Plattform mit den diversen Arduino-Magic-Tricks vor dem Kompilieren zu implementieren, damit haben die Arduino-Macher Neuland betreten und sich dabei gehörig vergallopiert.

Einerseits bekommen String-Objekte ihre Länge dynamisch zur Laufzeit zugewiesen, dadurch wird der Heap bei laufendem Programm fragmentiert, wenn Zuweisungen ständig unterschiedlich langer Strings erfolgen. Irgendwann ist dann kein freier Speicherbereich zur Zuweisung eines langen Strings mehr frei ==> Crash. Alleine schon deswegen eignen sich String-Objekte eigentlich nur auf Systemen mit weitgehend unbegrenztem Hauptspeicher, insbesondere für Computer mit der Möglichkeit von Auslagerungsspeicher auf Festplatte.

Aber bei der Arduino-Software ist alles noch schlimmer.
Denn offensichtlich ist die String-Library auf der Arduino-Software mit ihren ganzen Magic-Arduino-Tricks vor dem Kompilieren fehlerhaft  implementiert, sonst könnte es nicht sein, dass bei nur so wenigen Iterationen der Speicher crasht und das Ende der while-Schleife nicht erreicht wird:

Crash-Code mit String-Objekten, Demonstration für Arduino UNO:
Code:
void setup() {
  Serial.begin(9600); 
  String str, strMalDrei, strMalZehn;
  int n = 0;
  // Auf einem Arduino "UNO" crasht die while-Schleife
  // ohne das Schleifenende zu erreichen
  while(n <= 100) {
    str= String(n);
    strMalDrei=String(n*3);
    strMalZehn=String(n*10);
    str = str + ", " + strMalDrei + ", " + strMalZehn;
    Serial.println(str);
    delay(250);
    n++;
  }
  Serial.println("Done"); 
}

void loop() {
  // put your main code here, to run repeatedly:
}
==> Crash mit String-Objekten auf Arduino UNO mit Arduino 1.0.1 vor dem Schleifenende.
Logged

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

Vielen Dank an euch beide ! Habe das jetzt endlich mal einigermaßen verstanden, was so ein char Array alles gutes bewirkt !

Ich habe mich dann auch mal an den "fertigen" Code gesetzt und folgendes ist rausgekommen:
Code:
#include <SoftwareSerial.h>

char msg[12];
char lastRead[12];
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[1] = 0;
      } //Lastread "Resetten"   
    }

    else
    {

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

Also es ist leider immer noch das Problem von 'damals' vorhanden :/ Solange ich nur den RICHTIGEN Tag verwende funktioniert das mit dem einmal-ausführen echt super ! Aber wenn ich dann zum FALSCHEN Tag greife dann macht der das so lange ich den Tag an die Antenne halte ?! Ich weiß einfach nicht woran das liegen kann !!! Für mich ist das sowas unerklärlich ?! Das echt so ein nerviger Fehler ! Hoffentlich kann mich jemand darüber aufklären !

Und dann hätte ich da noch eine Frage bezüglich Arduino Mega2560:
Da ich später eh zu einem Mega greifen werde, weil ich etwas größere Sachen mit Arduino vorhabe, habe ich mal Fix ausprobiert, ob das mit dem RFID auch beim Mega auf Anhieb klappt. Natürlich musste ich noch den RX pin ändern, da ja die SoftwareSerial.lib nicht alle Pins beim Mega unterstützt. Da habe ich erstmal so pin 50 benutzt.
An sich funktioniert es EIGENTLICH, aber wirklich zuverlässig liest der Mega nicht mehr ! Manchmal tut er es und manchmal nicht, weiß jetzt nicht wie man das noch besser beschreiben könnte...
Hoffe ich habe das irgendwas kleine Übersehen ! Oder ist das unmöglich mit dem Mega ?

Grüße
Lorenz
Logged

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