Wyczyść istniejącą tablicę po otrzymaniu nowego polecenia szeregowego

Zaczynam budować mój pierwszy projekt Arduino, ale mam problemy z komunikacją szeregową.

Otrzymuję dane szeregowe z konsoli i przechowuję je w tablicy znaków o nazwie „dane”.

Następnie, kiedy wysyłam nową wiadomość z konsoli do Arduino, chcę, aby wyczyściła istniejąca tablica „data” i przechowuj tylko nowe dane w tej tablicy.

Nie rozumiem dokładnie, co jest nie tak z moim kodem: uważam, że te zagnieżdżone instrukcje Serial.available () nie działają ale nie mam pomysłu, jak naprawić kod.

Dane są prawidłowo przechowywane przez Arduino, ale łączy nowszy ciąg ze starym.

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

Z góry dziękuję!

Odpowiedź

Aby wyczyścić tablicę, zrobiłbyś:

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

lub

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

, który robi to samo, używając funkcji biblioteki.

Jednak ponieważ ciągi znaków (nie odnoszących się tutaj do obiektów „String”) jest zakończonych bajtem zerowym, wystarczy wyzerować tylko pierwszy bajt:

data[0] = (char)0; 

zrobi to .

Odpowiedź

Po pierwsze, jest to doskonały przykład znaczenia białych znaków. Twój kod jest naprawdę trudny do odczytania w obecnej postaci, ponieważ przeglądając go, wydaje się, że jest to drugie, jeśli instrukcja jest poza pierwszą.

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

Wydaje się również, że wypisuje” Polecenie otrzymane: „w każdej iteracji, niezależnie od tego, czy są nowe dane, czy nie (chociaż może to być zamierzona funkcja).

Jak wspomniano, nie czyści się zmiennej, po prostu tworzysz nową. Aby rozwiązać ten problem, musisz wyczyścić i zresetować count. Jednak samo zresetowanie licznika nie zadziała, jeśli drugie polecenie jest krótsze niż przed.

Poza tym, dlaczego komplikujesz kod za pomocą zmiennej dataComplete? Uprościłem poniższy kod:

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

Odpowiedź

To prawdopodobnie nie „t zrób to, co zamierzasz:

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

Dane wyjściowe informują, że czyścisz tablicę data, ale „nie robię czegoś takiego. W rzeczywistości deklarujesz nową zmienną lokalną o nazwie data, która jest niezależna od globalnej data już zadeklarowałeś na początku swojego programu. Zmienne lokalne istnieją tylko w zakresie, w którym zostały zadeklarowane (wewnątrz najbliższego otaczającego { }).

Zamiast tego, zmienna count śledzi ilość otrzymanych danych. Więc może wykonaj następujące czynności:

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

Nie jest to jedyna rzecz, która może spowodować nieoczekiwane działanie programu, ale powinna przynajmniej rozwiązać problem opisany w Twoje pytanie.

Komentarze

  • Dla danych potrzebny jest również terminator o wartości zerowej: Dodaj data[count]='\0'; po dataComplete = true;
  • Tak, to ' jest prawdą, ale większym problemem jest to, że nadawca nie ma możliwości wskazują koniec transmisji danych inny niż pauza. A ponieważ jest to serial, będzie wystarczająco długa przerwa między każdym wysłanym znakiem.
  • Dziękuję wam obojgu. Mój kod był nieprawidłowy i zmiana go na ” count = 0 ” zadziałała. Dodałem również ogranicznik, aby wskazać koniec polecenia wejściowego i teraz działa zgodnie z przeznaczeniem. Jednak jedynym sposobem, który działał w celu opróżnienia tablicy ” danych „, było użycie pętli for, jak wskazuje @JRobert: w ten sposób nowszy polecenia działają, nawet jeśli są krótsze niż starsze.

Odpowiedź

Aby mówić do sedna pytania i co autor próbował osiągnąć.

Żaden z tych kodów nie działa w rzeczywistości jako całość. Dane zostałyby nadpisane i po prostu zapętliłyby się w sposób ciągły … w każdym razie oto działający przykład oryginalnego kodu.

Ta metoda wolę wyczyścić tablicę:

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

Oto działający przykład. (Pamiętaj, aby wybrać powrót karetki na monitorze szeregowym)

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

Odpowiedź

Przeczytałem wszystkie komentarze do tego pytania, ale wszystkie kody były tak wymowne. Następnie tworzę kod z prostymi funkcjami i mniejszą liczbą wierszy. w tym przypadku myślę, że ten kod będzie działał dobrze

jeśli ustawisz szybkość transmisji poniżej 115200, musisz dodać opóźnienie (), aby zapisać wiadomość w tablicy znaków

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

Komentarze

  • char data[] = {}; zwróci tablicę o zerowej długości. Próba umieszczenia w nim danych to zły pomysł.
  • Zgadzam się z @NickGammon.Zmień swoją odpowiedź i zastąp ” Myślę, że … będzie działać dobrze ” definitywnym tak / nie, po przetestowaniu kod.
  • @NickGammon dzięki za poprawkę, sprawdziłem mój kod

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *