Aloitan ensimmäisen Arduino-projektini rakentamista, mutta minulla on joitain ongelmia sarjaliikenteen kanssa.
Saan sarjatiedot konsolista ja tallennan ne ”data” -merkkiryhmään.
Kun sitten lähetän uuden konsoliviestin Arduinolle, haluan sen tyhjentävän olemassa oleva ”data” -taulukko ja tallenna vain uudet tiedot taulukkoon.
En ymmärrä tarkalleen, mikä koodissani vikaa: Uskon, että ne sisäkkäiset Serial.available () -lausekkeet eivät toimi mutta minulla ei ole ideoita koodin korjaamisesta.
Arduino tallentaa tiedot oikein, mutta se yhdistää uudemman merkkijonon vanhaan.
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); }
Kiitos etukäteen!
Vastaa
Voit tyhjentää taulukon seuraavasti:
for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0;
tai
memset(data, 0, sizeof(data));
, joka tekee saman asian kirjastotoiminnon avulla.
Kuitenkin, koska merkkijonot merkkiä (ei viittaa tässä merkkijono-objekteihin) päättyy nollatavulla, vain ensimmäinen tavu on nollattava:
data[0] = (char)0;
tekee sen .
Vastaus
Ensinnäkin tämä on erinomainen esimerkki miksi välilyönnillä on merkitystä. Koodiasi on todella vaikea lukea sellaisenaan, sillä sen ohittaminen näyttää toiselta, jos lause on ensimmäisen ulkopuolella.
Kiinteä koodi:
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); }
Näyttää myös siltä, että se tulostaa” Komento vastaanotettu: ”kaikki iteraatiot riippumatta siitä, onko uusia tietoja vai ei (vaikka tämä voisi olla tarkoitettu ominaisuus).
Kuten mainittiin, et tyhjennä muuttujaa, vaan luot vain uuden. Sinun on tyhjennettävä ja palautettava count
ongelman korjaamiseksi. Pelkkä laskurin nollaaminen ei toimi, jos toinen komento on lyhyempi kuin yksi ennen.
Miksi monimutkaistat koodia muuttujalla dataComplete
? Yksinkertaistin alla olevaa koodia:
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); }
Vastaa
Tämä ei todennäköisesti ”t” tee se, mitä aiot tehdä:
Serial.println("There is data already, clearing..."); char data[30];
Lähdössä sanotaan, että tyhjennät data
-taulukon, mutta ”en tee mitään sellaista. Itse asiassa ilmoitat uuden paikallisen muuttujan nimeltä data
, joka on riippumaton globaalista data
sinusta olet jo ilmoittanut ohjelman yläosassa. Paikalliset muuttujat ovat olemassa vain siinä laajuudessa, jossa ne on ilmoitettu (lähimmän ympäröivän { }
sisällä).
Sen sijaan count
-muuttuja seuraa vastaanotettujen tietojen määrää. Joten tee ehkä seuraava:
Serial.println("There is data already, clearing..."); count = 0;
Tämä ei ole ainoa asia, joka saattaa aiheuttaa ohjelman odottamattoman toiminnan, mutta sen pitäisi ainakin korjata kysymyksesi.
Kommentit
Vastaa
Puhuaksesi kysymykseen asti ja mitä kirjoittaja yritti saavuttaa.
Mikään näistä koodeista ei todellakaan toimi kokonaisuutena. Tiedot pääsisivät kirjoitettujen yli ja jatkaisivat silmukointia jatkuvasti … tässä tapauksessa tässä on toimiva esimerkki alkuperäisestä koodista.
Tämä menetelmä haluan tyhjentää taulukon:
for( int i = 0; i < sizeof(data); ++i ) data[i] = (char)0;
Tässä on toimiva esimerkki. (Muista valita sarjaliikennevälineen rivinvaihto)
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; } } }
Vastaa
Luin kaikki kommentit tästä kysymyksestä, mutta kaikki koodit jaettiin niin verbosing. Sen jälkeen luon koodin, jossa on yksinkertaiset toiminnot ja vähemmän riviä. tässä tapauksessa luulen, että tämä koodi toimii hyvin
jos asetat baudrate-arvon alle 115200, on lisättävä delay () viestin tallentamiseksi char-taulukkoon
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); }
Kommentit
-
char data[] = {};
antaa sinulle nollapituisen taulukon. Tietojen yrittäminen siihen on huono idea. - Olen samaa mieltä @NickGammonin kanssa.Muokkaa vastaustasi korvaamaan ” mielestäni … toimii hyvin ” lopullisella kyllä / ei, kun olet testannut koodi.
- @NickGammon kiitos korjauksesta, olin tarkistamassa koodiani
data[count]='\0';
dataComplete = true;