GLG Programs fa uso di cookie per migliorare l'esperienza di navigazione degli utenti, ma non per tracciarne un profilo. Proseguendo nella navigazione, si accetta implicitamente l'utilizzo dei cookie.
[OK]Note legaliNon mi importa
Logo GLGPrograms Logo GLGPrograms

Dispense Arduino

[Icona della Guida] Materiale tratto dal nostro corso di base Arduino, con esempi ed esercizi

Icona sensori dispense

Lettura di sensori

In questa lezione vedremo come usare i pin digitali di Arduino come input, ovvero abilitarli alla lettura di impulsi esterni. Approfondiremo la differenza fra la lettura digitale e analogica, imparando a leggere sia dei semplici impulsi che degli stati di tensione variabili.

Pulsanti e interruttori

Analisi PushButton

Dalla figura vediamo che i pushbuttons hanno solitamente due pin opposti sempre connessi fra loro (in questo caso AC e BD); premendo il bottone si chiude un contatto che cortocircuita le coppie adiacenti AC e BD. Vorremmo adesso applicare questo su Arduino, realizzando un programma che accende un led se il bottone è premuto.
Nota: in definitiva l'effetto del pushbutton è quello di connettere due parti di curcuito, quindi una coppia di pin è ridondante, e serve esclusivamente per comodità nel realizzare circuiti stampati.

Se impostato in lettura, un pin digitale va a determinare lo stato di tensione che vi si applica: così come per l'output possiamo leggere uno stato HIGH, compreso fra i 5 e i 2.5 Volt, e uno stato LOW, fra i 2.5 e gli 0 Volt.

La circuiteria è la seguente: un capo del pulsante è collegato all'alimentazione positiva (5v), l'altro capo arriva sia al pin di Arduino (digital 2), sia ad una resistenza collegata alla massa (GND); con il pulsante a riposo la lettura è LOW, poiché è presente la resistenza collegata a massa. Premendo il pulsante, il pin si viene a trovare a potenziale 5v, e si avra di conseguenza la lettura HIGH.

La funzionalità della resistenza è duplice: se si rimuovesse del tutto si avrebbe una lettura instabile nelle condizioni a riposo, poiché il pin di Arduino, scollegato, sarebbe soggetto a qualsiasi tipo di interferenza elettrostatica (scariche dalle mani, correnti indotte sulla scheda o sulla breadboard...);
Se invece si effettuasse un collegamento diretto a massa, premendo il bottone si avrebbe un cortocircuito. Per questo la resistenza deve avere un valore alto, tale da non provocare inutili correnti, ovvero dell'ordine dei 10kΩ. Puoi verificare, applicando la legge di Ohm, che la corrente che la attraversa in caso pulsante attivo è di circa 500uA, pressoché nulla.

Una resistenza posta in questa configurazione è detta pull-down, per la sua funzionalità di mantenere un segnale basso stabile. Si può porre, analogamente, una resistenza in pull-up collegandola invece al positivo: Si può provare come esercizio a realizzare circuito e programma in tale configurazione.

// Pin del bottone
const byte PIN_BOTTONE = 2;
// Pin del LED
const byte PIN_LED = 13;
// Variabile di stato del bottone
byte statoBottone = 0;

void setup() {
    pinMode(PIN_LED, OUTPUT);       // LED in INPUT
    pinMode(PIN_BOTTONE, INPUT);    // bottone in OUTPUT
}

void loop(){
    // Leggo il bottone e memorizzo lo stato
    statoBottone = digitalRead(PIN_BOTTONE);
    
    // Se il pin del bottone è HIGH (premuto)...
    if (statoBottone == HIGH) {
        // Accendo il LED
        digitalWrite(PIN_LED, HIGH);
    }
    // Altrimenti...
    else {
        // Spengo il LED
        digitalWrite(PIN_LED, LOW);
    }
    delay(10);
}

Pull-up interno

// Pin del bottone
const byte PIN_BOTTONE = 2;
// Pin del LED
const byte PIN_LED = 13;
// Variabile di stato del bottone
byte statoBottone = 0;

void setup() {
    pinMode(PIN_LED, OUTPUT);       // LED in INPUT
    // bottone in OUTPUT, e abilito il PullUp interno
    pinMode(PIN_BOTTONE, INPUT_PULLUP);
}

void loop(){
    // Leggo il bottone e memorizzo lo stato
    statoBottone = digitalRead(PIN_BOTTONE);
    
    // Se il pin del bottone è LOW (premuto)...
    if (statoBottone == LOW) {
        // Accendo il LED
        digitalWrite(PIN_LED, HIGH);
    }
    // Altrimenti...
    else {
        // Spengo il LED
        digitalWrite(PIN_LED, LOW);
    }
    delay(10);
}

Il chip integrato di Arduino ha, per ogni pin di output, una resistenza integrata collegata a +5V (pull-up). Questa può essere collegata internamente (nella figura questa possibilità è stata resa con un interruttore "interno" al chip). L'abilitazione viene fatta nel codice in fase di inizializzazione, impostando il pin come INPUT_PULLUP anziché come INPUT.

Il circuito esterno si semplifica notevolmente, non essendoci più necessità di inserire la resistenza esterna. Nel codice, invece, avremo un'inversione negli stati del bottone: quando non è premuto la lettura è HIGH, quando è premuto LOW.

Ottimizzazione del codice

Le righe 16-20 dei precedenti listati possono essere semplificate accorgendosi che, in configurazione pull-down, lo stato del bottone corrisponde allo stato del LED (bottone LOW → led LOW).

const byte PIN_BOTTONE = 2;  // pin del bottone
const byte PIN_LED =  13;   // pin del led
byte statoBottone = 0;  // variabile di stato del bottone

void setup() {
  pinMode(PIN_LED, OUTPUT);     // il pin del LED è in OUTPUT
  pinMode(PIN_BOTTONE, INPUT);
}

void loop(){
  digitalWrite(PIN_LED, digitalRead(PIN_BOTTONE));
  delay(20);
}

Esercizi

Pulsanti temporizzati

Può essere utile assegnare ad un singolo bottone più funzioni, discriminando il tempo di pressione. Per far questo si ricorre alla funzione millis(), che restituisce il tempo da quando il programma è stato avviato, in millisecondi. Siccome questo è un valore che può essere molto grande, deve essere memorizzato in variabili adatte a contenerlo, in particolare si usa una unsigned long int, che consente di memorizzare un tempo fino a circa 50 giorni.

L'obiettivo del listato è accendere il primo led se si clicca sul pulsante, il secondo se si preme per un secondo, il terzo se si preme per due, infine spegnere tutto se si preme più a lungo.
La struttura del listato riprende l'esercizio "Luci passo passo".

Il segnale analogico

Alcuni sensori analogici Alcuni sensori analogici

I pin Analog di Arduino sono provvisti di una circuiteria hardware supplementare, detta convertitore Analogico-Digitale (ADC) che consente di decodificare un segnale di tensione compresa fra 0~5 Volt in un valore intero leggibile da microcontrollore.

Questo ADC ha una risoluzione di 10bit, questo significa che i valori letti da programma saranno compresi fra 0 e 1023, e che ogni singola unità corrisponde ad una variazione di tensione di circa 5mV (5V/1024).

Possiamo suddividere i sensori analogici in due categorie, che hanno un diverso approccio circuitale: le resistenze variabili e sensori integrati.
Come suggerisce il nome, le resistenze variabili sono componenti con la proprietà di variare la resistenza ai propri capi in funzione delle variazioni esterne. I più comuni sono:

Abbiamo detto che Arduino va a misurare differenze di potenziale: vedremo che i precedenti sensori dovranno essere combinati con una resistenza fissa per poterne leggere le variazioni. Al contrario, i sensori integrati sono già provvisti di una circuiteria specifica che, una volta alimentata dagli appositi pin, restituisce un segnale di tensione variabile sul morsetto di uscita. Alcuni sensori di temperatura (TMP36) ed accelerometri (ADXL3xx) sono così realizzati.

Partitore di tensione Potenziometro esploso

Vediamo quindi come collegare dei sensori resistivi ad Arduino. Il circuito da costruire viene detto partitore di tensione, è composto da due resistenze in serie ai cui capi è presente una differenza di potenziale fissata: nel punto di giunzione è sempre presente una tensione intermedia, che varia in funzione delle resistenze.
Il potenziometro è già un partitore di tensione, per cui se si collegano i morsetti laterali all'alimentazione, sul centrale abbiamo una tensione dipendente dalla posizione della manopola
La fotoresistenza va invece messa in serie ad una resistenza fissa, che abbia un valore più o meno intermedio al range coperto dal sensore, ovvero circa 10kOhm. Osservando il circuito sottostante, analizziamo cosa succede nei due casi limite:

Con il seguente listato andiamo a leggere i valori di tensione sui pin analog0 e analog1, per poi inviarli al computer via USB: puoi leggerli cliccando su serialmonitor dall'IDE Arduino.

Fritzing bottone e led Circuito bottone e led
const byte PIN_POTENZIOMETRO = A0;	// Pin del potenziometro
const byte PIN_FOTORESISTENZA = A1;	// Pin della fotoresistenza
int valoreSensore = 0;		        // Valriabile con il valore letto

void setup() {
  Serial.begin(9600);		// Avvia la comunicazione 
}							// seriale a 9600 baud

void loop() {
      //Legge il valore del sensore, e lo stampa
  valoreSensore = analogRead(PIN_POTENZIOMETRO);
  Serial.print("potenziometro = ");
  Serial.println(valoreSensore);
  valoreSensore = analogRead(PIN_FOTORESISTENZA);
  Serial.print("fotoresistenza = ");
  Serial.println(valoreSensore);
  delay(1000);  // 1 secondo di pausa per poter
}				// leggere i valori

La funzione chiave è analogWrite(pin analogico), che restituisce il valore compreso fra 0 e 1023, proporzionale alla tensione letta sul pin analogico specificato. C'è da notare che il pin non deve essere indicato come input nel setup, poiché la circuiteria dell'ADC è gestita in automatico quando si effettua la lettura.

Bisogna fare un cenno alle funzioni Serial, che riguardano la comunicazione con il computer:

Una trattazione maggiore sarà fatta più avanti, insieme ad altri metodi di comunicazione.

Generazione di numeri casuali

Parlando del bottone si è fatto riferimento ad eventuali interferenze ambientali da evitare; non sempre queste sono un fenomeno indesiderato, ma possono essere sfruttate per la generazione di valori casuali: con la funzione random([minimo,] massimo) che restituisce un valore compreso fra minimo e massimo (se non si specifica un valore minimo, questo è sottointeso come zero).

La generazione trae il suo fattore di casualità effettuando letture da un pin analogico scollegato, e quindi sottoposto a rumore ambientale. Questo deve essere sempre specificato nella setup attraverso la funzione randomSeed(pin analogico). Trovi qui un semplice esempio, che non richiede alcun tipo di circuito.

void setup() {
    // Usa Analog 0 come pin per la lettura
    randomSeed(analogRead(A0));
    // Uso la comunicazione seriale
    Serial.begin(9600);
}

void loop() {
    byte casuale;
    // un numero casuale da 1 a 29
    casuale = random(1, 30);
    Serial.println(casuale);
    delay(500);
}

Esercizi

Pagina scritta da GiulioGiulio

Hai una domanda? Scrivici!
Questa pagina ti è piaciuta? Condividila!
Share on Facebook Share on Google+ Share on linkedin