Leggere 3 pulsanti con 2 pin

Stamattina non sapevo che fare e mi è venuta in mente una idea.
Magari è già stata presentata, non so. Io ve la espongo.

Siete a corto di pin? Dovete leggere 3 pulsanti e volete risparmiare ingressi del vostro Arduino?
Con 2 diodi, potete leggere 3 pulsanti usando 2 soli pin della scheda. Il giochino è molto semplice ed una specie di retro-charlieplexing! :sweat_smile: (con il charlieplexing si possono accendere 3 LED usando 2 soli pin, qui è l’opposto: si possono leggere 3 pulsanti con 2 ingressi).

Basta impostare 2 pin in INPUT con PULL-UP interna attiva e connettere i 3 pulsanti come nello schema allegato. Dal programma si legge lo stato INVERSO del pulsante: se è libero, restituirebbe 1 ma noi vogliamo 0; se è premuto restituirebbe 0, ma noi vogliamo indietro 1. Cosa accade?

Non premendo niente, la lettura consecutiva dei 2 ingressi sarebbe in binario 11, che invertita, diventa 00. Quindi, nessun pulsante premuto. Premendo un pulsante laterale, il corrispondente pin restituisce 0, con la logica invertita diventa 1. Quindi sappiamo che quel pulsante è stato premuto. Ma che succede se premiamo il pulsante centrale? Mettiamo a massa ENTRAMBI i pin (cosa che non accade nelle altre situazioni per la presenza dei 2 diodi). Basta uno switch per sapere quindi quale pulsante è stato premuto.

Ecco la tabella verità (ricordatevi la logica inversa, se vedete 1 in realtà sul pin state leggendo 0):

PIN1   PIN2      LETTURA
 1      0       PULSANTE 1
 0      1       PULSANTE 2
 1      1       PULSANTE 3

Il sistema si può ovviamente espandere e trasformare il libreria ma per lo scopo didattico per cui è nato, va già più che bene.

const byte IN1 = 6;
const byte IN2 = 7;

void setup() {
  pinMode(IN1, INPUT_PULLUP);
  pinMode(IN2, INPUT_PULLUP);
  Serial.begin(19200);
  delay(2000);
  Serial.println(F("Begin"));
}

void loop() {
    byte reading = readButtons(IN1, IN2);
    if (reading) { //a button has been pressed
        //while (readButtons(IN1, IN2)); //wait for the button release
        switch(readButtons(IN1, IN2)) {
            case 1: //button 1 pressed
                Serial.println(F("Button 1 pressed"));
                break;
            case 2:
                Serial.println(F("Button 2 pressed"));
                break;
            case 3:
                Serial.println(F("Button 3 pressed"));
                break;
        }
    }
    delay(100); //a little delay - remove if unnecessary
}

byte readButtons(byte inputPin1, byte inputPin2) {
    byte response = 0;
    
    response = (((!digitalRead(inputPin1))<<1) | !digitalRead(inputPin2));
    return response;
}

schema.png

Manca l'else di "if (reding)" per l'opzione nessun pulsante premuto.

E' un codice di esempio, serve solo a far capire come gestire la lettura. Se uno ha bisogno anche di un'azione "nessun pulsante premuto" aggiunge l'else. Ma ai fini della comprensione del sistema non serviva mettercelo.

Diavolo d'un @Leo ]:) :grin:

E' magari una strnzt ma sono proprio quelle cose a cui la gente non pensa. :stuck_out_tongue_closed_eyes:

Forse si potrebbe ottenere la.stessa cosa con un pi unico analogico alternando pulsante e resistenza :(

Ovvio che sì. Basta tarare bene le R da usare e puoi leggere da un unico pin analogico più valori. E poi il sistema sui pin analogici è già stato fatto ;)