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
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
data[count]='\0';
podataComplete = true;