Tabelline con Arduino

Vorrei fare un piccolo programma che generi casualmente delle tabelline e permette all'utente di tentare il risultato.
Come primo passo userei il serial monitor.
Qualcuno ha consigli su come gestire input e otput?
N

Ennesimo problema di gestione dei dati da e per la seriale... basta leggere sul forum, ci sono almeno dieci discussioni sul problema aperte negli ultimi 10 giorni (1 al giorno, non esagero).

Leo ho fatto un po di ricerche e non ho trovato nulla, forse sbaglio io con le parole chiave. Oppure dimmi se c'è qualche modo per indirizzare la ricerca. Se hai sotto mano i titolo me li dici cosi vedo che parole usano gli altri.
Grazie

Basta cercare "seriale" oppure "spedire dati seriale" oppure "comunicazione seriale" ed esce un sacco di roba. Basta anche guardare le prime 3 pagine della sezione:
Questi qui sotto sono in 1a pagina:
http://arduino.cc/forum/index.php/topic,124066.0.html
http://arduino.cc/forum/index.php/topic,123927.0.html
http://arduino.cc/forum/index.php/topic,52320.0.html
http://arduino.cc/forum/index.php/topic,123032.0.html

Intanto grazie.
Adesso guarderò il secondo.
Perchè il primo gestisce un carattere in ingresso e gli altri 3 sono solo sulla comunicazione.

Io cercavo qualcosa piu vicino alle gestione di stringhe di cui non si conosce la lunghezza, quindi usare un terminatore e in base a quello che si è scritto fare cose diverse.

N

Un terminatore non è altro che un comune byte a cui dai tu un significato diverso dal proprio.
Puoi usare il byte $FF, per esempio, nessun carattere comprensibile (alfanumerico) ha quel valore. Oppure uno a tua scelta.
Seriale = spedisci byte, leggi byte. Il resto è in quei link (ci sono anche esempi comleti di codice) e nel Reference:

Allora letto, ma non mi aiuta.
Leo, io ho gia fatto una parte che setta e scatta foto usando la seriale tramite una camera jpg seriale.
Il mio problema non è la comunicazione seriale, ma idee su come gestire proprio un discorso di domanda e risposta, legato anche al timing, magari senza usare gli interrupt. Anche se poi quello che vorrò fare è usare 2 interrupt per gestire i due eventi che si potrebbero verificare.

Il problema su cui cerco idee è che io vorrei non imporre protocolli, ma lasciare l'input aperto.
Quindi Arduino fa una domanda e in loop aspetta caratteri.
Quando arriva un terminatore ad esempio .

Nell'esempio qui sotto ad esempio intercetto se leggo mario o nicola, ma se sbaglio non rientro piu.

N

char inData[20]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character

void setup() {
    Serial.begin(38400);
    Serial.write("Power On");
}

char Comp(char* This) {
    while (Serial.available() > 0) // Don't read unless
                                   // there you know there is data
    {
        if(index < 19) // One less than the size of the array
        {
            inChar = Serial.read(); // Read a character
            inData[index] = inChar; // Store it
            index++; // Increment where to write next
            inData[index] = '\0'; // Null terminate the string
        }
    }

    if (strcmp(inData,This)  == 0) {
        for (int i=0;i<19;i++) {
            inData[i]=0;
        }
        index=0;
        return(0);
    }
    else {
        return(1);
    }
}

void loop()
{
    if (Comp("nicola")==0) {
        Serial.write("NICOLA\n");
        
    }
    if (Comp("mario")==0) {
        Serial.write("MARIO\n");
    }
}

non un protocollo ma un minimo di controllo dell'input/output devi creartelo altrimenti non ne esci più.
Se fai domande ed attendi risposte devi:

  1. registrare un tempo d'inizio
  2. inviare la domanda
  3. chiedere la risposta
  4. filtrare l'input dell'utente
  5. controllare se la risposta è giusta, nel caso uscire, oppure
  6. controllare se il tempo concesso è finito, nel caso uscire, oppure tornare al punto 3.

Poi gestisci il punteggio e/o il numero di risposte esatte e/o il meccanismo per terminare il quiz.
Ti serve una strutturazione del codice base tipo questa.

Teoricamente mi è molto chiaro.
Ma come dicevo prima volevo che qualcuno mi aiutasse a vedere un esempio di codice che sta in ascolto e quando arriva un terminatore prende la parola al limite la confronta (come ho già fatto nell'esempio) e faccia una serie di cose, ma poi si rimetta nello stato iniziale.
Questa parte non riesco a fare.
N

Bastava che tu avessi aperto uno dei link che ti ho passato: te l'avevo detto che c'erano già dei codici scritti... ad esempio apri il 2° e scorri a metà pagina.

Dato che il trasmittente non mi interessa perchè vorrei simulare tutto con il Serial Monito, immagino tu dica di guardare questo codice:

#include <SoftwareSerial.h> // libreria creazione porta seriale virtuale

SoftwareSerial mySerial(2, 3); // RX, TX

int I = 0; 
int J = 0; 
String Z = "";
byte Decimali = 1;  

String SerRx = "";                                   // azzera buffer ricezione
const unsigned long TimeOut = 5000;                  // timeout 1 s
unsigned long Timer = millis();// timer partito

int Temp1=0 ;
int Temp2=0 ;
int Temp3=0 ;
int Temp4=0 ;
int Temp5=0 ;

void setup() {
  Serial.begin(9600);  // inizializza porta seriale
  Serial.println("seriale rx inizio");
  mySerial.begin(19200);
  mySerial.println("seriale virtuale rx inizio");                             // inizializza porta seriale ausiliaria
}

void loop() {

  SerRx = "";                                        // azzera buffer ricezione
  Timer = millis();                                  // timer partito

  while (millis() - Timer < TimeOut) {               // attesa timeout
    while (mySerial.available() > 0) {              // ricezione da modulo
      SerRx += char(mySerial.read());               // aggiungi carattere al buffer          
      Timer = millis();                              // reset timer 
    }
  }

  if (SerRx.length() > 0) {                          // ci sono dei dati nel buffer (Temp1<CR><LF>Temp2<CR><LF>...Temp5<CR><LF>
    J = 0;
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp1 = Z.toInt();
      J = I + 2;       // nuova posizione di ricerca
      mySerial.println(Temp1, Decimali);
      Serial.print("Temp1 = ");
      Serial.println(Temp1, Decimali);
      
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp2 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      mySerial.println(Temp2, Decimali);
      Serial.print("Temp2 = ");
      Serial.println(Temp2, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp3 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      mySerial.println(Temp3, Decimali);
      Serial.print("Temp3 = ");
      Serial.println(Temp3, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp4 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      mySerial.println(Temp4, Decimali);
      Serial.print("Temp4 = ");
      Serial.println(Temp4, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp5 = Z.toInt();
      mySerial.println(Temp5, Decimali);
      Serial.print("Temp5 = ");
      Serial.println(Temp5, Decimali);
    }
  }
}

Ripeto che sono alle prime armi, ma mi sembra di vedere un codice molto legato a quello che definivo un protocollo.
Si aspetta dei numeri di 2 cifre con un decimale formattati.

Ma forse sbaglio a capire il codice e non riesco a provarlo non avendo due Arduini.
Tu mi confermi che continua ad aspettare cose e le scrive anche oltre i 5 caratteri?

Non riesci a dirmi cosa cambiare per usarlo col serial Monitor?
Vorrei partire da un esempio funzionante per cercare di capire.
Anche con la macchina fotografica ho problemi perchè l'inizializzazzione richiede 10 secondi e a volte non mi fa cose e non capisco dove sia il problema.
Non so se hai dato un occhio al mio esempio che funziona.
Perchè se sbaglio una volta poi non riesco piu a fargli leggere niente?

N

Chissà perchè ho il presentimento che si andrà a finire come il quizzettone...

Che intendi?
Ho modificato come sotto e qualcosa torna.
Adesso cerco di vedere come modificare il codice.
Il timeout serve solo a controllare ogni tot (5 sec) cosa è stato digitato?
Nel caso scrivo a cavallo perdo dei dati giusto?

N

int I = 0; 
int J = 0; 
String Z = "";
byte Decimali = 1;  

String SerRx = "";                                   // azzera buffer ricezione
const unsigned long TimeOut = 5000;                  // timeout 1 s
unsigned long Timer = millis();// timer partito

int Temp1=0 ;
int Temp2=0 ;
int Temp3=0 ;
int Temp4=0 ;
int Temp5=0 ;

void setup() {
  Serial.begin(9600);  // inizializza porta seriale
  Serial.println("seriale rx inizio");
}

void loop() {

  SerRx = "";                                        // azzera buffer ricezione
  Timer = millis();                                  // timer partito

  while (millis() - Timer < TimeOut) {               // attesa timeout
    while (Serial.available() > 0) {              // ricezione da modulo
      SerRx += char(Serial.read());       // aggiungi carattere al buffer          
      Timer = millis();                              // reset timer 
    }
  }

  if (SerRx.length() > 0) {                          // ci sono dei dati nel buffer (Temp1<CR><LF>Temp2<CR><LF>...Temp5<CR><LF>
    Serial.println(SerRx);
    J = 0;
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp1 = Z.toInt();
      J = I + 2;       // nuova posizione di ricerca
      Serial.println(Temp1, Decimali);
      Serial.print("Temp1 = ");
      Serial.println(Temp1, Decimali);
      
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp2 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      Serial.println(Temp2, Decimali);
      Serial.print("Temp2 = ");
      Serial.println(Temp2, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp3 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      Serial.println(Temp3, Decimali);
      Serial.print("Temp3 = ");
      Serial.println(Temp3, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp4 = Z.toInt();
      J = I + 2;                                     // nuova posizione di ricerca
      Serial.println(Temp4, Decimali);
      Serial.print("Temp4 = ");
      Serial.println(Temp4, Decimali);
    }
    I = SerRx.indexOf(13, J);                        // cerca CR (carriage return) a partire dal carattere J
    if (I > 0) {
      Z = SerRx.substring(J, I);                      // sotto stringa dal carattere J al carattere I-1
      Temp5 = Z.toInt();
      Serial.println(Temp5, Decimali);
      Serial.print("Temp5 = ");
      Serial.println(Temp5, Decimali);
    }
  }
}

contecavour:
Che intendi?
...

Il quizzettone fu un topic entrato ormai nella storia del forum, quando hai un attimo buttaci un occhio che ne vale la pena... in breve si tratta di un dispositivo per giocare al quizzettone con tanto di "sorpresine" per chi dà la risposta sbagliata, roba che nemmeno George Lucas sotto allucinogeni può concepire :sweat_smile:

Scusami per l'OT sul tuo topic.

Cos'è un OT?
Scusa ma sono nuovo.

Invece ho trovato un tuo esempio finalmente delucidante.
Grazie
N

contecavour:
Cos'è un OT?
Scusa ma sono nuovo.

OT sta per Off Topic, quindi risposte fuori tema.

Ecco, intendevo qualcosa del genere.

String miaStringa = "";         
String nome = ""; 
boolean terminata = false;  
int passo = 1;

void setup() {
  // initialize serial:
  Serial.begin(9600);
  miaStringa.reserve(200);
  nome.reserve(200);
  Serial.println("Come ti chiami ?");
  passo = 1;
}

void loop() {
  if (terminata) {
    switch (passo) {
    case 1:
      Serial.print("Ciao ");
      Serial.print(miaStringa);
      nome = miaStringa;
      miaStringa = "";
      Serial.println(". Quanti anni hai? ");
      terminata = false;
      passo = 2;
      break;
    case 2:
      Serial.print("Ciao ");
      Serial.print(nome);
      Serial.print(". Hai ");
      Serial.print(miaStringa);
      Serial.println(" anni");
      passo = 1;
      Serial.println("Come ti chiami ?");
      miaStringa = "";
      terminata = false;
      break;
  }
  }
}

void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read(); 
    if (inChar == '\n') {
      terminata = true;
    } else
    {
    miaStringa += inChar;
    }  
  }
}