Elkezdem építeni az első Arduino projektemet, de néhány probléma merül fel a soros kommunikációval.
Soros adatokat kapok a konzolról, és egy “data” nevű char tömbben tárolom.
Ezután, amikor új konzolos üzenetet küldök az Arduino-nak, azt akarom, hogy törölje a a meglévő “data” tömb és csak az új adatokat tárolja abban a tömbben.
Nem értem pontosan, mi a baj a kódommal: úgy gondolom, hogy a beágyazott Serial.available () utasítások nem működnek de nincs ötletem a kód javításáról.
Az Arduino megfelelően tárolja az adatokat, de összefűzi az újabb sztringet a régivel.
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); }
Előre is köszönöm!
Válasz
Egy tömb törléséhez tegye a következőket:
for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0;
vagy
memset(data, 0, sizeof(data));
, amely ugyanazt csinálja egy könyvtár függvény használatával.
Azonban azért, mert húrok karaktert (itt nem hivatkozva a “String” objektumokra) nulla bájttal zárja le, csak az első bájtot kell nullázni:
data[0] = (char)0;
megteszi .
Válasz
Először is ez egy kiváló példa, miért fontos a szóköz. A kódod nagyon nehéz elolvasni, ahogy van, a rajta való áthúzás másodiknak tűnik, ha az utasítás kívül esik az elsőn.
Javított kód:
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); }
Emellett úgy tűnik, hogy a” Parancs kapott: “minden iterációt kiírja, függetlenül attól, hogy vannak-e új adatok vagy sem (bár ez lehet a tervezett funkció).
Mint említettük, nem “törölheti a változót, csak létrehoz egy újat. A probléma megoldásához törölnie kell a és reset count
elemeket. Ha a második parancs rövidebb, mint a parancs, akkor a számláló visszaállítása nem fog működni. előtt.
Ezenkívül miért bonyolítja a kódot a dataComplete
változóval? Az alábbi kódot egyszerűsítettem:
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); }
Válasz
Ez valószínűleg nem “t” tedd azt, amit szeretnél:
Serial.println("There is data already, clearing..."); char data[30];
A kimeneted szerint tisztítod a data
tömböt, de “nem csinál ilyet. Valójában egy iv új = data
nevű helyi változót deklarál, amely független a globális data
től már deklarálta a program tetején. A helyi változók csak abban a körben léteznek, amelyben deklarálták (a legközelebbi bezáró { }
belül).
Ehelyett a count
változó nyomon követi, hogy mennyi adatot kapott. Tehát tegye a következőket:
Serial.println("There is data already, clearing..."); count = 0;
Nem csak ez okozhatja a program váratlan működését, de legalább meg kell oldania a a kérdésed.
Megjegyzések
Válasz
A kérdés lényegéhez szólni , és amit a szerző megpróbált megvalósítani.
A kódok egyike sem működik egészében. Az adatok túllépnének az írtakon, és folyamatosan folytatnák a hurkolást … amúgy itt van egy működő példa az eredeti kódra.
Ez a módszer inkább egy tömböt töröl:
for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0;
Íme egy működő példa. (Ügyeljen arra, hogy a soros monitoron válassza a Carriage Return lehetőséget)
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; } } }
Válasz
Olvastam az összes megjegyzést erről a kérdésről, de az összes kód megosztott volt. Ezt követően létrehozok egy egyszerű függvényekkel rendelkező kódot, kevesebb sorral. ebben az esetben azt hiszem, hogy ez a kód jól fog működni
ha az átviteli sebességet 115200 alatt állítja be, akkor hozzá kell adnia a delay () értéket az üzenet char tömbbe mentéséhez
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); }
Megjegyzések
-
char data[] = {};
nulla hosszúságú tömböt kap. Rossz ötlet megpróbálni adatokat betenni. - Egyetértek a @NickGammon véleményével.Kérjük, szerkessze a válaszát, hogy ” helyettesítse. Azt hiszem, … jól fog működni kódot.
- @NickGammon köszönöm a javítást, átdolgoztam a kódomat
data[count]='\0';
hozzáadásadataComplete = true;