Hallo,
kann man eine while-Schleife vorzeitig verlassen (Abbruchbedingung) und falls nicht, was wäre die Alternative?
Gruß Chris
Hallo,
kann man eine while-Schleife vorzeitig verlassen (Abbruchbedingung) und falls nicht, was wäre die Alternative?
Gruß Chris
Die While-Schleife hat doch eine Laufbedingung. Die musst Du nur entsprechend formulieren.
Ansonsten gibt es noch break.
Die nächste Frage wäre, wozu Du while brauchst, wenn Du doch loop hast?
Gruß Tommy
Hi Tommy56,
was meinst Du mit "loop"?
Zur Info: Hier soll nach eintreffen eines CR nicht mehr weiter eingelesen werden:
if (Serial.available()) // Sobald seriell ein Zeichen ankam..
{
delay (10); // Kurz warten
while (Serial.available()) // So lange es noch nicht ausgelesene Zeichen gibt
{
c = Serial.read(); // Zeichen einzeln auslesen
if (c > 32 or c == 13) // Nur Return und Zeichen oberhalb der Leertaste (032d) auslesen
{
commandbuffer[i] = c; // Zeichen in den Buffer schreiben
i++; // Schreibindex um eins erhöhen
}
}
}
Gruß Chris
Das Endzeichen sollte man nicht abspeichern. Das ist nur ein Steuerzeichen. Eher solltest du aufpassen dass du nicht über den Puffer hinaus schreibst
So geht es:
char* readSerial(Stream& stream)
{
static byte index;
static char serialBuffer[SERIAL_BUFFER_SIZE];
while (stream.available())
{
char c = stream.read();
if (c == '\r' && index > 0)
{
serialBuffer[index] = '\0';
index = 0;
return serialBuffer;
}
else if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
{
serialBuffer[index++] = c;
}
}
return NULL; //noch nicht fertig
}
Einfach return wenn das Endzeichen eingelesen wurde. Geht auch mit true/false wenn man das Array global hat
Bei der ganzen Sache auch beachten wie langsam die serielle Übertragung ist. In der Regel wird die while-Schleife gar nicht richtig ausgeführt und bricht gleich wieder ab. Jedenfalls wenn man loop() richtig programmiert.
Aufgerufen wird das dann so (editiert damit man auch den Text abfragen kann):
void loop()
{
char* str = readSerial(Serial);
if(str != NULL) //oder: if(str)
{
....
}
}
Also immer wieder aufrufen. Nicht nur einmal. Sobald was anderes als NULL kommt ist man fertig.
Dann braucht man kein delay(10). Außerdem hängt diese Wartezeit von der Baudrate und der Länge des Strings ab. Daher ist da was festest auch schlecht
Wenn Du nicht weist, was loop ist, solltest Du ganz an den Anfang zurück gehen (gehe nicht über Los, zihe nicht 4000€ ein).
Du kannst doch in jedem Loop-Durchlauf (wenn loop nicht blockiert) ein Zeichen einlesen, bis Du auf '\n' stößt. Ein Beispiel dazu habe ich hier gezeigt.
Gruß Tommy
Um Sereniflys Beitrag noch narrensicherer zu machen:
Statt des NeueZeile-Endezeichen mit abzuspeichern wird der Text mit einem Null-Byte abgeschlossen.
Ausserdem bekommt der Aufrufer, wenn fertig, den Text geliefert.
void loop() {
if(char* msg = readSerial(Serial)) {
// msg enthält die gelesene Zeile ....
}
}
Das = ist eine Wertzuweisung, kein Vergleich
Ja, Rückgabewert muss man da abspeichern damit man auch an den Wert kommt. Ohne das ist das eher für ein globales Array
Es geht zwar mittlerweile nun nicht mehr nur um eine while-Schleife, möchte aber trotzdem zu dem mit viel Copy-and-paste zusammengewürfelten Code ein paar Fragen stellen.
const int SERIAL_BUFFER_SIZE = 38;
char serialBuffer[SERIAL_BUFFER_SIZE];
void setup()
{
Serial.begin(9600);
Serial.print("Start!");
}
void loop()
{
char* str = readSerial(); // Serielle Schnittstelle auslesen
if (str != NULL)
parseSerial(str);
}
char* readSerial() //String bilden. Gibt NULL zurück wenn noch nicht fertig. Wenn fertig einen Zeiger auf den Puffer
{
static byte index;
while (Serial.available())
{
char c = Serial.read();
if (c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
{
serialBuffer[index++] = c;
}
else if (c == '\r' && index > 0)
{
serialBuffer[index] = '\0';
index = 0;
Serial.println(serialBuffer);
return serialBuffer;
}
}
return NULL; //noch nicht fertig
}
char* parseSerial(char* str) //String verarbeiten
{
if (strstr(serialBuffer, "prio") == serialBuffer) // Steht am Anfang des Strings "prio"?
{
Serial.print("prio zu Beginn des Strings erkannt.");
// Folgt ein Komma?
// Folgt eine Zahl?
// Folgt Return?
}
else if (strcmp(serialBuffer, "") != 0)
{
Serial.print("Unbekanntes Kommando: ");
Serial.println(serialBuffer);
}
}
Grundsätzlich funktioniert das Konstrukt, aber nun zu den Fragen:
Die Verwendung von Zeigern im Rahmen dieses Sketches verstehe ich nicht.
Gruß Chris
Da serialBuffer global ist, könntest Du das für 1. tun.
Merksatz: Der Name eines Arrays ist ein Zeiger auf sein erstes Element.
Gruß Tommy
- Ist es so, dass die Zeile char* parseSerial(char* str) in void parseSerial() geändert werden könnte?
Nein. Die Funktion muss melden wenn sie fertig ist! Wenn man keinen Zeiger zurück gibt muss der Rückgabewert bool sein
Beim Zeiger gibt man entweder NULL zurück wenn man nicht fertig ist oder einen Zeiger auf den Puffer wenn ja