Ich beginne mit der Erstellung meines ersten Arduino-Projekts, habe jedoch Probleme mit der seriellen Kommunikation.
Ich erhalte serielle Daten von der Konsole und speichere sie in einem char-Array namens „data“.
Wenn ich dann eine neue Konsolennachricht an das Arduino sende, soll diese gelöscht werden vorhandenes „Daten“ -Array und speichere nur die neuen Daten in diesem Array.
Ich verstehe nicht genau, was mit meinem Code falsch ist: Ich glaube, dass diese verschachtelten Serial.available () -Anweisungen nicht funktionieren Ich habe jedoch keine Ahnung, wie der Code repariert werden soll.
Daten werden vom Arduino korrekt gespeichert, verketten jedoch die neuere Zeichenfolge mit der alten.
int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0){ if (dataComplete == true){ Serial.println("There is data already, clearing..."); char data[30]; dataComplete = false; } if (dataComplete == false){ Serial.println("New command, collecting..."); while (Serial.available()>0){ char character = Serial.read(); data[count] = character; count++; } dataComplete = true; } } Serial.print("Command received: "); Serial.println(data); delay(1000); }
Vielen Dank im Voraus!
Antwort
Um ein Array zu löschen, gehen Sie wie folgt vor:
for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0;
oder
memset(data, 0, sizeof(data));
, was dasselbe mit einer Bibliotheksfunktion tut.
Allerdings, weil Zeichenfolgen Die Anzahl der Zeichen (die sich hier nicht auf „String“ -Objekte beziehen) wird durch ein Null-Byte abgeschlossen. Es muss nur das erste Byte auf Null gesetzt werden:
data[0] = (char)0;
erledigt dies .
Antwort
Zunächst einmal ist dies ein ausgezeichnetes Beispiel, warum Leerzeichen wichtig sind. Ihr Code ist wirklich schwer zu lesen, da er überflogen wird. Es scheint, als ob die zweite if-Anweisung außerhalb der ersten liegt.
Fester Code:
int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available() > 0){ if (dataComplete == true){ Serial.println("There is data already, clearing..."); char data[30]; dataComplete = false; } if (dataComplete == false){ Serial.println("New command, collecting..."); while (Serial.available()>0){ char character = Serial.read(); data[count] = character; count++; } dataComplete = true; } } Serial.print("Command received: "); Serial.println(data); delay(1000); }
Außerdem scheint es, als würde“ Befehl empfangen: „jede Iteration gedruckt, unabhängig davon, ob neue Daten vorhanden sind oder nicht (obwohl dies die beabsichtigte Funktion sein könnte).
Wie bereits erwähnt, löschen Sie die Variable nicht, sondern erstellen einfach eine neue. Sie müssen löschen und count
zurücksetzen, um dieses Problem zu beheben. Das Zurücksetzen der Anzahl funktioniert jedoch nicht, wenn der zweite Befehl kürzer als der eine ist vorher.
Warum komplizieren Sie den Code auch mit der Variablen dataComplete
? Ich habe den folgenden Code vereinfacht:
int count = 0; char data[30]; boolean dataComplete = false; void setup() { Serial.begin(9600); } void loop() { if (Serial.available()){ Serial.println("New command, collecting..."); count = 0; data[] = ""; while (Serial.available()){ char character = Serial.read(); data[count] = character; count++; } } Serial.print("Command received: "); Serial.println(data); delay(1000); }
Antwort
Dies ist wahrscheinlich nicht der Fall Tun Sie, was Sie beabsichtigen:
Serial.println("There is data already, clearing..."); char data[30];
Ihre Ausgabe besagt, dass Sie das Array data
löschen, aber Sie „Ich mache so etwas nicht. Tatsächlich deklarieren Sie eine neue lokale Variable mit dem Namen data
, die unabhängig von der globalen data
Sie ist haben bereits oben in Ihrem Programm deklariert. Lokale Variablen existieren nur in dem Bereich, in dem sie deklariert sind (in ihrem nächsten umschließenden { }
).
Stattdessen verfolgt Ihre Variable count
, wie viele Daten Sie empfangen haben. Gehen Sie also möglicherweise wie folgt vor:
Serial.println("There is data already, clearing..."); count = 0;
Dies ist nicht das einzige, was dazu führen kann, dass Ihr Programm unerwartet funktioniert, aber es sollte zumindest das in angegebene Problem beheben Ihre Frage.
Kommentare
- Für Daten wird auch ein Nullterminator benötigt: Fügen Sie
data[count]='\0';
nachdataComplete = true;
- Ja, das ‚ ist wahr, aber das größere Problem ist, dass es für den Absender keine Möglichkeit gibt Geben Sie das Ende einer anderen Datenübertragung als die Pause an. Und da dies seriell ist, wird es zwischen jedem übertragenen Zeichen eine ausreichend lange Pause geben.
- Vielen Dank an euch beide. Mein Code war falsch und das Ändern in “ count = 0 “ hat funktioniert. Ich habe auch ein Trennzeichen hinzugefügt, um das Ende eines Eingabebefehls anzuzeigen, und es funktioniert jetzt wie beabsichtigt. Die einzige Möglichkeit, das Array “ data “ zu leeren, war die Verwendung einer for-Schleife, wie von @JRobert angegeben: auf diese Weise neuer Befehle funktionieren auch dann, wenn sie kürzer als ältere sind.
Antwort
Um auf den Punkt der Frage zu sprechen und was der Autor versucht hat zu erreichen.
Keiner dieser Codes funktioniert tatsächlich als Ganzes. Die Daten würden überschrieben und würden einfach weiterlaufen … trotzdem ist hier ein funktionierendes Beispiel für den Originalcode.
Bei dieser Methode lösche ich lieber ein Array:
for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0;
Hier ist ein Arbeitsbeispiel. (Stellen Sie sicher, dass auf dem seriellen Monitor Wagenrücklauf ausgewählt ist.)
char message[32]; uint8_t incomingByte = 0; uint8_t BufferPos = 0; int clearbyte = 0; void setup() { Serial.begin(9600); Serial.println("\n String conversion testing"); } void loop() { if (BufferPos >= 32) { Serial.print("Buffer Full\n"); BufferPos = 00; incomingByte = 0; } if (Serial.available()) { incomingByte = Serial.read(); message[BufferPos++]= incomingByte; switch(incomingByte) { case "\n": case " ": break; case "\r": Serial.println(message); for( int i = 0; i < sizeof(message); ++i ) message[i] = (char)0; BufferPos= 0; incomingByte= 0; } } }
Antwort
Ich habe alle Kommentare zu dieser Frage gelesen, aber alle Codes wurden so ausführlich geteilt. Danach erstelle ich einen Code mit einfachen Funktionen und weniger Zeilen. In diesem Fall denke ich, dass dieser Code gut funktioniert.
Wenn Sie die Baudrate unter 115200 einstellen, muss delay () hinzugefügt werden, um die Nachricht im char-Array zu speichern.
void loop() { char data[255]; uint8_t k = 0; while (Serial.available()) { data[k] = Serial.read(); k++; } for (int i = 0; i < k; i++) { Serial.print(data[i]); data [i] = "\0"; } //delay(50); }
Kommentare
-
char data[] = {};
gibt Ihnen ein Array mit der Länge Null. Der Versuch, Daten darin abzulegen, ist eine schlechte Idee. - Ich stimme @NickGammon zu.Bitte bearbeiten Sie Ihre Antwort, um “ zu ersetzen. Ich denke … wird “ durch ein definitives Ja / Nein funktionieren, sobald Sie das getestet haben Code.
- @NickGammon danke für die Korrektur, ich habe meinen Code überarbeitet