Guten Abend,
habe ein Problem mit dem Verständniss zu Serial.parseInt!
Ich sende eine Zahl in Ascii (z.B. -1000 mit einem \n am Schluss) zu
meinem uC und wandel diese in einen long. Dazu nutze ich den Seriellen
Port. Chip ist ein ATMega8.
Abfangen tu ich es mit:
if (Serial.available() > 0){
long myInt = Serial.parseInt(SKIP_ALL, '\n');
...
}
Mein Problem:
Sobald ich Serial.parseInt verwende, scheint es als würde der uC sich
eine Gedenksekunde gönnen und wird blockiert. Benötigt Serial.parseInt
tatsächlich so viel Leistung oder fährt es in einen TimeOut?
Die Wandlung funktioniert nämlich wie ich es möchte. Nur diese ewige
Pause möchte ich vermeiden, da eine andere Aufgabe dann stehen bleibt.
Wenn ich hingegen:
long myInt = -1000;
schreibe, mehkt man keine Verzögerung (und kann auch keine mit dem Sozi
messen)!
Könnte es daran liegen, dass das Endzeichen nicht erkannt wird und statt
dessen ein Timeout ausgelöst wird? Oder dass das Endzeichen erkannt
wird, aber noch ein zusätzliches Zeichen in der Pipe steckt, welches
dann den Timeout auslöst?
https://www.arduino.cc/reference/en/language/functions/communication/serial/parseint/
=> Serial.setTimeout()
Ansgar schrieb:> Ich sende eine Zahl in Ascii (z.B. -1000 mit einem \n am Schluss) zu> meinem uC und wandel diese in einen long. Dazu nutze ich den Seriellen> Port.> if (Serial.available() > 0){
Sobald das erste Zeichen (›-‹) empfangen wurde, wird die Abfrage wahr
und
> long myInt = Serial.parseInt(SKIP_ALL, '\n');
wird aufgerufen.
> Sobald ich Serial.parseInt verwende, scheint es als würde der uC sich> eine Gedenksekunde gönnen und wird blockiert. Benötigt Serial.parseInt
Das wartet nun solange bis alle notwendigen Zeichen empfangen wurden.
Hängt von deiner Schnittstelle ab, bei 9600 ungefähr 1ms pro Zeichen.
>Das wartet nun solange bis alle notwendigen Zeichen empfangen wurden.>Hängt von deiner Schnittstelle ab, bei 9600 ungefähr 1ms pro Zeichen.
Das Problem ist der Ausdruck "alle notwendigen Zeichen".
Ich habe es gerade mal im Wokwi-Simulator ausprobiert:
https://wokwi.com/projects/334148643034497620
Beim ersten Zeichen wird parseInt() aufgerufen. Wenn man hingereinander
1,2,3 eintippt (ohne CR,LF) geht es etwa eine Sekunde (TimeOut) und die
Zahl wird angezeigt.
chris_ schrieb:> Beim ersten Zeichen wird parseInt() aufgerufen. Wenn man hingereinander> 1,2,3 eintippt (ohne CR,LF) geht es etwa eine Sekunde (TimeOut) und die> Zahl wird angezeigt.
Wenn's in einen Timeout läuft, dann wurden eben nicht alle notwendigen
Zeichen empfangen.
Vernünftigerweise sammelt man ohne Verzögerung erst einmal eine
Eingabezeile und extrahiert dann die Informationen.
Anstelle von Serial.available() kannst mit Serial.peek() antesten, ob
das letzte empfangene Zeichen ein Zeilenumbruch war. Erst dann rufst du
Serial.parseInt() auf.
Dieses Vorgehen hat aber zwei Knackpunkte:
a) Wenn der Empfangspuffer nicht groß genug, die ganze Zahl aufzunehmen,
kommt Schrott heraus. Ich denke der Puffer von Arduino ist normalerweise
groß genug.
b) Wenn du nach dem Zeilenumbruch noch etwas anders empfangen hast, dann
ist das letzte Zeichen eben kein Zeilenumbruch. Dadurch "verpasst" du
unter Umständen eine komplette Zeile.
Um es besser zu machen habe ich folgende Prozedur geschrieben:
1
/**
2
* Append characters from a stream to the buffer until the terminator has been found.
3
* In case of buffer overflow, read until the terminator but skip all characters that
4
* do not fit into the buffer.
5
* @param source The source stream.
6
* @param buffer The target buffer, must be terminated with '\0'.
7
* @param bufSize Size of the buffer.
8
* @param terminator The last character that shall be read from the stream, e.g. '\n'.
9
* @return True if the terminator has been reached, false if the stream did not contain the terminator.
>>https://wokwi.com/projects/334148643034497620>Wenn's in einen Timeout läuft, dann wurden eben nicht alle notwendigen>Zeichen empfangen.
Das ist erst mal eine "Schlafschulweisheit". Die Probleme liegen hier
tiefer.
Wenn du den obigen Simulatorlink ausprobierst, kannst du sehen, dass
beim Drücken der Return-Taste eine unnötige '0' als geparster Integer im
Ausgabefenster auftaucht.
chris_ schrieb:>>>https://wokwi.com/projects/334148643034497620>>Wenn's in einen Timeout läuft, dann wurden eben nicht alle notwendigen>>Zeichen empfangen.>> Das ist erst mal eine "Schlafschulweisheit". Die Probleme liegen hier> tiefer.> Wenn du den obigen Simulatorlink ausprobierst, kannst du sehen, dass> beim Drücken der Return-Taste eine unnötige '0' als geparster Integer im> Ausgabefenster auftaucht.
Es wird gemunkelt das lesen hilft:
1
parseInt() returns the first valid (long) integer number from the serial buffer. Characters that are not integers (or the minus sign) are skipped.
2
3
In particular:
4
5
Initial characters that are not digits or a minus sign, are skipped;
6
Parsing stops when no characters have been read for a configurable time-out value, or a non-digit is read;
7
If no valid digits were read when the time-out (see Stream.setTimeout()) occurs, 0 is returned;
>cr ist \r und nicht \n.>Du gibst cr lf über das Terminal ein.
Das wiederum ist der Grund vieler Fehler bei der Datenübertragung
zwischen Unix- und Windowssystemen.
Die Frage ist, ob Ansgar hier ein Unix- oder Windows System benutzt. Im
Eingangspost schreibt er nur \n ohne \r. Beim Simulator im Browser
vermute ich, dass er unabhängig vom Betriebssystem CR/LF beim Drücken
der Returntaste erzeugt.
>They are used to mark a line break in a text file. As you indicated, >Windows
uses two characters the CR LF sequence; Unix only uses LF and the >old MacOS (
pre-OSX MacIntosh) used CR.
aus
https://stackoverflow.com/questions/1552749/difference-between-cr-lf-lf-and-cr-line-break-types
Stefan ⛄ F. (stefanus)
>Anstelle von Serial.available() kannst mit Serial.peek() antesten, ob>das letzte empfangene Zeichen ein Zeilenumbruch war. Erst dann rufst du>Serial.parseInt() auf.
Vermutlich ist deine Lösung die sauberste. Schade, dass man es so selber
implementieren muss. ParseInt scheint für viele Anwendungen ungeeignet
und bedürfte dahingehend einer besseren Implemtierung mit der Erkennung
eines "Terminator"-Zeichens.