NUMERO INTERO DA MONITOR SERIALE IN ARDUINO 

Quello che propongo qui sono due dei tanti metodi per caricare un numero intero in un registro di Arduino tramite Monitor Seriale. Il primo usa  le potenze di 10 memorizzate  in un vettore,  l'alto, invece,  le genera all'interno di una "for", in ambedue i metodi le potenze vengono  moltiplicate per le cifre del numero dando a quest'ultime il peso opportuno. Entrambi i metodi sono simili, io descrivero' solo il primo mettendo  poi in evidenza la differenza tra i due.

Il numero memorizzato potra'  essere usato per molteplici applicazioni, in questo programma il sistema memorizza l'intero in un  registro e lo spedisce al monitor per comprovare l'avvenuto caricamento.

Il valore che puo' essere immesso va da -2147483648 a 2147483647 quindi un tipo long int. Nella figura sottostante viene visualizzato l'immissione del  numero e la sua stampa a monitor.


Vado quindi alla descrizione del programma  nelle sue parti piu' 
intrinseche. Per seguire la spiegazione occorre tenere davanti lo sketch nominato "InputOutputMonitorInteroMetodo1".    

Dentro la funzione "void loop", alla riga 15, troviamo la istruzione condizionale "if" il cui corpo viene eseguito solo quando la funzione "Serial.available()" restituisce un valore maggiore di zero; questo accade  quando viene scritto un numero nel "serial monitor" ed eseguito l'invio,
in caso di nessuna immissione il programma salta alla "else" alla riga 28 la quale contiene, alla linea 30, una "if" che pero' non permette l'esecuzione delle istruzioni contenute nel suo corpo dato che il registro "cout" è ancora a zero (come da inizializzazione alla riga 2). Il programma salta quindi alla prima "if" e cosi' di seguito fintanto che non viene immesso un numero.

Immaginiamo ora di scrivere il numero piu' grande positivo possibile, cioe'
2147483647 e premere invio, adesso la "if" alla riga 15 esegue' il suo corpo dato che "Serial.available()" restituisce un valore maggiore di zero. Tutte le istruzioni contenute nel corpo della "if" verranno eseguite tante volte quante sono le cifre del numero che abbiamo immesso, nel nostro caso dieci volte.

Alla riga 17 troviamo l'istruzione "Serial.read" che prende la prima cifra (2) del numero espressa in formato asii e la carica nel registro "segno" (che verra' usato anche per altri scopi diversi da quelli ai quali fa pensare il suo nome), alla riga 19 troviamo l'istruzione "delay(50)" che serve per dare il tempo al sistema di  trasferire il byte letto nel registro "segno"
ed essere pronto per ricevere il successivo (corrispondente alla cifra 1).

Alla riga 20 troviamo una "if"  che eseguirebbe la istruzione contenuta nel suo corpo (settare il registro "flag" inizializzato a zero nella riga 5)  se avessimo fatto precedere il numero dal carattere "-" facendo intendere al programma di volere inserire un numero negativo, in questo esempio  abbiamo scelto di immettere  un numero  positivo per cui il programma non esegue l'istruzione e salta alla "else" (riga 22), all'interno del suo corpo troviamo due istruzioni, la prima, alla riga 24, immette il valore letto  nella prima locazione del vettore "cifra[count]" puntata dalla variabile "cout" (inizializzata a zero nella riga 2), notare che per passare dal  codice ascii  al valore decimale occorre sottrarre al byte il numero 48. La seconda istruzione carica nel registro "conteggio" il valore del registro "count", quest'ultimo sara' incrementato al suo prossimo  utilizzo. Uscito dal corpo della "else" il programma salta alla "if" alla riga 15 e ripetera' le operazioni descritte per la cifra successiva che verra' memorizzata nella locazione 1 del vettore 
"cifra[count]"  e cosi' via per tutte le cifre del numero.
Quando l'ultima cifrà  sara' stata letta e memorizzata nel vettore avremo la seguente situazione:
registro conteggio = 9
registro cout = 9
locazioni occupate dal vettore = 0, 1, 2, 3, 4, 5, 6, 7, 8 ,9
Numeri memorizzati              = 2 , 1, 4, 7, 4, 8, 3, 6, 4, 7

Il programma saltera' per la 11 volta alla "if" alla riga 15 ma allora il corrispondente corpo non verra' eseguito dato che la "
"Serial.available()" restuitira' zero essendo state lette tutte le cifre del numero immesso, quindi verra' eseguita la "else" alla riga 28, nel suo corpo troviamo la "if" alla riga 30, essendo il valore del registro "count" maggiore di zero
(anche nel caso si immetta una cifra sola grazie all'incremento di "count" effettuato alla riga 25 che viene eseguito prima di abbandonare il corpo dove è contenuto) il corpo della "if" verra' eseguito.
La "for" alla riga 32 non fa altro che moltiplicare i valori contenuti nel vettore "cifra[count]", precedentemente memorizzati,  per il vettore "power[conteggio]" il quale ha memorizzate le potenze di 10 da 1 a 1000000000 nelle relative locazioni da 0 a 9, con un semplice meccanismo questo sistema da il giusto peso alla cifra inserita in base alla sua posizione nel numero, il risultato della moltiplicazione viene poi sommato al registro numero e memorizzato nello stesso (riga 33).
Vediamo i particolari di questo meccanismo analizzando la figura seguente.


Il primo numero a sinistra indica il registro"count", il successivo il registro "conteggio" e l'ultimo il registro "numero".
Quando viene eseguita la "for" essa imposta il registro "count" a zero mentre il valore presente  nel registro "conteggio" non viene alterato. Al primo ciclo della "for" ci troviamo nella situazione raffigurata nella prima riga visualizzata nella figura, cioe' "count" = 0, "conteggio" = 9, questo significa che la cifra memorizzata nel vettore
"cifra[count]" alla locazione zero (cioe' 2) viene moltiplicata per il decimale 1000000000 contenuto nella locazione 9 del  vettore "power[conteggio]" dando il giusto peso alla cifra stessa, il risultato viene poi sommato al  registro "numero" (inizializzato a zero alla riga 6) e memorizzato in quest'ultimo.
Al prossimo ciclo della "for" il registro "count" viene incrementato e quello "conteggio" decrementato, cioe' ci troviamo nella situazione "count" = 1, "conteggio" = 8, allora 
la cifra memorizzata nel vettore "cifra[count]" alla locazione uno (cioe' 1) viene moltiplicata per il decimale 100000000 dando il giusto peso alla stessa, il risultato viene poi sommato al  registro "numero" (che contiene 2000000000) e memorizzato in quest'ultimo, il risultato è 2100000000.
Il programma esce dal ciclo "for"  quando il valore del registro "conteggio" raggiunge -1, a questo punto  avremo il numero che avevamo immesso nel "serial monitor" interamente memorizzato nel registro "numero".
La prossima istruzione che il programma incontra e' la "if" alla riga 34 che in questo caso non esegue la istruzione presente nel suo corpo perche' il registro "flag" ha valore zero come da inizializzazione, quindi viene inviato  il numero memorizzato nel registro "numero" al "serial monitor" tramite la funzione " Serial.println(numero)". Se invece avessimo inserito il carattere "-" prima del numero il registro "flag" sarebbe stato settato e la istruzione nel corpo della "if" sarebbe stata eseguita, quest'ultima non fa altro che rendere negativo il numero moltiplicandolo semplicemente per -1.

L'altro programma, nominato
"InputOutputMonitorInteroMetodo2", è molto simile a quello appena visto, la differenza consiste nel diverso modo per generare le potenze di 10, infatti alla riga 27 di questo secondo programma c'è una "for" che moltiplica tante volte 10 a seconda del peso che  la cifra deve avere, il resto del programma e' identico al precedente a parte alcuni registri che uno possiede e l'altro no.

Per concludere vi ricordo di non inserire spazi o caratteri (a parte il "-")  prima o dopo il numero che volete memorizzare, se lo faceste il risultato sarebbe del tutto errato. Non fatevi inoltre tentare di usare la funzione pow() dato che essa, lavorando con tipi flat, immette continue approssimazioni per cui,  dopo un certo numero di interazioni, non danno risultati corretti.

Programmi

Fabio
HOME