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