Nell’ultimo articolo abbiamo visto il modo in cui Arduino riesce a riprodurre output di tipo analogico mediante il segnale PWM. 
In questo episodio invece estenderemo il discorso al caso degli input analogici.

È arrivato il momento di smantellare il circuito che abbiamo utilizzato fino ad ora! (vi ci eravate affezionati, vero?). Per far si che Arduino legga degli input analogici e contemporaneamente possa interpretarli, ovviamente abbiamo prima bisogno di componenti elettronici che siano in grado di produrre degli output di questo tipo: in particolare andremo ad utilizzare un potenziometro.

 

IL POTENZIOMETRO

Il potenziometro è un resistore a resistenza variabile.

""""

Si compone di un piccolo cursore (a rotazione) e di tre terminali: quelli alle estremità vanno collegati, uno ai 5V e uno al GND, mentre quello centrale, che erogherà i valori di tensione variabili, va collegato ad un pin di input analogico su Arduino. Nello scorso episodio abbiamo visto che per l’output di tipo analogico bisogna utilizzare i pin contrassegnati da una tilde; nel caso degli input invece ci sono 6 pin dedicati, evidenziati dal prefisso “A” di “Analog input”.

""""

Come è fatto un potenziometro?

All’interno del potenziometro c’è un piccolo circuito circolare fatto di grafite, che non è un buon conduttore, e il funzionamento di questo componente si basa proprio sulla resistenza che la grafite oppone al passaggio della corrente:
""""

  • Girando il cursore in senso orario (si veda l’immagine), la corrente dovrà attraversare un tratto più lungo del circuito grafitico e quindi le verrà opposta una resistenza maggiore. Il risultato sarà un valore minore di tensione sul pin interessato*.
  • Girando invece il cursore in senso antiorario, la corrente dovrà attraversare un percorso più breve e quindi la tensione in uscita sarà maggiore.

Dalla legge di Ohm R=V/I si deduce che, a parità di tensione, l'intensità di corrente è inversamente proporzionale alla resistenza del conduttore.

Per capire il funzionamento degli input analogici scriviamo un programma che legga su un pin i valori di tensione determinati da un potenziometro e stampi a video i risultati mediante la comunicazione seriale.

 

HARDWARE

Per questo piccolo progetto abbiamo bisogno esclusivamente di

  • 1 potenziometro
  • 3 jumper

Ecco il circuito:
""""

Attenzione! Solitamente i terminali del potenziometro non si incastrano perfettamente all’interno della breadboard, e anche dei piccoli spostamenti potrebbero dar luogo a false letture. Per evitare questo problema dovreste avere cura di mantenere fermo il componente durante la rotazione del cursore.

 

SOFTWARE

Ecco il codice:

Come avrete notato non abbiamo dichiarato il pin A0 in modalità di input; questo perchè i pin di input analogico sono pre-settati come tali, quindi non è necessario farlo.

ANALISI DELLE ISTRUZIONI

  • int potenziometro ⇒ la variabile potenziometro conterrà i valori di lettura del pin A1.
  • Serial.begin(9600) ⇒ avviamo una comunicazione seriale a 9600 baud poichè abbiamo bisogno di stampare dei valori di output.
  • potenziometro=analogRead(A0) ⇒ la funzione analogRead() consente di leggere degli input analogici sul pin indicato tra parentesi. Il valore minimo di lettura è 0, mentre il valore massimo è 1023. In questo caso, come già anticipato, i valori restituiti in output dalla funzione saranno scritti nella variabile “potenziometro”.
  • Serial.println(potenziometro) ⇒ stampa il contenuto della variabile “potenziometro” e poi va a capo.
  • delay(100) ⇒ un ritardo tra una stampa e la successiva conferisce stabilità all’output del monitor seriale.

Otterrete un output di questo tipo:

""""

Osservando il risultato delle letture noterete sicuramente che tutti i valori saranno compresi tra un minimo di 0 e un massimo di 1023: la lettura di un pin analogico infatti ha esattamente 1024 passi, cioè 1024 valori diversi che su 5V forniscono una precisione di circa 0,005 Volt.

Adesso però cerchiamo di rendere il programma più interessante per capire magari in che modo è possibile interfacciare, tra loro, input e output analogici. Scriviamo un programma che consenta di controllare la luminosità di un diodo led mediante il potenziometro e contemporaneamente stampi a video i valori di tensione applicati alle estremità del led. 
 

HARDWARE

Abbiamo bisogno dei seguenti componenti: 

  • 1 potenziometro
  • 1 diodo LED
  • 1 resistore da 220 Ω
  • 5 jumper

Questi sono i collegamenti:

""""

SOFTWARE

L’idea è quella di leggere i valori di tensione determinati dal potenziometro e poi scriverli sul pin collegato all’anodo del led. 

In realtà la questione è un po’ più complicata: come abbiamo visto prima, la funzione analogRead() può restituire in output dei valori che vanno da 0 a 1023, ma la funzione analogWrite() accetta esclusivamente valori che vanno da 0 a 255. Per questo motivo possiamo pensare di determinare il valore di scrittura mediante la seguente proporzione:

        valore : 255 = potenziometro : 1023

da cui ricaviamo:

        valore = potenziometro*255/1023

  • La variabile valore (tipo int) conterrà, appunto, i valori da passare alla funzione analogWrite().
  • La variabile potenziometro (tipo int) contiene invece i valori letti dalla funzione analogRead().

L’equazione così ottenuta però dà luogo ad un problema:
la variabile “valore” è di tipo intero, quindi il numero massimo che potrà contenere è “32183”; ebbene, il risultato del prodotto (potenziometro*255) è maggiore di 32183 già per potenziometro=128, infatti (128*255=32640 > 32183). Se ne ricava che per tutti i valori di potenziometro >= 128, la variabile “valore” darà un risultato non valido.

Per risolvere questo problema allora possiamo pensare di invertire tranquillamente l’ordine delle operazioni di prodotto e quoziente, in questo modo:


       valore = potenziometro/1023*255

Ora siamo sicuri che il contenuto della variabile “valore” non supera il numero limite rappresentabile per il tipo intero.
Se invertiamo le operazioni però dobbiamo considerare che la divisione (potenziometro/1023) avrà come risultato non solo numeri interi, ma anche (anzi, soprattutto) decimali. Per questo motivo dobbiamo dichiarare la variabile “valore” con un tipo che possa contenere numeri decimali: il tipo float.   

Ecco il codice:

Attenzione!  valore=potenziometro;

Con questa istruzione il numero contenuto nella variabile  “potenziometro”, che è intero (tipo int), passa alla variabile valore come float, cioè come se fosse un numero decimale. In questo modo ci assicuriamo che non ci siano errori di mancata corrispondenza tra i tipi delle variabili coinvolte nelle operazioni.


Abbastanza complicato, vero? In realtà l’IDE di Arduino è progettato per facilitare la vita ai programmatori e infatti mette a disposizione una funzione che, senza farci “sporcare le mani”, effettua autonomamente la proporzione/conversione dei valori da un intervallo ad un altro.
 

map(variabile,daMin,daMax,aMin,aMax)

La funzione map richiede in input i seguenti parametri: 

  • La variabile che conterrà il valore “mappato”.
  • Il minimo valore dell’intervallo da cui si vuole partire.
  • Il massimo valore dell’intervallo da cui si vuole partire.
  • Il minimo valore dell’intervallo in cui si vuole convertire.
  • Il massimo valore dell’intervallo in cui si vuole convertire.

Ad esempio, l’istruzione 

valore = map(potenziometro,0,1023,0,255)

converte il numero contenuto nella variabile “potenziometro” dall’intervallo [0;1023] all’intervallo [0;255] ed assegna il risultato alla variabile “valore”, e questo è esattamente ciò che ci serve!

Il nuovo codice sarà quindi: