Serial.available() loop

Ciao

Mi è venuto un dubbio a cui non so dare risposta.

Ho dei device che comunicano via seriale alla mia arduino che funzionano a polling (ad un mio comando loro rispondono).

Così ho creato delle finestre temporali entro le quali devono rispondere, altrimenti proseguo.

Non ho capito, però, se è più giusto innestare un if(Serial.available()) oppure un while(Serial.available())

Questo è un pezzo di codice:

  unsigned long start = millis();
  while (millis() - start < COUNT*2)
  {
    if (Serial.available()) {
      character = Serial.read();
      content.concat(character);
    }
  }

Vedendo alcune librerie qualcuno mette la if, altri il while… cosa suggerite?

Saluti

if(Serial.available())

Controlla il buffer e esegue se qualcosa presente quello che é scritto dopo.

while(Serial.available())

Aspetta finche arriva qualcosa nel buffer, percui é bloccante.

Il modo giusto dipende dalla logica con cui scrivi lo sketch.

Ciao Uwe

Tutto dipende da cosa deve fare il resto del codice in attesa del flusso di dati.

Ad esempio se il flusso di dati è qualcosa di simile ad un pacchetto di dimensioni predefinite, diciamo 10byte, ti calcoli in base al baud rate quanto tempo ci vuole per ricevere questi 10byte.

Se usi il while è sicuro che hai collezionato 10byte, ma durante questo tempo trascorso il resto del codice non viene eseguito.

Se invece non di tratta di un pacchetto ma di singoli byte devi usare if, perché così il byte ricevuto può essere subito usato dal codice, magari per controllare una macchina a stati basati su switch case.

Ci possono essere tante altre varianti, una ad esempio, che alza un flag (o genera un interrupt hardware via software) quando il pacchetto dati è pronto per essere computato, come dire mi hai detto di collezionare questi dati, quando ho finito alzo la bandierina (flag) ed in questo caso il while non puoi usarlo, ed inoltre devi mantenere il loop() di breve durata, in modo che non si riempa il buffer della seriale.

Ciao.

[Anticipato da @uwefed]

Grazie a tutti.

Preferirei che la lettura fosse bloccante e che l'arduino non facesse nulla e si "concentrasse" sulla lettura di questa stringa. Probabilmente è meglio il while perché mi aspetto una frase di 50byte di risposta e quindi ho COUNT*2 di tempo per leggerla tutta...

Se in quel'arco temporale non ho risposta... amen, vado avanti con il codice.

Probabilmente è meglio il while perché mi aspetto una frase di 50byte di risposta e quindi ho COUNT*2 di tempo per leggerla tutta...

Si, si, non c'è altra soluzione, durante quel tempo non puoi neanche fare lampeggiare un led.

Se ti basta questo la soluzione è trovato, diversamente chiedi, che ti sarà dato, ricorda non strofinare troppo forte la lampada. :grin:

Forse non ti serve il primo while() che attende un intervallo di tempo, potresti invece usare un if() per vedere se ci sono byte da seriale, se vero al suo interno esegui un while() per la lettura stringa, in questo modo arduino perde tempo a leggere la seriale solo se effettivamente deve farlo.

Esempio

/* Per trasmettere una stringa è bene usare un terminatore stringa anziché basarsi sui numero byte
    disponibili, nell'esempio il terminatore è '\n' . Sarebbe anche meglio usare le stringhe del C e non 
    l'oggetto String, comunque mi attengo a quanto fatto da te...
*/

void loop(){

     if(Serial.available()){ // Se ci sono byte eseguo la lettura, altrimenti proseguo col programma

          do{
           
                while(!Serial.available()); //Attende che effettivamente ci sia un byte da leggere
                character = Serial.read();
                if(character!='\n')
                    content.concat(character);
  
          }while(character!='\n');
     }

}

torn24: Forse non ti serve il primo while() che attende un intervallo di tempo, potresti invece usare un if() per vedere se ci sono byte da seriale, se vero al suo interno esegui un while() per la lettura stringa, in questo modo arduino perde tempo a leggere la seriale solo se effettivamente deve farlo.

Esempio

/* Per trasmettere una stringa è bene usare un terminatore stringa anziché basarsi sui numero byte
    disponibili, nell'esempio il terminatore è '\n' . Sarebbe anche meglio usare le stringhe del C e non 
    l'oggetto String, comunque mi attengo a quanto fatto da te...
*/

void loop(){

    if(Serial.available()){ // Se ci sono byte eseguo la lettura, altrimenti proseguo col programma

          do{          
                while(!Serial.available()); //Attende che effettivamente ci sia un byte da leggere                 character = Serial.read();                 if(character!='\n')                     content.concat(character);             }while(character!='\n');     }

}

Buona idea. Però può capitare che il device connesso sia "busy" nel'istante in cui faccio polling.

Magari potrei fare un paio di chiamate finchè non risponde.