Tre tasti interbloccati con reset.

Buon Giorno, ho avuto la necessità di realizzare un circuito con dei tasti interbloccati con il seguente funzionamento: la selezione di un qualsiasi tasto esclude il funzionamento degli altri due, ritorna a riposo
premendo il reset.

Metto a disposizione questo sketch perchè non ho visto in rete qualcosa di simile con l'occasione vi chiedo di dare u'occhiata allo stesso per un vosto autorevole parere, ho ripreso da poco è sono "arrugginito", poichè tutto è perfettibile datemi eventuali consigli.

#define pgen  13    //pulsante 1
#define pqua  14 //pulsante 2
 int pinv = 3;    //pulsante 3
 int pres = 4;   //pulsante reset
 int lrgen = 6;  // led 1
 int lrqua = 7; // led 2
 int lrinv = 8; // led 3
 int statolrgen = LOW; //stato led1
 int statolrqua = LOW; //stato led2
 int statolrinv = LOW; //stato led3
 

void setup() {
 pinMode (lrgen, OUTPUT);
 pinMode (lrqua, OUTPUT);
 pinMode (lrinv, OUTPUT);
 pinMode (pgen, INPUT);
 pinMode (pqua, INPUT);
 pinMode (pinv, INPUT);
 pinMode (pres, INPUT);

} 
 
 
  
 
void loop(){
   
        // gestione tasti
  
 if (digitalRead(lrqua) == HIGH && digitalRead(lrinv)==HIGH){
  statolrgen = digitalRead(pgen);
  }
  if  (statolrgen == HIGH){ // tasto1 premuto
  digitalWrite(lrgen, LOW);
  delay(40);
  }
  if (digitalRead(lrgen) == HIGH && digitalRead(lrinv)==HIGH){
  statolrqua = digitalRead(pqua);
  }
  if (statolrqua == HIGH){  // tasto2 premuto
  digitalWrite(lrqua, LOW);
  delay(40);
  }
  if (digitalRead(lrgen) == HIGH && digitalRead(lrqua)==HIGH){
  statolrinv = digitalRead(pinv);
  }
  if (statolrinv == HIGH){ // tasto3 premuto            
  digitalWrite(lrinv, LOW);
  delay(40);
  }
          
          if (digitalRead(pres) == HIGH)// tasto reset premuto
          {
          digitalWrite (lrgen, HIGH);
          digitalWrite (lrqua, HIGH);
          digitalWrite (lrinv, HIGH);
          }       
}

Grazie a tutti voi.

  1. usa il CTRL+T dentro ad IDE che ti indenta meglio il codice

  2. non mi pare bello usare per alcune costanti la define e per altre un int semplice

  3. se usi una variabile per definire un valore che in realtà è costante, come i numeri dei pin,
    o usi define oppure const byte
    const byte pinRes = 4; //pulsante reset
    ed inoltre come prima parte del nome specificherei che rappresenta un pin, 2 caratteri in più chiariscono a cosa serve

Ok , nelle prove fatte non ho rimesso la costante corretta per tutti i pin, per il tasto di reset ho bisogno di capire meglio cosa fà ciò (const byte pinRes = 4; //pulsante reset). ho corretto lo sketch.

(come prima parte del nome specificherei che rappresenta un pin, 2 caratteri in più chiariscono a cosa serve) sè intendi l'abbreviazione "pgen" per mè è pulsante generatore ma pensavo fosse irrilevante.

#define pgen  13 //pulsante 1
#define pqua  14 //pulsante 2
#define pinv  3  //pulsante 3
#define pres  4  //pulsante reset
#define lrgen 6  // led 1
#define lrqua 7  // led 2
#define lrinv 8  // led 3
int statolrgen = LOW; //stato led1
int statolrqua = LOW; //stato led2
int statolrinv = LOW; //stato led3


void setup() {
  pinMode (lrgen, OUTPUT);
  pinMode (lrqua, OUTPUT);
  pinMode (lrinv, OUTPUT);
  pinMode (pgen, INPUT);
  pinMode (pqua, INPUT);
  pinMode (pinv, INPUT);
  pinMode (pres, INPUT);

}




void loop() {

  // gestione tasti

  if (digitalRead(lrqua) == HIGH && digitalRead(lrinv) == HIGH) {
    statolrgen = digitalRead(pgen);
  }
  if  (statolrgen == HIGH) { // tasto1 premuto
    digitalWrite(lrgen, LOW);
    delay(40);
  }
  if (digitalRead(lrgen) == HIGH && digitalRead(lrinv) == HIGH) {
    statolrqua = digitalRead(pqua);
  }
  if (statolrqua == HIGH) { // tasto2 premuto
    digitalWrite(lrqua, LOW);
    delay(40);
  }
  if (digitalRead(lrgen) == HIGH && digitalRead(lrqua) == HIGH) {
    statolrinv = digitalRead(pinv);
  }
  if (statolrinv == HIGH) { // tasto3 premuto
    digitalWrite(lrinv, LOW);
    delay(40);
  }

  if (digitalRead(pres) == HIGH)// tasto reset premuto
  {
    digitalWrite (lrgen, HIGH);
    digitalWrite (lrqua, HIGH);
    digitalWrite (lrinv, HIGH);
  }
}

La define si usa anche per le costanti ma in realtà è una sostituzione brutale della parola fatta dal preprocessore.

Una variabile pres o pinv è inutile sia "variabile" meglio dichiararla costante. Quindi la parola const davanti.
Poi, un pin (ma anche il valore della digitalRead) è un valore piccolo, un int occupa 2 byte, meglio usare byte

Dalle prove fatte vedendo poi cosa fa il compilatore gcc con una const byte abbiamo visto che NON crea e occupa in memoria un byte, ma la tratta un pò come la define, sostituisce dove usata semplicemente il suo valore.
Ma a differenza di define, const byte dice al compilatore che è un valore byte, mentre la define non lo dice

sal_co_:
(come prima parte del nome specificherei che rappresenta un pin, 2 caratteri in più chiariscono a cosa serve) sè intendi l'abbreviazione "pgen" per mè è pulsante generatore ma pensavo fosse irrilevante.

Il tuo programma fa già quello che deve. I miei suggerimenti sono solo "estetici" e per migliorare la leggibilità.
Oggi tu sai bene che pres è un pulsante, ma tra un mese riguardi il programma... ti ricordi cosa è pres a meno che non vai in testa al programma a leggerti la annotazione ? Non ti pare che un nome pinRes sia più chiaro ? Solo solo suggerimenti

nid69ita:
La define si usa anche per le costanti ma in realtà è una sostituzione brutale della parola fatta dal preprocessore.

Una variabile pres o pinv è inutile sia "variabile" meglio dichiararla costante. Quindi la parola const davanti.
Poi, un pin (ma anche il valore della digitalRead) è un valore piccolo, un int occupa 2 byte, meglio usare byte

Dalle prove fatte vedendo poi cosa fa il compilatore gcc con una const byte abbiamo visto che NON crea e occupa in memoria un byte, ma la tratta un pò come la define, sostituisce dove usata semplicemente il suo valore.
Ma a differenza di define, const byte dice al compilatore che è un valore byte, mentre la define non lo dice

Ok intanto grazie ora vedo fare un ulteriore revisione, sono perfettamente d'accordo modificherò le descrizioni.
Ti sarei grato sè mi postassi un esempio pratico per il tasto reset e dei pin ( perdonami ma sto riprendendo dopo tanti anni ).

nid69ita:
La define si usa anche per le costanti ma in realtà è una sostituzione brutale della parola fatta dal preprocessore.

Ma a differenza di define, const byte dice al compilatore che è un valore byte, mentre la define non lo dice

e infatti proprio perché non lo dice usare una #define permette delle ottimizzazioni più spinte, al compilatore

io (e mio fratello pure) uso sempre delle #define se si tratta di valori costanti per progetto

la parola chiave const (che è stata aggiunta non si sa perché nel 'C') servirebbe solo per impedire di modificare delle variabili

che menata è?

se è variabile è variabile, altrimenti uso una #define

se è variabile deve avere un indirizzo, essere puntabile etc. etc.

se è una #define non deve avere nulla di tutto questo

è sbagliato consigliare l'uso di const come se fosse una forma "intelligente" di #define, è l'esatto opposto

sal_co_:
vi chiedo di dare u'occhiata allo stesso per un vosto autorevole parere, ho ripreso da poco è sono "arrugginito", poichè tutto è perfettibile datemi eventuali consigli.

Le costanti per convenzione si scrivono in maiuscolo, così si distinguono dalle variabili a colpo d'occhio.
Le variabili 'statolrgen' ecc sono fuorvianti, servono a contenere le letture dei pulsanti, quindi molto meglio usare nomi come 'statopgen' ecc.
I delay 40 in tutte le righe si possono togliere e metterne uno solo alla fine.

if (digitalRead(LRQUA) == HIGH  &&  digitalRead(LRINV) == HIGH) {
  statopgen = digitalRead(PGEN);
}
if (statopgen == HIGH) { // tasto1 premuto
  digitalWrite(LRGEN, LOW);
}

Invece di leggere gli ingressi mettendoli in una variabile, e leggere le altre uscite per sapere se si può procedere o se si è in condizione implicita di blocco, meglio usare una variabile esplicita 'blocco', la logica diventa più breve e leggibile:

if (digitalRead(PGEN) == HIGH  &&  blocco == 0) { // tasto1 premuto
  blocco = 1;
  digitalWrite(LRGEN, LOW);
}

se ho capito bene tu vuoi fare quello che si chiama "radio button", come nelle vecchie radio ani 70
qualunque bottone sia premuto se ne premi un altro quello già premuto si sgancia e si accende solo il led corrispondente al nuovo premuto
e un master reset sgancia senza accendere nulla

e riprendendo l'idea di usare variabili invece di define
tra poco vedi perché

scritta al volo qui

// radio button
// del dinamico duo



// quanti gruppi
#define GRUPPI 3
// un array di bottoni
byte pulsanti[GRUPPI] = {13,14,3}; //copiati da te
//un array di led
byte led[GRUPPI]={6,7,8};
//master reset
#define RESET 4


void setup(void){
   for (byte i=0; i<GRUPPI;i++){
      pinMode(pulsanti[i],INPUT);
      pinMode(led[i],OUTPUT);
      }
   pinMode(RESET,INPUT);
   }


void loop(void){
   for (byte i=0; i<GRUPPI;i++){
      if(digitalRead(pulsanti[i])){
         spegnitutto();
         digitalWrite(pulsanti[i],HIGH);
         }
      }
   if(digitalRead(RESET){
      spegnitutto();
      }
   }


void spegnitutto(void){
   for (byte i=0; i<GRUPPI;i++){
      digitalWrite(pulsanti[i],LOW);
      }
   }

e che Massimo mi perdoni per avergli rubato l'idea

Ducembarr:
se ho capito bene tu vuoi fare quello che si chiama "radio button", come nelle vecchie radio ani 70
qualunque bottone sia premuto se ne premi un altro quello già premuto si sgancia e si accende solo il led corrispondente al nuovo premuto
e un master reset sgancia senza accendere nulla

e riprendendo l'idea di usare variabili invece di define
tra poco vedi perché

scritta al volo qui

// radio button

// del dinamico duo

// quanti gruppi
#define GRUPPI 3
// un array di bottoni
byte pulsanti[GRUPPI] = {13,14,3}; //copiati da te
//un array di led
byte led[GRUPPI]={6,7,8};
//master reset
#define RESET 4

void setup(void){
  for (byte i=0; i<GRUPPI;i++){
      pinMode(pulsanti[i],INPUT);
      pinMode(led[i],OUTPUT);
      }
  pinMode(RESET,INPUT);
  }

void loop(void){
  for (byte i=0; i<GRUPPI;i++){
      if(digitalRead(pulsanti[i])){
        spegnitutto();
        digitalWrite(pulsanti[i],HIGH);
        }
      }
  if(digitalRead(RESET){
      spegnitutto();
      }
  }

void spegnitutto(void){
  for (byte i=0; i<GRUPPI;i++){
      digitalWrite(pulsanti[i],LOW);
      }
  }





e che Massimo mi perdoni per avergli rubato l'idea

Forse non ho esposto bene il funzionamento dei quattro tasti; i primi tre sono di selezione, il quarto di reset, il primo tasto che viene selezionato manda in blocco gli altri due, passando dal reset ritornano tutti selezionabili.

Indicatore di primo evento, quindi

Non difficile.

Claudio_FF:
Le costanti per convenzione si scrivono in maiuscolo, così si distinguono dalle variabili a colpo d'occhio.
Le variabili 'statolrgen' ecc sono fuorvianti, servono a contenere le letture dei pulsanti, quindi molto meglio usare nomi come 'statopgen' ecc.
I delay 40 in tutte le righe si possono togliere e metterne uno solo alla fine.

if (digitalRead(LRQUA) == HIGH  &&  digitalRead(LRINV) == HIGH) {

statopgen = digitalRead(PGEN);
}
if (statopgen == HIGH) { // tasto1 premuto
 digitalWrite(LRGEN, LOW);
}



Invece di leggere gli ingressi mettendoli in una variabile, e leggere le altre uscite per sapere se si può procedere o se si è in condizione implicita di blocco, meglio usare una variabile esplicita 'blocco', la logica diventa più breve e leggibile:


if (digitalRead(PGEN) == HIGH  &&  blocco == 0) { // tasto1 premuto
 blocco = 1;
 digitalWrite(LRGEN, LOW);
}

Ho provato come mi hai consigliato con una variabile di blocco è molto più semplice, provato è funziona
fermo restando che modificherò dietro tuo consiglio le costanti in maiuscole ecc.
ripubblico lo sketch completo .

Grazie mille.

#define pgen  13 //pulsante 1
#define pqua  14 //pulsante 2
#define pinv  3  //pulsante 3
#define pres  4  //pulsante reset
#define lrgen 6  // led 1
#define lrqua 7  // led 2
#define lrinv 8  // led 3


void setup() {
  pinMode (lrgen, OUTPUT);
  pinMode (lrqua, OUTPUT);
  pinMode (lrinv, OUTPUT);
  pinMode (pgen, INPUT);
  pinMode (pqua, INPUT);
  pinMode (pinv, INPUT);
  pinMode (pres, INPUT);
  digitalWrite (lrgen, HIGH);
  digitalWrite (lrqua, HIGH);
  digitalWrite (lrinv, HIGH);
}


int blocco = 0;

void loop() {

  if (digitalRead(pgen) == HIGH  &&  blocco == 0) { // tasto1 premuto
    blocco = 1;
    digitalWrite(lrgen, LOW);
  }
  if (digitalRead(pqua) == HIGH  &&  blocco == 0) { // tasto1 premuto
    blocco = 1;
    digitalWrite(lrqua, LOW);
  }
  if (digitalRead(pinv) == HIGH  &&  blocco == 0) { // tasto1 premuto
    blocco = 1;
    digitalWrite(lrinv, LOW);
  }
  if (digitalRead(pres) == HIGH)// tasto reset premuto
  {
    digitalWrite (lrgen, HIGH);
    digitalWrite (lrqua, HIGH);
    digitalWrite (lrinv, HIGH);
    blocco = 0;
  }
}

Salvorhardin:
Indicatore di primo evento, quindi

Non difficile

Esatto può essere visto come i pulsanti di tre concorrenti che alla domanda solo chi è più veloce si aggiudica il diritto di risposta...

Io avrei fatto così:

byte x;

void setup()
{DDRD=0xFF;}

void loop()
{
     if(digitalRead(8))  x=0; // Reset
else if(digitalRead(9))  x=1; // A
else if(digitalRead(10)) x=2; // B
else if(digitalRead(11)) x=4; // C
PORTD=x;
}

Troppo semplice?... :slight_smile:

molto elegante, non portabile ma molto elegante

ti va di commentarlo?

Beh... è semplice:

byte x;

void setup()
{DDRD=0xFF;} // Imposto tutta la porta D in uscita (D0...D7)

void loop()
{
// Se premo uno dei 4 pulsanti, x assume i valori 0, 1, 2, 4, che in binario sono:
// 0b00000000
// 0b00000001
// 0b00000010
// 0b00000100
     if(digitalRead(8))  x=0; // Reset 
else if(digitalRead(9))  x=1; // A
else if(digitalRead(10)) x=2; // B
else if(digitalRead(11)) x=4; // C
PORTD=x; // Imposta la porta D secondo il valore di x, come mostrato dal suo valore in binario, tenendo conto che:
//  D7 D6 D5 D4 D3 D2 D1 D0
// 128 64 32 16  8  4  2  1 
}

Io ho voluto ridurlo al minimo, supponendo che il microcontrollore non dovrà usare per altri scopi D4...D7. Più correttamente, per poter usare anche quelle 4 uscite, deve essere:

byte x;

void setup()
{DDRD|=0x0F;} // Imposto in uscita i bit 0...3 della porta D, senza interferire con gli altri.

void loop()
{
     if(digitalRead(8))  x=0; // Reset
else if(digitalRead(9))  x=1; // A
else if(digitalRead(10)) x=2; // B
else if(digitalRead(11)) x=4; // C
PORTD&=x+240; // 240=0b11110000: imposta a 0 i bit di x che sono a 0, senza interferire con D7...D4, che vengono moltiplicati comunque per 1.
PORTD|=x; // Imposta a 1 i bit della porta D corrispondenti ai bit di x che sono a 1.
}

Datman:
Beh... è semplice:

byte x;

void setup()
{DDRD=0xFF;} // Imposto tutta la porta D in uscita (D0...D7)

void loop()
{
// Se premo uno dei 4 pulsanti, x assume i valori 0, 1, 2, 4, che in binario sono:
// 0b00000000
// 0b00000001
// 0b00000010
// 0b00000100
    if(digitalRead(8))  x=0; // Reset
else if(digitalRead(9))  x=1; // A
else if(digitalRead(10)) x=2; // B
else if(digitalRead(11)) x=4; // C
PORTD=x; // Imposta la porta D secondo il valore di x, come mostrato dal suo valore in binario, tenendo conto che:
//  D7 D6 D5 D4 D3 D2 D1 D0
// 128 64 32 16  8  4  2  1
}

Complimenti Datman.

Ottimo! molto tecnico mi piace ricorda molto il linguaggio assembler, ma io non ho questa competenza specifica e vorrei chiederti qualche chiarimento: quando dichiari" {DDRD=0xFF;} // Imposto tutta la porta D in uscita (D0...D7)" quindi sè voglio impostare solo 4 porte dovrò fare...{DDRD=0x03;} // Imposto tutta la porta D in uscita (D0...D3) poi dalla porta D4....D7 posso utilizzarle come voglio?

Poi non capisco questa impostazione perchè c'è il 240 cosa fà? "PORTD&=x+240;"

Nel messaggio #16 imposto solo i 4bit 0...3. Se scrivi 0x03, imposti solo D0 e D1, perché 3=1+2. Per impostare i bit 0...3 devi mettere 1+2+4+8=15=0x0F.

240 è 0xF0; perciò, moltiplicando (&) per 240+x, i 4 bit a sinistra (7...4) vengono moltiplicati per 1111, rimanendo inalterati: se un bit è 0, 0&1=0; se un bit è 1, 1&1=1.

Datman:
Nel messaggio #16 imposto solo i 4bit 0...3. Se scrivi 0x03, imposti solo D0 e D1, perché 3=1+2. Per impostare i bit 0...3 devi mettere 1+2+4+8=15=0x0F.

240 è 0xF0; perciò, moltiplicando (&) per 240+x, i 4 bit a sinistra (7...4) vengono moltiplicati per 1111, rimanendo inalterati: se un bit è 0, 0&1=0; se un bit è 1, 1&1=1.

Ok chiaro, sai ti ho posto questa domanda perchè in un'altro sketch dovevo leggere un ingresso dal buffer di trasmissione, in quel caso l'indirizzo era 0x000F riferito al pin 15, forse la differenza è che uno tratta i dati in binario e l'altro in esadecimale?