Stamani ero al computer senza nulla da fare, e stavo ragionando su un progetto. Facevo la conta dei pin che mi servivano, cercando di ottimizzarne l’uso, visto che avevo a che fare con dei pulsanti da far premere all’utente, e mi è sorta la domanda: c’è un modo semplice per risparmiare pin quando si ha a che fare con i pulsanti? Normalmente si usano chip esterni, dei port expander o degli shift register PISO (Parallel In – Serial Out) , per poter gestire più linee di I/O. Ma se io volessi fare tutto con poca roba, con quei componenti che normalmente si hanno nel cassetto, senza acquistare chip appositi? La soluzione che vi propongo è tanto semplice quanto banale: con 2 pin riuscirete a leggere 3 pulsanti.
Avete mai sentito parlare di charlieplexing? Si tratta di una tecnica mediante la quale si riescono a pilotare molti LED usando pochi pin e sfruttando la capacità dei LED di condurre in una sola direzione (alla fine, sono dei diodi). Ho rigirato il problema: perché non usare un qualche sistema che mi permette di leggere più ingressi usando pochi pin sfruttando dei componenti che conducono in una sola direzione? Usando quindi dei… diodi? Il diodo è un semiconduttore che permette far scorrere la corrente in un unico verso. Se ne accoppio due con i catodi in comune, la corrente scorrerà solo verso il nodo, il punto in comune, ma non da uno all’altro. Quindi se ad esempio ho due pin impostati in input e connessi da 2 diodi uniti come detto, se collego il primo pin a massa, leggerò lo stato LOW solo da questo pin perché l’altro sarà isolato dal diodo polarizzato inversamente. Stessa cosa per il secondo pin. E se collego a massa il nodo comune, il punto di giunzione dei 2 diodi? Leggere uno stato LOW su entrambi i pin, perché entrambi i pin saranno collegati a massa dal corrispondente diodo polarizzato. Ecco quindi l’idea che mi ha portato allo schema seguente:
Proviamo il circuito. Avete bisogno di:
- una breadboard
- 2 diodi (vanno benissimo i comuni 1N4007, oppure anche i diodi veloci 1N4148 così come degli Schottky 1N5819)
- 3 pulsanti di tipo da montaggio superficiale
- cavetti
- una scheda Arduino (UNO, Leonardo)
Realizziamo i collegamenti come nel disegno seguente (realizzato con Fritzing):
Montate i 3 pulsanti centralmente, poi collegate i loro piedini posti in alto a destra sulla linea di massa superiore. Collegate la linea di massa superiore con quella inferiore. Collegate il piedino in basso a sinistra del pulsante di sinistra con i piedino in basso a sinistra del pulsante centrale usando uno dei due diodi: il catodo (il lato segnato con la linea di colore bianca) va a destra. Adesso collegate il piedino in basso a sinistra del pulsante di destra con il piedino in basso a sinistra del pulsante centrale usando l’altro diodo, avendo l’accortezza di rispettare la polarità indicata nel disegno: come nell’altro diodo, il catodo va posto verso il pulsante centrale, quindi il diodo questa volta deve stare con il corpo che presenta la riga bianca a sinistra. Collegate il piedino in basso a sinistra del pulsante di sinistra al pin 7 di Arduino ed il piedino in basso a sinistra del pulsante di destra al pin 6 di Arduino. L’ultimo collegamento va fatto fra un pin GND di Arduino e la linea inferiore di massa della breadboard. Come si vede dallo schema, non usiamo resistenze esterne di pull-up o di pull-down: questa è una scelta precisa fatta per risparmiare componenti. Per dare uno stato ben definito ai pulsanti non premuti useremo perciò le pull-up interne presente su tutti i pin digitali dell’Arduino. A causa di questa scelta, dovremo usare nella funzione che legge i pulsanti la logica inversa, dato che uno stato HIGH sul pin corrisponderà ad un pulsante non premuto mentre uno stato LOW ad un pulsante premuto. Non preoccupatevi: la funzione esegue la conversione per voi.
Adesso caricate il seguente sketch:
/* HOW TO READ 3 BUTTONS USING JUST 2 PIN
Written by Leonardo Miliani
Code released under the Creative Commons License
CC-BY-SA 3.0 or any newer
V. 1.0 - 20140826
*/
//pins declaration - use any pin you like
const byte IN1 = 6;
const byte IN2 = 7;
//setup function
void setup() {
//setting the mode of the pins
pinMode(IN1, INPUT_PULLUP);
pinMode(IN2, INPUT_PULLUP);
Serial.begin(19200); //opening the serial
delay(2000); //a little delay to let the user open the serial monitor
Serial.println(F("Begin"));
}
//main loop
void loop() {
byte reading = readButtons(IN1, IN2); //read the buttons
if (reading) { //a button has been pressed
switch(readButtons(IN1, IN2)) {
case 1: //button 1 pressed
Serial.println(F("Button 1 pressed"));
break;
case 2: //button 2 pressed
Serial.println(F("Button 2 pressed"));
break;
case 3: //button 3 pressed
Serial.println(F("Button 3 pressed"));
break;
}
}
delay(100); //a little delay - remove if unnecessary
}
//read the buttons
byte readButtons(byte inputPin1, byte inputPin2) {
byte response = 0;
//I'm using the inverted logic so I do a "not" (!) to the digital read
//then I combine the readings in a sngle bit using the 2 binary digits
response = (((!digitalRead(inputPin1))<<1) | !digitalRead(inputPin2));
return response;
}
Come funziona il sistema? Come detto, il cuore di tutto sono i 2 diodi. In stato di riposo (nessun pulsante premuto), la funzione readButtons che legge i 2 pin a cui è connessa la matrice di pulsanti vedrà i due ingressi in HIGH (o 1). Ma a noi serve la logica inversa, perché vogliamo che un pulsante non premuto corrisponda ad una lettura LOW (o 0). Per far ciò usiamo il segno di negazione del C, il “!“, che restituisce l’opposto del valore: 0 per 1 e 1 per 0. Uniamo poi le due letture in un’unica coppia di valori binari usando lo spostamento a sinistra (<<). Il valore che ne esce è il valore restituito dalla funzione. Quando premiamo il pulsante a sinistra sulla breadboard solo il pin a cui è agganciato direttamente (il pin 7 di Arduino) verrà collegato a massa, grazie al diodo polarizzato inversamente che lo unisce al pulsante centrale. Stessa cosa per il pulsante a destra. Quindi in entrambi i casi la funzione readButtons, che legge i 2 pin dichiarati nel programma, vedrà una sola pressione. Se premiamo invece il pulsante centrale le cose cambiano: per effetto dei diodi polarizzati direttamente, entrambi i pin verranno collegati a massa.
La tabella della verità della funzione è perciò la seguente:
PIN1 PIN2 LETTURA
1 0 PULSANTE 1
0 1 PULSANTE 2
1 1 PULSANTE 3
2 Responses
[…] gestire 3 pulsanti usando solo 2 canali di entrata di Arduino (potete leggere l’articolo qui http://www.leonardomiliani.com/2014/gestire-3-pulsanti-con-2-soli-pin/ […]
[…] Mi ha molto incuriosito un articolo che spiega come poter gestire 3 pulsanti usando solo 2 canali di entrata di Arduino (potete leggere l’articolo qui http://www.leonardomiliani.com/2014/gestire-3-pulsanti-con-2-soli-pin/) […]