Introduzione
Le resistenze di pull-up e di pull-down sono molto comuni quando si utilizzano i microcontrollori o qualsiasi altro dispositivo digitale.
I pin di ingresso dei circuiti digitali presentano normalmente un’impedenza abbastanza alta, e questo significa che basta una corrente minima per poter cambiarne lo stato. Ma significa anche che sono soggetti a captare qualsiasi disturbo elettromagnetico o elettrostatico e quindi a commutare le loro uscite in modo del tutto imprevisto ed incontrollato. Un pin di ingresso che si trova in questo stato (cioè a cui non è collegato nulla) si definisce in stato di floating (fluttuante).
Lasciare un circuito in questo stato è un errore molto grave, in quanto è possibile (e senza dubbio lo sarà) che campi elettrici e magnetici esterni indurranno sul pin in questione delle tensioni (anche piccole) tali da far commutare il circuito interno.
Da qui deriva la necessità di impostare il suddetto pin in uno stato perfettamente conosciuto, che non possa portare a stati di incertezza sulle letture effettuate.
Cosa è una resistenza di pull-up
Ecco quindi che viene introdotto il concetto di resistenza di pull-up e di pull-down.
Si inserisce una piccola resistenza tra il pin di ingresso e la tensione di riferimento, per fare in modo che all’ingresso sia sempre presente un segnale certo. Se la resistenza viene inserita tra il pin e la Vdd si parlerà di resistenza di pull-up, se invece viene inserita tra il pin e la Vss (normalmente GND o 0V) si parlerà di resistenza di pull-down.
Vediamo degli esempi concreti.
Con la resistenza R1, il potenziale del pin è impostato alla tensione di riferimento Vcc (in questo caso 5V). Quando l’interruttore viene chiuso l’ingresso viene portato a massa.
Quindi gli stati possibili per il pin vengono ben definiti dalle tensioni presenti ai due capi della connessione, senza possibili disturbi esterni.
Adesso invertiamo la logica e colleghiamo la resistenza tra il pin e la massa, e l’interruttore tra il pin e la Vcc.
Con la resistenza R1, il potenziale del pin è impostato alla tensione di riferimento Vss (in questo caso 0V). Quando l’interruttore viene chiuso l’ingresso viene portato al valore di Vcc.
Anche in questo caso, gli stati possibili per il pin sono ben definiti dalle tensioni presenti ai due capi della connessione.
Calcolare il valore della resistenza di pull-up
A questo punto ci si pone quindi il dubbio su quali sono i valori accettabili per una resistenza di pull-up o di pull-down da collegare ad un porta di ingresso logico?
La resistenza deve essere dimensionata per poter svolgere correttamente il suo lavoro, cioè quello di portare a livello alto la tensione sul pin di ingresso.
Bisogna considerare che il circuito equivalente del pin di ingresso può essere sintetizzato come una resistenza, che chiamiamo Ringresso.
Quando il pulsante è aperto, il pin di ingresso si trova nello stato HIGH e la corrente che fluisce nel circuito è bassa per via della resistenza, ma grazie all’alta impedenza sarà sufficiente a mantenerne alto lo stato.
Quando il pulsante viene premuto la corrente fluisce a massa e la tensione è prossima a 0V , portando il pin nello stato LOW.
Quindi il dimensionamento della resistenza di pull-up dipende molto dall’impedenza del pin di ingresso, che si può conoscere leggendo il datasheet del microcontrollore.
Proviamo a fare dei calcoli per vedere come cambiano i valori di corrente e di tensione al pin di ingresso al variare della R1
Fissiamo i seguenti valori:
- Vin = tensione di alimentazione = 5 V
- Ringresso = 1 MΩ
R1 | Ringresso | Req (Ω) | Vpin | I (A) | Potenza (W) |
1 Ω | 1 MΩ | 0,99999900 | 4,99999500 | 5 | 25 |
10 Ω | 1 MΩ | 0,99999000 | 4,99995000 | 0,5 | 2,5 |
100 Ω | 1 MΩ | 0,99990001 | 4,99950005 | 0,05 | 0,25 |
1 kΩ | 1 MΩ | 0,99900100 | 4,99500500 | 0,005 | 0,025 |
10 kΩ | 1 MΩ | 0,99009901 | 4,95049505 | 0,0005 | 0,0025 |
100 kΩ | 1 MΩ | 0,90909091 | 4,54545455 | 0,00005 | 0,00025 |
1 MΩ | 1 MΩ | 0,50000000 | 2,50000000 | 0,000005 | 0,000025 |
10 MΩ | 1 MΩ | 0,09090909 | 0,45454545 | 0,0000005 | 0,0000025 |
100 MΩ | 1 MΩ | 0,00990099 | 0,04950495 | 0,00000005 | 0,00000025 |
Possiamo notare 3 cose:
- per valori bassi di R1, la caduta di tensione è irrilevante, ma la corrente che entra nel pin di ingresso è molto alta, con relativi alti consumi
- per valori compresi tra 1/100 Ringresso < R1 < 1/10 Ringresso la caduta di tensione è irrilevante ed i consumi sono contenuti
- per valori di R1 dello stesso ordine di grandezza di Ringresso o superiori, la caduta di tensione è notevole e potrebbe non essere sufficiente a portare il pin a livello HIGH
Nella pratica si può quindi applicare la regola empiricamente corretta di utilizzare una resistenza di pull-up (o di pull-down) pari ad 1/10 della Ringresso.
Nei progetti con Arduino possiamo tranquillamente utilizzare una resistenza di pull-up di circa 10 kΩ.
Passiamo alla pratica
Realizziamo un semplice circuito con Arduino e verifichiamo l’utilità di una resistenza di pull-down sul pin di ingresso di un pulsante.
Ecco cosa servirà per proseguire con gli esperimenti:
- Breadboard
- Resistori
- Arduino Uno Kit
- Mini Interruttori
- LED
- Batterie o alimentatore per circuiti
Realizziamo quindi il circuito come nella figura seguente:
Normalmente per leggere lo stato di un pulsante (aperto / chiuso) sarebbe bastato un ingresso digitale (LOW / HIGH), ma ho scelto di utilizzare come input un pin analogico per poter “visualizzare” meglio le oscillazioni prodotte da un pin in stato di floating.
Ecco il codice da caricare sul nostro Arduino:
// Accende e spegne un LED quando viene premuto
// il pulsante collegato sul pin 2
/**********************************/
const int keyPin = A2; // il pin pulsante
const int ledPin = 8; // il pin del led
int val = 0; // il valore letto dal pin analogico
/**********************************/
void setup()
{
pinMode(keyPin,INPUT); // inizializza il pin del pulsante come INPUT
pinMode(ledPin,OUTPUT); // inizializza il pin del LED come OUTPUT
Serial.begin(9600);
}
/**********************************/
void loop()
{
// legge il valore sul pin del pulsante
// e controlla se il pulsante è stato premuto
// se è stato premuto imposta lo stato del LED
// su HIGH, altrimenti su LOW
val = analogRead(keyPin);
Serial.println(val);
if(val >= 1023 )
{
digitalWrite(ledPin,HIGH);//turn on the led
}
else
{
digitalWrite(ledPin,LOW);//turn off the led
}
}
/************************************/
Come si può notare, sul pin di ingresso n° 2 è stata inserita una resistenza di pull-down da 10 kΩ, che porta la tensione del pin analogico A2 a 0V quando il pulsante non è premuto. Per visualizzare i valori letti sul pin, apriamo il monitor seriale premendo la combinazione di tasti Ctrl+Maiusc+M ed analizziamo le lettura fatte dal nostro codice.
Così come è stato progettato il circuito, fino a quando il pulsante risulta aperto, sul monitor seriale viene visualizzato il valore zero, mentre invece se il pulsante viene premuto il valore scritto è 1023 (il massimo leggibile su un pin analogico) equivalente in questo caso alla tensione massima del circuito e cioè 5V.
Adesso mettiamo il pin in stato di floating, eliminando la resistenza tra il pin A2 ed il pulsante.
Sul monitor seriale immediatamente vengono visualizzati tanti valori fluttuanti, sempre diversi uno dall’altro… ecco cosa significa avere un ingresso in stato di floating, ed ecco a cosa serve inserire una resistenza di pull-up o di pull-down nei circuiti elettronici.
Guglielmo dice
Ciao
ho un un arduino pro mini alimentato a batterie, collegato ad un interruttore magnetico. Per ridurre al minimo i consumi conviene una resistenza di pull-up o di pull-down?
Grazie
emanuele dice
Ciao Guglielmo, se utilizzare pull-up o pull-down dipende dalla logica dell’interruttore, cioè se deve ricevere un segnale costantemente alto, oppure basso. Per ridurre al minimo i consumi, invece, bisogna utilizzare una resistenza il più grande possibile, come descritto nell’articolo.
Kim dice
Ciao, guarda che nel codice che hai scritto c’è un errore, manca una A prima del 2,
Così legge il pin digitale 2 e mostra una serie di valori fluttuanti.
hai scritto
const int keyPin = 2; // il pin pulsante
invece di
const int keyPin = A2; // il pin pulsante
Ciao
Emanuele dice
Ciao Kim, grazie per la segnalazione. Ho apportato la modifica che giustamente hai indicato.
Paolo dice
Ciao come calcoli la resistenza equivalente??
Loris dice
ciao Emanuele
ti volevo chiedere se quanto sopra si applica solo agli ingressi analogici o anche ai digitali.
Esempio un ingresso analogico a cui è collegato un LM 35 per leggere la temperatura avrò bisogno di una pull down o posso andare diretto sull’input? dallo schema di un termostato che mi ritrovo è così
Emanuele dice
Ciao Loris, per un sensore analogico come il sensore di temperatura LM35, non avrai bisogno di inserire nessuna resistenza di pull-up/down, in quanto dovrai andare a leggere il valore grezzo della resistenza, sul morsetto del segnale del sensore.
Il collegamento DEVE quindi essere fatto direttamente sulla porta analogica.
Francesco Maffia dice
Salve, io avrei bisogno di misurare i giri di un torsiometro il cui segnale di rpm è fornito in forma ùttl con 60 impulsi / giro. Mi dicono di applicare un pull up resistor di 1KOhm, ma da profano della materia non capisco come. Io vedo solo i due fili in uscita dal mio torsiometro, quello di segnale e quello di ground.
Potete consigliarmi?
Grazie
Francesco
Plinio dice
Questa condizione, scritta in questo modo: if(val >= 1023 ), non ha senso. Il valore massimo è 1023, per cui la condizione di maggiore non si verificherà mai, basta l’eguale, oppure si verifica un valore diverso dal massimo, ed esempio if(val >= 1000 ).
angelo dice
salve, mi perdoni sono alle prime armi con Arduino..Ho provato a simulare lo sketch con Tinkercad ma ricevo errore sulla riga relativa alla stringa
if(val >= 1023 )
ok il concetto di if val è chiaro ma a cosa serve > ??? Quale correzione dovrebbe essere apportata?
Grazie
Emanuele Genovese dice
Ciao Angelo, purtroppo qualche aggiornamento dei plugin ha modificato il contenuto dell’articolo.
In questo caso ha convertito in codice HTML il simbolo di maggiore.
Adesso ho corretto la riga di codice.
if(val >= 1023 )