MODALITA DI ELABORAZIONE DEI MESSAGGI
I messaggi provenienti in ricezione dalla seriale possono essere letti nel loop() sostanzialmente in due maniere:
- un byte alla volta
- in buffering
In entrambi i casi l’applicazione tiene un proprio buffer (buffer dei messaggi) dove memorizzare i messaggi ricevuti per poterli elaborare. Si tratta di un buffer gestito direttamente dall’applicazione e a parte rispetto a quelli di RX e TX che sono nascosti all’applicazione e gestiti in maniera ad essa trasparente da un apposito driver (funzione di libreria di Aduino).
Nella prima modalità un messaggio viene letto un carattere alla volta ad ogni loop e ogni carattere è memorizzato in posizioni successive all’interno di un buffer di dimensioni opportune. La fine dell’accumulo è segnalato o da un contatore, o dallo scadere di un timer o dalla ricezione di un carattere “tappo”, cioè un carattere speciale che, all’interno del flusso di byte, indichi la fine della stringa. A questo punto il messaggio è completo e può essere prelevato dal buffer per essere utilizzato dall’applicazione.
La seconda modalità, il buffering, usa il loop solo per verificare la disponibilità di dati (byte) nel buffer di ricezione, si controlla inoltre la loro quantità, che ad ogni loop() cresce con nuovi arrivi. Quando il numero di byte ricevuti è sufficiente, oppure quando scade un timer oppure quando si legge (senza prelevarlo) un carattere speciale, allora, e solo allora, i caratteri vengono letti tutti insieme e vengono caricati sul buffer dei messaggi per essere elaborati dall’applicazione. In sostanza, il messaggio, pur essendo controllato in tutti i loop, non viene letto in nessuno meno che in un loop() particolare quando, in una sola volta (solitamente tramite un ciclo while), viene letto tutto intero e caricato sul buffer dell’applicazione.
Esempio di caricamento ad ogni loop
Viene considerato un messaggio tutta la parte numerica terminata dai caratteri speciali + e =
int vals[3];
unsigned count;
char p;
char buf[10];
void setup() {
// Attiva il protocollo seriale
Serial.begin(9600);
count = 0;
}
void loop() {
// polling sul registro USR che controlla se, nel loop corrente, è in arrivo un nuovo dato
if (Serial.available()) { // vero se c'è qualcosa da leggere
p = Serial.read(); // leggi un carattere
if(p == '+'){ //carichi il primo operando (carattere speciale)
buf[count] = '\0'; // metti il carattere "tappo" di fine stringa, cioè crei la stringa
count = 0; // azzeri il buffer (dopo ci scrivi sopra)
vals[0] = atoi(buf); // trasformi la stringa in un numero
}else if(p == '='){ //carichi il secondo operando (carattere speciale)
buf[count] = '\0';
count = 0;
vals[1] = atoi(buf); // calcoli il segno dell'operazione di somma
Serial.print("La somma di ");
Serial.print(vals[0]);
Serial.print(" con ");
Serial.print(vals[1]);
Serial.print(" vale: ");
vals[2] = vals[0] + vals[1]; // calcoli la somma
Serial.println(vals[2]); // stampi il risultato (println stampa sia numeri, che caratteri)
}else{// è un numero
buf[count] = p; // riempi il buffer un carattere alla volta
count++;
}
}
}
Simulazione su Arduino con Tinkercad: https://www.tinkercad.com/embed/d3IXwCqI0iN?editbtn=1
Esempio di caricamento in modalità buffering
int vals[3];
unsigned count;
char p;
char buf[10];
void setup() {
// Attiva il protocollo seriale
Serial.begin(9600);
count = 0;
}
void loop() {
// polling sul registro USR che controlla se, nel loop corrente, è in arrivo un nuovo dato
if(Serial.available() > 0) { // vero se c'è qualcosa da leggere
p = Serial.peek(); // leggi un carattere ma non devi prelevarlo dal buffer di RX
if(p == '+'){ //carichi il primo operando
Serial.read(); // leggi il carattere speciale e ignoralo, senza salvarlo da nessuna parte
count++; // passa all’operando successivo
}else if(p == '='){ //carichi il secondo operando
Serial.read(); // leggi il carattere speciale e ignoralo, senza salvarlo da nessuna parte
count = 0; // torna al primo operando
Serial.print("La somma di ");
Serial.print(vals[0]);
Serial.print(" con ");
Serial.print(vals[1]);
Serial.print(" vale: ");
vals[2] = vals[0] + vals[1]; // calcoli la somma
Serial.println(vals[2]); // stampi il risultato (println stampa sia numeri, che caratteri)
}else{
vals[count] = Serial.parseInt(); //lettura del messaggio (valore operando)
// blocca finchè non arriva un messaggio o, alternativamente, scade un timeout
}
}
}
Simulazione su Arduino con Tinkercad: https://www.tinkercad.com/embed/8Z5TziTzkHH?editbtn=1
Viene considerato un messaggio tutta la parte numerica terminata dai caratteri speciali + e =
La funzione Serial.parseInt() internamente chiama la Serial.available() per effettuare il parsing dei caratteri in arrivo aggiornando di uno la posizione della testa della coda di ricezione.
L’esempio seguente mostra come si possa realizzare il riempimento del buffer fino al prossino carattere speciale con un ciclo while.
Esempio di caricamento in modalità buffering
int vals[3];
unsigned count, v;
char p;
char buf[10];
void setup() {
// Attiva il protocollo seriale
Serial.begin(9600);
count = 0;
v = 0;
}
void loop() {
// polling sul registro USR che controlla se, nel loop corrente, è in arrivo un nuovo dato
if(Serial.available() > 0) { // vero se c'è qualcosa da leggere
p = Serial.peek(); // leggi un carattere ma non devi prelevarlo dal buffer di RX
if(p == '+'){ //carichi il primo operando
buf[count] = '\0';
Serial.read(); // leggi il carattere e ignoralo, senza salvarlo da nessuna parte
vals[0] = atoi(buf); // trasformi la stringa in un numero
count = 0;
}else if(p == '='){ //carichi il secondo operando
buf[count] = '\0';
Serial.read(); // leggi il carattere e ignoralo, senza salvarlo da nessuna parte
vals[1] = atoi(buf);
count = 0;
Serial.print("La somma di ");
Serial.print(vals[0]);
Serial.print(" con ");
Serial.print(vals[1]);
Serial.print(" vale: ");
vals[2] = vals[0] + vals[1]; // calcoli la somma
Serial.println(vals[2]); // stampi il risultato (println stampa sia numeri, che caratteri)
}else{
// caricamento dei caratteri delle cifre del numero sul buffer (non bloccante)
while(Serial.available()){
uint8_t curr = Serial.read();
if((curr != '+') && (curr != '=')){
buf[count++] = curr;
}else{
break;
}
}
}
}
}
Simulazione su Arduino con Tinkercad: https://www.tinkercad.com/embed/1ScNVsfRbnt?editbtn=1