Go Down

Topic: 125khz rfid Reader - char* / char[] (Read 5244 times) previous topic - next topic

jurs


Und jurs du hast meinen Tag echt gerade irgendwie gerettet !
Es funktioniert ! ^^


Na bravo!


Aber warum macht while (Rfid.available()) Rfid.read(); alles gleich funktionsfähig ?
"nur" weil der cache wieder geleert wird ?!


Das komplette Wegschmeißen der Zeichen im Eingangspuffer nach einem Buffer-Overrun wegen der schnarchlangsamen Verarbeitung mit langen Delays bei gleichzeitig hoher Eingangsdatenrate ist ein probates Mittel, um den Eingangspuffer wieder leer zu bekommen, damit er sich wieder mit neuen und hoffentlich nützlichen Daten füllen kann.

Dein Code ist nicht darauf ausgelegt, vernünftig mit dem Fall umzugehen, dass plötzlich irgendwann nur noch ein "halber, angefangener Code" aus dem Eingangspuffer gezogen werden kann und der Rest fehlt. Und da Dein Code damit nicht umgehen kann, ist es dann am vernünftigsten, den ganzen Buffer-Overrun-mit-Codequatsch im Eingangspuffer wegzuschmeißen und den Puffer wieder freizuräumen, so dass sich der Puffer danach wieder mit solchen Daten füllen kann, mit denen Dein Code was anfangen kann.

michael_x

Quote
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.


Kleiner Einspruch: Sicher können auf seriellen Leitungen Zeichen verloren gehen.
read() blockiert aber nicht, sondern liefert -1, was zu einem ungültigen Code führt und sich mit der nächsten Start-Kennung ( 0x02 ) wieder synchronisiert. 

Code: [Select]
  while (inChar = Rfid.read() != 2)   
  {
  } 

Vermutlich weiss Lorenz gar nicht, dass dies der beste Teil seines Codes ist ;) 
(Zusammen mit der Tatsache, dass der rfid-Reader ein Start-Zeichen hat und irgendwann aufhört zu senden, wenn kein Tag in der Nähe ist.)

pylon

Quote
Kleiner Einspruch: Sicher können auf seriellen Leitungen Zeichen verloren gehen.
read() blockiert aber nicht, sondern liefert -1, was zu einem ungültigen Code führt und sich mit der nächsten Start-Kennung ( 0x02 ) wieder synchronisiert.


Stimme ich grundsätzlich zu, aber die ungültigen Codes sind ja gerade sein Problem (deshalb die mehrfachen roten Blinksignale). Oder habe ich das immer noch falsch verstanden? Wenn ein Byte als -1 eingelesen wird, dann wird ein gültiges Tag zu einem ungültigen (rotes Blinksignal), das nächste richtige Einlesen des gültigen Tags führt dann wieder zu einem grünen Signal, ein -1 an einer anderen Stelle zu einem erneuten roten Signal. Nach seiner Beschreibung sieht er genau diese Symptome.

jurs


Stimme ich grundsätzlich zu, aber die ungültigen Codes sind ja gerade sein Problem (deshalb die mehrfachen roten Blinksignale). Oder habe ich das immer noch falsch verstanden? Wenn ein Byte als -1 eingelesen wird, ...


Damit hat er überhaupt keine Probleme, denn in seinem Code wartet er immer auf das Startzeichen (ASCII-2) vom Reader, busy waiting bis das erste Zeichen mit dem Startcode da ist. Und nach dem Senden des Startcodes macht der Reader ja keine Pause, sondern sendet hintereinander weg insgesamt 14 Zeichen.

Der gepostete Code wartet einfach jedesmal 10ms auf jedes weitere der 12 folgenden Zeichen. Damit ist er ganz weit auf der sicheren Seite, denn der Reader sendet seine 14 Zeichen natürlich nacheinander weg mit 9600 Baud, d.h. ca. 960 Zeichen pro Sekunde oder fast 10 Zeichen in 10 Millisekunden. Sobald er den Startcode am Arduino detektiert hat ist ca. 20 Millisekunden später der gesamte Readercode im seriellen Eingangspuffer angekommen. Wenn er sein Programm beschleunigen wollte, könnte er statt vor jedem der 12 Zeichen 10 ms mit dem Auslesen zu warten (Gesamt-Wartezeit 120ms) auch einmalig 25ms (mit ausreichend Zeitpuffer) warten und dann sogar alle Zeichen auf einen Rutsch auslesen, weil sie dann bei 9600 Baud Datenrate bereits im seriellen Eingangspuffer vorhanden sind.
Code: [Select]

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

delay(25);
for (x = 0; x < 12; x++)

    inChar = Rfid.read();
    msg[x] = inChar;
}
msg[12] = 0;

pylon

Quote
Damit hat er überhaupt keine Probleme,


Also in gut 12ms sind die 12 Zeichen beim Arduino. Danach sendet der Reader wahrscheinlich gleich wieder die nächsten Zeichen. In den 120ms, die der gepostete Code mit Warten zubringt, können also über 100 Zeichen übertragen worden sein. Der Eingangspuffer einer SoftwareSerial-Instanz ist 64 Zeichen gross (Ringpuffer), somit werden bereits die ersten Zeichen überschrieben sein, bevor die 12 Zeichen fertig ausgelesen sind. Ist das keine Race-Condition? Gibt das keine Probleme? Hier streite ich nicht mal mehr über einwandfrei, das ist schlicht absolut unzuverlässig.

Die einzig richtige Vorgehensweise ist, zu warten bis ein Zeichen empfangen wurde und es dann auszulesen. Fixe Wartezeiten sind bei seriellen Schnittstellen nie eine gute Idee!

jurs


Der Eingangspuffer einer SoftwareSerial-Instanz ist 64 Zeichen gross (Ringpuffer), somit werden bereits die ersten Zeichen überschrieben sein, bevor die 12 Zeichen fertig ausgelesen sind.


Ach was, die ersten 63 Zeichen, die in den seriellen Eingangspuffer reingespeichert werden, können da in jedem Fall auch wieder ausgelesen werden, selbst wenn zwischendurch ein Buffer-Overrun auftritt. Die Zeichen, die auf einen vollen Eingangspuffer treffen, gehen verloren, aber sie überschreiben nicht die bereits im Eingang befindlichen Zeichen.

pylon

Das ist korrekt, hatte ich falsch in Erinnerung, habe es aber im Code nachgeprüft.

Mein Argument zieht trotzdem. Auch wenn es die ersten 5 Durchgänge möglicherweise noch so durchgeht, kommen dann Zeichen in mehr oder weniger zufälliger Originalposition an. Wenn ein Zeichen gelesen wird, wird ja wieder eine Position im Puffer frei. Somit wird das Zeichen das vom Reader gerade gesendet wird, an diese Position geschrieben. Da danach 10ms gewartet wird, ist die nächste Position die nicht verworfen wird, mehr oder weniger zufällig.

Go Up