Jag börjar bygga mitt första Arduino-projekt men jag stöter på problem med seriell kommunikation.
Jag får seriell data från konsolen och lagrar den i en char-array som heter ”data”.
Sedan, när jag skickar ett nytt konsolmeddelande till Arduino, vill jag att det ska rensa befintlig ”data” array och lagrar bara de nya data i den arrayen.
Jag förstår inte exakt vad som är fel med min kod: Jag tror att de kapslade Serial.available () uttalandena inte fungerar men jag har inga idéer för hur jag ska fixa koden.
Data lagras korrekt av Arduino men det sammanfogar den nyare strängen till den gamla.
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); }
Tack på förhand!
Svar
För att rensa en matris skulle du göra:
for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0;
eller
memset(data, 0, sizeof(data));
, vilket gör samma sak med hjälp av en biblioteksfunktion.
Men eftersom strängar av tecken (som inte hänvisar till ”String” -objekt här) avslutas med en nollbyte, bara den första byten behöver nollställas:
data[0] = (char)0;
gör det .
Svar
Först och främst är detta ett utmärkt exempel på varför det stora utrymmet är viktigt. Din kod är väldigt svår att läsa som den är, eftersom den skummar över den verkar som den andra om uttalandet ligger utanför det första.
Fast kod:
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); }
Det verkar också som om det skrivs ut” Kommando mottaget: ”varje iteration, oavsett om det finns nya data eller inte (även om detta kan vara den avsedda funktionen).
Som nämnts, ömmer du inte variabeln, du skapar bara en ny. Du måste rensa och återställa count
för att åtgärda problemet. Men bara att återställa antalet kommer inte att fungera om det andra kommandot är kortare än det innan.
Varför komplicerar du också koden med variabeln dataComplete
? Jag förenklade koden nedan:
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); }
Svar
Detta gör förmodligen inte ”t gör vad du tänker göra:
Serial.println("There is data already, clearing..."); char data[30];
Din utdata säger att du rensar data
-arrayen, men du ”gör inget sådant. Du förklarar faktiskt en ny lokal variabel som heter data
, som är oberoende av den globala data
du redan har deklarerat högst upp i ditt program. Lokala variabler finns bara inom det omfång inom vilket de deklareras (i deras närmaste omslutande { }
).
I stället håller din count
variabel reda på hur mycket data du har fått. Så gör kanske följande:
Serial.println("There is data already, clearing..."); count = 0;
Detta är inte det enda som kan få ditt program att fungera oväntat, men det borde åtminstone åtgärda problemet som anges i din fråga.
Kommentarer
Svar
Att tala till punkten i frågan , och vad författaren försökte åstadkomma.
Ingen av denna kod fungerar faktiskt som en helhet. Uppgifterna skulle bli överskrivna och bara fortsätta att kretsa kontinuerligt … hur som helst här är ett fungerande exempel på den ursprungliga koden.
Denna metod föredrar jag att rensa en array:
for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0;
Här är ett fungerande exempel. (Se till att du väljer Vagnretur på seriell bildskärm)
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; } } }
Svar
Jag fick läsa alla kommentarer på den här frågan, men alla koder var så delaktiga. Efter det skapar jag en kod med enkla funktioner och mindre linje. i det här fallet tror jag att den här koden fungerar bra
om du ställer in baudrate under 115200, måste du lägga till fördröjning () för att spara meddelande i char array
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); }
Kommentarer
-
char data[] = {};
ger dig en matris med noll längd. Att försöka lägga in data i det är en dålig idé. - Jag håller med @NickGammon.Redigera ditt svar för att ersätta ” Jag tror … kommer att fungera bra ” med ett definitivt ja / nej, när du har testat kod.
- @NickGammon tack för rättelsen, jag reviderade min kod
data[count]='\0';
efterdataComplete = true;