Analogico o Digitale?
- I segnali in ingresso e in uscita possono essere analogici o digitali.
- Un segnale analogico può assumere qualsiasi valore (all’interno di un range noto). Con notevole semplificazione, si può pensare che siano “analogiche” tutte le grandezze fisiche misurabili nell’ambiente.
- Un segnale digitale può assumere due soli stati (High/Low, 1/0), corrispondenti a due livelli di tensione convenzionali (ad esempio, 5-0V). Con simile semplificazione, si può pensare che siano “digitali” tutte le informazione scambiate tra componenti logici (microprocessori, memorie, interfacce di rete, display…).
Come viene letto un segnale Analogico o Digitale?
- Affinchè possa essere letto ed elaborato da Arduino, il segnale analogico deve essere campionato, ovvero convertito in una sequenza di bit che ne esprime l’ampiezza.
- Un segnale digitale è immediatamente “leggibile” non appena ne è stato discriminato il livello (Hight/Low).
- Del segnale analogico interessa leggere il valore istantaneo, opportunamente campionato.
- Del segnale digitale occorre sapere solo lo stato alto o basso.
Arduino come riconosce se un segnale è di ingresso o di uscita?
- Affichè Arduino riconosca se sul PIN a cui facciamo riferimento sia presente un segnale di Ingresso o Uscita, I PIN digitali devono essere preventivamente impostati in modalità input o output. Questo avviene tramite pinMode.
Esempio: pinMode(13, OUTPUT);
imposta il PIN 13 in modalità OUTPUT. Questo significa che dal PIN 13 può “uscire” un segnale digitale e quindi potrà risultare Alto o Basso. (In pratica a livello elettronico potrà essere emessa una tensione che assumerà due soli valori, 5V o 0V).
Esempio: pinMode(2, INPUT);
Questo esempio, invece, imposta il PIN 2 in modalità INPUT. Questo significa che dal PIN 2 può “entrare” un segnale digitale che come nel caso precedente dovrà risultare Alto o Basso.
Da notare bene che solo i PIN Digitali vanno preventivamente impostati, quelli analogici no.
Come leggo o scrivo sui PIN?
- La lettura e Scrittura avvengono attraverso funzioni dedicate.
- Per i PIN Digitali abbiamo:
digitalWrite() e digitalRead()
- Per i PIN Analogici invece:
Esempio di “scrittura” Digitale :
pinMode(13, OUTPUT); //Imposto il PIN 13 in modalità OUTPUT digitalWrite(13, HIGH); //Scrivo sul PIN 13 il valore Alto
Questo codice imposta prima il PIN 13 in modalità OUTPUT (come visto in precedenza). Successivamente “Scrive” sullo stesso PIN un valore Alto.
Esempio di “lettura” Analogica:
int valore; //Dichiaro una variabile intera di nome "valore" valore = analogRead(1); //Assegno alla variabile la lettura del PIN 1
Questo codice dichiara una variabile intera di nome “valore”. Succesivamente assegna a quest’ultima il valore analogico “letto” sul PIN Analogico 1.
Dove sono i PIN di INPUT/OUTPUT su Arduino UNO R3?
Differenza tra Input Digitale e Input Analogico
- A differenza di un Ingresso Digitale che può assumere i due valori LOW (basso) e HIGH (Alto) che corrispondono rispettivamente ad una tensione nulla (GND) o positiva (+5V), con un Ingresso Analogico è possibile leggere tensioni comprese tra 0 e +5V.
- La funzione analogRead(), come abbiamo visto nell’esempio precedente, riceve come parametro il numero del PIN Analogico da leggere e restituisce un numero intero assegnandolo ad una variabile.
Il numero intero restituito è compreso tra 0 e 1023. Questo significa che il segnale analogico in ingresso viene campionato con una risoluzione di 10 Bit (2^10=1024), ovvero divedendo la massima tensione (+5V) applicabile all’ingresso per 1024 otteniamo una unità di 4,9 mV (la risoluzione massima espressa in Volts).
Qualsiasi grandezza opportunamente trasformata in una tensione può essere letta da Arduino:
- Temperatura: sensore di temperatura
- Rotazione: potenziometro
- Intensità luminosa: fotoresistenza
- Distanza: sensore ad infrarossi
- Inclinazione: accelerometro
- …
I Pin PWM su Arduino
Arduino possiede 3 moduli OC (Output Compare), che fanno capo a 6 uscite PWM (pin 3, 5, 6, 9, 10 e 11 : ogni modulo ha 2 uscite). I 3 moduli sono contraddistinti dalle sigle OC0, OC1 e OC2 e vengono gestiti ognuno da un diverso timer:
Pin Arduino | Pin ATMega 328 | Modulo | Timer |
---|---|---|---|
6 | PD6 (OC0A) | OC0 | TCCR0 |
5 | PD5 (OC0B) | ||
9 | PB1 (OC1A) | OC1 | TCCR1 |
10 | PB2 (OC1B) | ||
11 | PB3 (OC2A) | OC2 | TCCR2 |
3 | PD3 (OC2B) |
Ogni modulo, essendo pilotato da un diverso Timer, ha la possibilità di operare ad una frequenza diversa dagli altri. E’ ovvio che i due pin appartenenti allo stesso modulo opereranno sempre alla stessa frequenza pur potendo variare individualmente il duty cycle.
Normalmente chi utilizza Arduino, per poter sfruttare il PWM, è abituato ad utilizzare la seguente funzione:
analogWrite(pin, valore);
dove pin assume il valore 6, 5, 9, 10, 11 o 3, e valore è un numero tra 0 (duty cycle:0%) e 255 (duty cycle:100%). Molti, purtroppo, ignorano la questione della frequenza: ok sto impostando il duty cycle… ma a che frequenza sto lavorando? E soprattutto: sono vincolato ad una frequenza fissa oppure ho la possibilità di variarla?
Di default Arduino imposta i pin 9, 10, 11 e 3 (moduli OC1 e OC2) per lavorare a 488Hz, e i pin 6 e 5 (modulo OC0) a 976Hz.
Segnale PWM Arduino sui pin 3, 9, 10, 11
Segnale PWM Arduino sui pin 5 e 6
Queste frequenze così basse potrebbero andare bene per variare la luminosità di un led ma non certo per pilotare un motore o generare un segnale analogico, come purtroppo molti fanno.
Il segnale PWM accetta come valori da 0 a 255, per ciascun valore varia il duty-cycle generato, ad esempio con il valore 0 otterrai un valore di duty-cycle dello 0% ossia sempre 0 in modo analogo a quello che avresti ottenuto utilizzando digitalWrite(pin,LOW).
Ricorda sempre di settare la modalità del pin prima di eseguire l’invio dei comandi, in questo esempio ho utilizzato il pin 11 scrivendo: pinMode(11,OUTPUT) indico ad Arduino di utilizzarlo in modo OUTPUT ( come una uscita ); posso quindi inviare il mio segnale con duty-cycle al 50%: analogWrite(11,127), avrai notato che ho utilizzato analog Write anche se il pin 11 è un pin digitale, il motivo è che il tipo di segnale che desidero generare ha una variazione di valori da 0 a 255 e non solo 0 e 1, la funzione digitalWrite accetta come secondo parametro solo 0 e 1 oppure LOW e HIGH. Il valore 127 è esattamente a metà della mia scala ( 0 – 255 ) quindi il duty-cycle generato sarà del 50%.
Per comprendere meglio la questione duty-cycle ho preso l’immagine riportat sul sito Arduino contenete alcuni valori simbolo del duty-cycle in funzione del numero che specificherai:
Esempio di lettura analogica tramite sensore di temperatura LM35DZ
- I sensori Analogici attivi (quelli ai quali è necessario fornire alimentazione) forniscono un segnale leggibile direttamente da Arduino.
Il sensore di temperatura LM35DZ restituisce una tensione d’uscita proporzionale alla temperatura ambientale: 10 mv per ogni °C (grado centigrado).
Poichè è un sensore attivo occorrerà fornigli alimentazione. Quest’ultima può essere prelevata direttamente da Arduino che mette a disposizione dei PIN opportuni. Il sensore è dotato di tre piedini, rispettivamente due di alimentazione (GND e +5v) e uno di uscita (VOUT). Quindi occorrerà semplicemente collegare i tre piedini del sensore direttamente ai PIN opportuni di Arduino secondo il seguente schema:
Abbiamo deciso di utilizzare come PIN Analogico di Ingresso il numero 5, come facilmente osservabile dallo schema.
A questo punto vediamo come implementare lo sketch del prototipo:
int PIN_TEMP=5; //Assegniamo alla variabile il pin di ingresso analogico scelto int temp; //Dichiariamo la variabile che conterrà il valore della temperatura void setup() { } void loop() { temp= analogRead(PIN_TEMP)*0.5; //Assegniamo alla variabile temp il valore restituito dalle lettura del pin 5 delay(100); //Aspettiamo 100 mS prima di leggere un nuovo valore }
- Perche abbiamo moltiplicato la lettura per 0.5 ?
Ogni step di analogRead() corrisponde a circa 5mV (la risoluzione è di 4,9 mV, ricordate?); Un grado centigrado corrisponde a un intervallo di 10mV, dunque:
temp=analogRead(PIN_TEMP)* 5/10