Go Down

Topic: Problema reading seriale e attesa condizione (Read 2241 times) previous topic - next topic

alexsgv

Salve a tutti,
io sono nuovo di questo forum ed ho appena iniziato ad usare ArduinoUNO.
Sto cercando di realizzare un programmino che faccia delle cose (non è questo il mio problema) e si interfacci con PuTTY via seriale e possa ricevere dei comandi.
il mio problema è realizzare il ciclo di controllo sulla seriale per verificare che il byte ricevuto soddisfi una mia condizione.....

int byteInArrivo = 0; // per iniziare la trasmissione seriale
int serial =0;
void setup( ) {
Serial.begin(9600); // apertura porta seriale, impostazione velocità di
// trasmissione dati a 9600bps
}
void loop( ) {
  Serial.println("\E[H\E[2J" );  //Clear Screen in PuTTY
  Serial.println("Scegli tra le seguenti opzioni:");
  delay(5);
  Serial.println("a - Leggi x");
  delay(5);
  Serial.println("b - Leggi y");
  delay(5);
  Serial.println("c - Leggi z");
  delay(5);
  Serial.print("\n");
  delay(5);

if (Serial.available()>0){
   byteInArrivo = Serial.read( );
   }

   delay(50);
    while (byteInArrivo!= 97 || byteInArrivo!=98 || byteInArrivo!=99){
        byteInArrivo = Serial.read( ); // leggi i byte che arrivano
        delay(500);
     }
    Serial.print("Wait.... ");

  Serial.flush( );

  delay(3000);
  Serial.println("\E[H\E[2J" );  //Clear Screen in PuTTY
  delay(5);
  }

in pratica, voglio leggere la seriale e aspettare finchè non è verificata la condizione in cui il dato ricevuto è uguale ad una delle mie condizioni.
Chi mi aiuta?!

vittorio68

#1
Feb 13, 2013, 09:46 am Last Edit: Feb 13, 2013, 09:53 am by vittorio68 Reason: 1
Ti scrivo qualche riga senza averla provata... usala solo come punto di partenza

Code: [Select]

int byteInArrivo = 0; // per iniziare la trasmissione seriale
int serial =0;

void setup( )
{
   Serial.begin(9600); // apertura porta seriale, impostazione velocità di
                                // trasmissione dati a 9600bps

   prompt()
}

void loop( )
{

   if (Serial.available()>0)
   {
      byteInArrivo = Serial.read( );
     
      switch (byteInArrivo)
      {
           case 97:
              Serial.print("Hai premuto a");
              // qui chiami la funzione da eseguire quando viene premuto a
              break;
           case 98:
              Serial.print("Hai premuto b");
              // qui chiami la funzione da eseguire quando viene premuto b
              break;
           case 99:
              Serial.print("Hai premuto c");
              // qui chiami la funzione da eseguire quando viene premuto c
              break;
           default:
              Serial.print("Comando sconosciuto");
              break;
      }
     
      delay(2000); // serve per dare 2 secondi di tempo per vedere l'eventuale output della funzione richiesta
                         // magari è inutile o vuoi sostituirlo con qualcos'altro
      prompt();
   }
}

void prompt()
{
   Serial.println("\E[H\E[2J" );  //Clear Screen in PuTTY
   Serial.println("Scegli tra le seguenti opzioni:");
   // perchè le delay? A cosa servono?
   //delay(5);
   Serial.println("a - Leggi x");
   //delay(5);
   Serial.println("b - Leggi y");
   //delay(5);
   Serial.println("c - Leggi z");
   //delay(5);
   Serial.print("\n");
   //delay(5);
}

alexsgv


Ti scrivo qualche riga senza averla provata... usala solo come punto di partenza

Code: [Select]

int byteInArrivo = 0; // per iniziare la trasmissione seriale
int serial =0;

void setup( )
{
   Serial.begin(9600); // apertura porta seriale, impostazione velocità di
                                // trasmissione dati a 9600bps

   prompt()
}

void loop( )
{

   if (Serial.available()>0)
   {
      byteInArrivo = Serial.read( );
     
      switch (byteInArrivo)
      {
           case 97:
              Serial.print("Hai premuto a");
              // qui chiami la funzione da eseguire quando viene premuto a
              break;
           case 98:
              Serial.print("Hai premuto b");
              // qui chiami la funzione da eseguire quando viene premuto b
              break;
           case 99:
              Serial.print("Hai premuto c");
              // qui chiami la funzione da eseguire quando viene premuto c
              break;
           default:
              Serial.print("Comando sconosciuto");
              break;
      }
     
      delay(2000); // serve per dare 2 secondi di tempo per vedere l'eventuale output della funzione richiesta
                         // magari è inutile o vuoi sostituirlo con qualcos'altro
      prompt();
   }
}

void prompt()
{
   Serial.println("\E[H\E[2J" );  //Clear Screen in PuTTY
   Serial.println("Scegli tra le seguenti opzioni:");
   // perchè le delay? A cosa servono?
   //delay(5);
   Serial.println("a - Leggi x");
   //delay(5);
   Serial.println("b - Leggi y");
   //delay(5);
   Serial.println("c - Leggi z");
   //delay(5);
   Serial.print("\n");
   //delay(5);
}




It works very well!!! Thank you so much!  :)

alexsgv

Ho solo un altro quesito da chiederti...
con che criterio hai scelto di mettere la lettura della seriale nel loop e invece il menu su un alta routine?
se premo invio un comendo seriale prima che abbia stamapato il menu a poco senso, no?!
Sto solo cercando di capire come strutturare i programmi. Sono nuovo e non ho la flessibilità suff. per vedere in modo chiaro, come scrivere un programma.

Grazie per l'aiuto!

lesto

è una semplice questione di ordine del codice... leggibilità
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

vittorio68

ciao

ho messo la stampa del menu in una funzione per poterlo richiamare sia da setup() che da loop(). L'ho messo anche in setup proprio per evitare che l'utente possa scrivere qualcosa sulla seriale prima della stampa del menu.

In generale però l'aspetto importante è un'altro. Nel codice che avevi scritto tu, bloccavi l'esecuzione di loop in attesa di un carattere sulla seriale. Questo magari funziona pure ma mi sembra un approccio meno "generico". Nel codice che ho proposto io invece il controllore esegue sempre il loop e quindi tu potrai fargli fare altre cose ad ogni ciclo in attesa che arrivi un comando.

Ti faccio un esempio. Immagina di voler realizzare un termostato che legga all'infinito una temperatura ed attivi un relè quando questa è più bassa di una certa soglia. In più, come hai fatto tu, ogni volta che sulla seriale arriva il carattere 'a' mi risponde con l'ultima temperatura letta, quando arriva 'b' mi risponde con la media, quando arriva 'c' mi cambia di stato al relè a prescindere dalla temperatura (magari quest'ultimo esempio andrebbe approfondito per non essere assurdo...).

Con il mio approccio puoi inserire il codice per la lettura del sensore e per l'attivazione del relè all'interno del loop (prima o dopo l'if sulla Serial.Available non ha molta importanza...) ed essere sicuro che sia la gestione del sensore e del relè sia la gestione della seriale avvenga "contemporaneamente" (o almeno che sembri così).

alexsgv


ciao

ho messo la stampa del menu in una funzione per poterlo richiamare sia da setup() che da loop(). L'ho messo anche in setup proprio per evitare che l'utente possa scrivere qualcosa sulla seriale prima della stampa del menu.

In generale però l'aspetto importante è un'altro. Nel codice che avevi scritto tu, bloccavi l'esecuzione di loop in attesa di un carattere sulla seriale. Questo magari funziona pure ma mi sembra un approccio meno "generico". Nel codice che ho proposto io invece il controllore esegue sempre il loop e quindi tu potrai fargli fare altre cose ad ogni ciclo in attesa che arrivi un comando.

Ti faccio un esempio. Immagina di voler realizzare un termostato che legga all'infinito una temperatura ed attivi un relè quando questa è più bassa di una certa soglia. In più, come hai fatto tu, ogni volta che sulla seriale arriva il carattere 'a' mi risponde con l'ultima temperatura letta, quando arriva 'b' mi risponde con la media, quando arriva 'c' mi cambia di stato al relè a prescindere dalla temperatura (magari quest'ultimo esempio andrebbe approfondito per non essere assurdo...).

Con il mio approccio puoi inserire il codice per la lettura del sensore e per l'attivazione del relè all'interno del loop (prima o dopo l'if sulla Serial.Available non ha molta importanza...) ed essere sicuro che sia la gestione del sensore e del relè sia la gestione della seriale avvenga "contemporaneamente" (o almeno che sembri così).



Ti ringrazio per la spiegazione! è stata molto esaustiva e chiara! Lo so sto muovendo i primi passi in questo mondo e qualsiasi consiglio è ben accettto!
Grazie ancora.

Alex

alexsgv


ciao

ho messo la stampa del menu in una funzione per poterlo richiamare sia da setup() che da loop(). L'ho messo anche in setup proprio per evitare che l'utente possa scrivere qualcosa sulla seriale prima della stampa del menu.

In generale però l'aspetto importante è un'altro. Nel codice che avevi scritto tu, bloccavi l'esecuzione di loop in attesa di un carattere sulla seriale. Questo magari funziona pure ma mi sembra un approccio meno "generico". Nel codice che ho proposto io invece il controllore esegue sempre il loop e quindi tu potrai fargli fare altre cose ad ogni ciclo in attesa che arrivi un comando.

Ti faccio un esempio. Immagina di voler realizzare un termostato che legga all'infinito una temperatura ed attivi un relè quando questa è più bassa di una certa soglia. In più, come hai fatto tu, ogni volta che sulla seriale arriva il carattere 'a' mi risponde con l'ultima temperatura letta, quando arriva 'b' mi risponde con la media, quando arriva 'c' mi cambia di stato al relè a prescindere dalla temperatura (magari quest'ultimo esempio andrebbe approfondito per non essere assurdo...).

Con il mio approccio puoi inserire il codice per la lettura del sensore e per l'attivazione del relè all'interno del loop (prima o dopo l'if sulla Serial.Available non ha molta importanza...) ed essere sicuro che sia la gestione del sensore e del relè sia la gestione della seriale avvenga "contemporaneamente" (o almeno che sembri così).



ma in setup () gli si può anche far fare delle cose come stampare il menu?!...non credo di aver capito bene la cosa! Credevo che li si potesse solo configurare e inizializzare le cose. Inoltre, mi puoi spiegare la funzione di controllo dati disponibili sulla seriale?!

Ciao
Alex

lesto

puoi fare quello che vuoi dove vuoi, l'unico caso a parte sono i vettori di interrupt ma direi che non devi preoccupartene per ora.

per le funzioni disponibili nelle librerie ufficiali dalla pagina principale arduino.cc fai reference -> libraryes
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

alexsgv


puoi fare quello che vuoi dove vuoi, l'unico caso a parte sono i vettori di interrupt ma direi che non devi preoccupartene per ora.

per le funzioni disponibili nelle librerie ufficiali dalla pagina principale arduino.cc fai reference -> libraryes


non so se mi puoi spiegare, ma non ho capito come non far fare il refresh continuo al menù....ora me lo fa di continuo (con il sw che mi ha scritto sopra) non è piacevole vederlo lampeggiare di continuo.... scusa la mia profonda ignoranza.

lesto

cosa vuol dire il refresh? da quel che vedo ridisegna il menù solo se necessario
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

alexsgv


cosa vuol dire il refresh? da quel che vedo ridisegna il menù solo se necessario

si forse ho detto una minchiata...
switchio la domanda... diciamo che tramite il menu arrivo in un punto in cui voglio inserire un dato da salvare in una variabile...
se premo un numero lui esce subito dalla routine...perchè ha visto che è stato trasmesso un dato! come faccio per dirgli di aspettare due caratteri?
esempio...voglio scrivere la temperatura da impostare....se premo 2 lui lo prende subito....io invece volevo scrivere 25!
Come si gestisce questa cosa?! ci sto diventando scemo!

lesto

Code: [Select]
if (Serial.available()>0)

dice di aspettare almeno 1 carattere... a te il resto
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

alexsgv


Code: [Select]
if (Serial.available()>0)

dice di aspettare almeno 1 carattere... a te il resto


ho provato così per acquisire 2byte (?)...ma non mi funziona ugualmente...
Code: [Select]
if (Serial.available()>1)
        {
        RifTemp = Serial.read( );
        Serial.println("Hai inserito");
        Serial.println(RifTemp,DEC);
      } 

lesto

la serial read legge un solo carattere... quindi semmai
Code: [Select]

RifTemp = Serial.read()+Serial.read( ) //se vuoi LA SOMMA DEI VALORI NUMERICI DEI BYTE (e quindi riftemp è un int o superiore)
RifTemp = (Serial.read()<<8)+Serial.read( ) //se riftemp è un int spdito in modo "grezzo" (prima parte alta e poi la LSB)
RifTemp = Serial.read()+""+Serial.read( ) //se riftemp è una stringa il "" (carattere vuoto) fa in modo che i valori di read NON si simmino, ma vengano affiancati. Ottimo per ricostruire parole, ad esempio


tu cosa vuoi fare?
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Go Up