Ștergeți matricea existentă când primiți o nouă comandă serială

Încep să construiesc primul meu proiect Arduino, dar întâmpin unele probleme cu comunicarea serială.

Obțin date seriale de pe consolă și le stochez într-o matrice de caractere numită „date”.

Apoi, când trimit un nou mesaj de consolă către Arduino, vreau să șterge matricea „de date” existentă și stochează doar noile date în matricea respectivă.

Nu înțeleg exact ce e în neregulă cu codul meu: cred că acele declarații imbricate Serial.available () nu funcționează dar nu am idei despre cum să repar codul.

Datele sunt stocate corect de Arduino, dar concatenează șirul mai nou cu cel vechi.

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); } 

Vă mulțumim anticipat!

Răspundeți

Pentru a șterge o matrice, veți face:

for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0; 

sau

memset(data, 0, sizeof(data)); 

, care face același lucru folosind o funcție de bibliotecă.

Cu toate acestea, pentru că șirurile de caractere (care nu se referă la obiectele „Șir” aici) sunt terminate cu un octet zero, doar primul octet trebuie zero:

data[0] = (char)0; 

o va face .

Răspuns

În primul rând, acesta este un exemplu excelent de ce contează spațiul alb. Codul dvs. este într-adevăr greu de citit așa cum este, întrucât, deasupra acestuia, pare ca al doilea, dacă instrucțiunea se află în afara primei.

Cod fix:

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); } 

De asemenea, se pare că se imprimă” Comandă primită: „fiecare iterație, indiferent dacă există sau nu date noi (deși, aceasta ar putea fi caracteristica intenționată).

Așa cum am menționat, nu ștergeți variabila, doar creați una nouă. Va trebui să ștergeți și resetați count pentru a remedia această problemă. Cu toate acestea, doar resetarea numărului nu va funcționa dacă a doua comandă este mai scurtă decât cea înainte.

De asemenea, de ce complicați codul cu variabila dataComplete? Am simplificat codul de mai jos:

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); } 

Răspuns

Probabil că nu faceți ceea ce intenționați să faceți:

Serial.println("There is data already, clearing..."); char data[30]; 

Rezultatul dvs. spune că ștergeți matricea data, dar dvs. Nu faci așa ceva. De fapt, declarați o nouă variabilă locală numită data, care este independentă de data global deja ați declarat în partea de sus a programului dvs. Variabilele locale există numai în domeniul în care sunt declarate (în cea mai apropiată incintă { }).

În schimb, variabila dvs. count ține evidența numărului de date pe care le-ați primit. Așadar, faceți următoarele:

Serial.println("There is data already, clearing..."); count = 0; 

Acesta nu este singurul lucru care ar putea determina programul dvs. să funcționeze în mod neașteptat, dar ar trebui cel puțin să rezolve problema enunțată în întrebarea dvs.

Comentarii

  • De asemenea, este necesar un terminator nul pentru date: Adăugați data[count]='\0'; după dataComplete = true;
  • Da, ‘ este adevărat, dar problema mai mare este că nu există nicio modalitate prin care expeditorul indicați sfârșitul unei transmisii de date, altul decât să faceți o pauză. Și din moment ce acesta este serial, va exista o pauză suficient de lungă între fiecare caracter transmis.
  • Mulțumesc amândurora. Codul meu a fost greșit și s-a schimbat în ” count = 0 ” a funcționat. Am adăugat, de asemenea, un delimitator pentru a indica sfârșitul unei comenzi de intrare și funcționează așa cum se intenționează acum. Cu toate acestea, singura modalitate care a funcționat pentru golirea ” date ” a fost utilizarea unei bucle for, așa cum a indicat @JRobert: în acest fel comenzile funcționează chiar dacă sunt mai scurte decât cele mai vechi.

Răspuns

Pentru a vorbi la punctul întrebării și ceea ce autorul a încercat să realizeze.

Niciunul dintre aceste coduri nu funcționează de fapt ca întreg. Datele vor fi scrise și ar continua să se bucle continuu … oricum iată un exemplu de lucru al codului original.

Această metodă prefer să șterg un tablou:

 for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0; 

Iată un exemplu de lucru. (Asigurați-vă că selectați Carriage Return pe monitorul serial)

 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; } } } 

Răspuns

Am fost citite toate comentariile la această întrebare, dar toate codurile au fost partajate atât de verbal. După aceea, creez un cod cu funcții simple și mai puține linii. în acest caz, cred că acest cod va funcționa bine

dacă setați baudrate sub 115200, trebuie să fie add delay () pentru salvarea mesajului în matricea de caractere

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); } 

Comentarii

  • char data[] = {}; vă va oferi o matrice de lungime zero. Încercarea de a introduce date este o idee proastă.
  • Sunt de acord cu @NickGammon.Vă rugăm să modificați răspunsul pentru a înlocui ” Cred că … va funcționa bine ” cu un da / nu definitiv, după ce ați testat cod.
  • @ NickGammon mulțumesc pentru corectare, am fost revizuit codul meu

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *