Domanda:
Cancella l'array esistente quando si riceve un nuovo comando seriale
squeck
2014-07-04 02:20:10 UTC
view on stackexchange narkive permalink

Sto iniziando a costruire il mio primo progetto Arduino ma riscontro alcuni problemi con la comunicazione seriale.

Ricevo dati seriali dalla console e li memorizzo in un array di caratteri chiamato "dati" .

Quindi, quando invio un nuovo messaggio di console ad Arduino, desidero che cancelli l'array "data" esistente e memorizzi solo i nuovi dati in quell'array.

I non capisco esattamente cosa c'è che non va nel mio codice: credo che quelle istruzioni Serial.available () nidificate non funzionino ma non ho idee su come correggere il codice.

I dati sono correttamente memorizzati dal Arduino ma concatena la stringa più recente a quella vecchia.

  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 ("Sono già presenti dati, cancellazione ..."); dati char [30]; dataComplete = false; } if (dataComplete == false) {Serial.println ("Nuovo comando, raccolta ..."); while (Serial.available () >0) {char character = Serial.read (); dati [conteggio] = carattere; count ++; } dataComplete = true; }} Serial.print ("Comando ricevuto:"); Serial.println (dati); delay (1000);}  

Grazie in anticipo!

Cinque risposte:
#1
+15
JRobert
2014-07-04 23:59:38 UTC
view on stackexchange narkive permalink

Per cancellare un array dovresti fare:

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

o

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

, che fa la stessa cosa utilizzando una funzione di libreria.

Tuttavia, poiché le stringhe di caratteri (che non si riferiscono a oggetti "String" qui) sono terminate da un byte zero, solo il primo byte deve essere azzerato:

  data [0] = (char) 0;  

lo farà.

#2
+3
Anonymous Penguin
2014-07-04 05:33:49 UTC
view on stackexchange narkive permalink

Prima di tutto, questo è un eccellente esempio del motivo per cui gli spazi sono importanti. Il tuo codice è davvero difficile da leggere così com'è, mentre lo scorri, sembra che la seconda istruzione if sia esterna alla prima.

Codice fisso:

  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 ("Sono già presenti dati, cancellazione in corso ..."); dati char [30]; dataComplete = false; } if (dataComplete == false) {Serial.println ("Nuovo comando, raccolta ..."); while (Serial.available () >0) {char character = Serial.read (); dati [conteggio] = carattere; count ++; } dataComplete = true; }} Serial.print ("Comando ricevuto:"); Serial.println (dati); delay (1000);}  

Inoltre, sembra che stampi "Comando ricevuto:" ogni iterazione, indipendentemente dal fatto che ci siano nuovi dati o meno (anche se questa potrebbe essere la caratteristica prevista) .

Come accennato, non azzera la variabile, ma ne crei solo una nuova. Dovrai cancellare e reimpostare il count per risolvere questo problema. Tuttavia, il semplice ripristino del conteggio non funzionerà se il secondo comando è più breve di quello precedente.

Inoltre, perché complichi il codice con la variabile dataComplete ? Ho semplificato il codice seguente:

  int count = 0; char data [30]; boolean dataComplete = false; void setup () {Serial.begin (9600);} void loop () { if (Serial.available ()) {Serial.println ("Nuovo comando, raccolta ..."); count = 0; data [] = ""; while (Serial.available ()) {char character = Serial.read (); dati [conteggio] = carattere; count ++; }} Serial.print ("Comando ricevuto:"); Serial.println (dati); ritardo (1000);}  
#3
+1
Greg Hewgill
2014-07-04 02:41:55 UTC
view on stackexchange narkive permalink

Questo probabilmente non fa quello che intendi fare:

  Serial.println ("Sono già presenti dati, cancellazione ..."); char data [30];  

Il tuo output dice che stai cancellando l'array data , ma non stai facendo nulla del genere. In effetti, stai dichiarando una nuova variabile locale chiamata data , che è indipendente dai dati globali che hai già dichiarato all'inizio del tuo programma. Le variabili locali esistono solo all'interno dell'ambito in cui sono dichiarate (all'interno del loro {} che lo racchiude più vicino).

Invece, la tua variabile count tiene traccia della quantità di dati che hai ricevuto. Quindi forse fai quanto segue:

  Serial.println ("Sono già presenti dati, cancellazione in corso ..."); count = 0;  

Questo è non è l'unica cosa che potrebbe far funzionare inaspettatamente il tuo programma, ma dovrebbe almeno risolvere il problema indicato nella tua domanda.

Inoltre è necessario un terminatore nullo per i dati: Aggiungi `data [count] = '\ 0';` dopo `dataComplete = true;`
Sì, è vero, ma il problema più grande è che non c'è modo per il mittente di indicare la fine di una trasmissione di dati se non per mettere in pausa. E poiché questo è seriale, ci sarà una pausa abbastanza lunga tra * ogni * carattere trasmesso.
Grazie a tutti e due ragazzi. Il mio codice era sbagliato e cambiarlo in "count = 0" ha funzionato. Ho anche aggiunto un delimitatore per indicare la fine di un comando di input e ora funziona come previsto. Tuttavia, l'unico modo che ha funzionato per svuotare l'array "data" è stato utilizzare un ciclo for come indicato da @JRobert: in questo modo i comandi più recenti funzionano anche se sono più brevi di quelli più vecchi.
#4
  0
nu11
2015-05-06 08:47:36 UTC
view on stackexchange narkive permalink

Per parlare fino al punto della domanda e di ciò che l'autore stava cercando di ottenere.

Nessuno di questo codice funziona effettivamente nel suo insieme. I dati verrebbero sovrascritti e continuerebbero a scorrere continuamente ... comunque ecco un esempio funzionante del codice originale.

Questo metodo preferisco cancellare un array:

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

Ecco un esempio funzionante. (Assicurati di selezionare Carriage Return sul monitor seriale)

  char message [32]; uint8_t incomingByte = 0; uint8_t BufferPos = 0; int clearbyte = 0; void setup () {Serial.begin (9600); Serial.println ("\ n Test di conversione di stringhe"); } void loop () {if (BufferPos > = 32) {Serial.print ("Buffer Full \ n"); BufferPos = 00; incomingByte = 0; } if (Serial.available ()) {incomingByte = Serial.read (); messaggio [BufferPos ++] = incomingByte; switch (incomingByte) {case '\ n': case '': break; case '\ r': Serial.println (messaggio); for (int i = 0; i < sizeof (message); ++ i) message [i] = (char) 0; BufferPos = 0; incomingByte = 0; }}}  
#5
  0
Ashif Riady
2019-01-17 10:54:12 UTC
view on stackexchange narkive permalink

Ho letto tutti i commenti su questa domanda, ma tutti i codici erano condivisi in modo così prolisso. Dopodiché, creo un codice con funzioni semplici e meno righe. in questo caso, penso che questo codice funzionerà bene

se imposti il ​​baudrate sotto 115200, devi aggiungere delay () per salvare il messaggio nell'array di caratteri

  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);}  
`char data [] = {};` ti darà un array di lunghezza zero. Cercare di inserire dati al suo interno è una cattiva idea.
Sono d'accordo con @NickGammon. Modifica la tua risposta per sostituire "Penso che ... funzionerà bene" con un sì / no definitivo, dopo aver testato il codice.
@NickGammon grazie per la correzione, stavo rivedendo il mio codice


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...