aggiungere pulsante

salve a tutti sto realizzando un progetto per accendere le luci da un keypad e dall'altra parte da un pulsante, ho fatto tutto lo sketch però non riesco ad inserire il pulsante.
praticamente il progetto funziona in questo modo:
se premo il tasto # accendo dei led temporizzati sulla tastiera per inserire il codice anche di notte, poi inserisco il mio codice di tre cifre e si accendono le luci temporizzate, in questa fase vorrei inserire un pulsante per accendere le luci da dentro casa perche questa tastiera si trova in mezzo la strada... Potete aiutarmi Grazie..

#include <Keypad.h>
#define luci 13
#define led 12
const byte ROWS = 4; //quattro righe
const byte COLS = 3; //tre colonne
char keyInsert[4];
// Queste variabili servono come verifica del corretto inserimento del codice
int i = 0;
int j = 0;
int s = 0;
int x = 0;
// Codice segreto
char code[4]= "000";
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {8,7,6,5}; //i Pin a cui sono connesse le righe del KeyPad
byte colPins[COLS] = {4,3,2}; // i Pin a cui sono connesse le colonne del KeyPad
 
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
 
void setup(){
  Serial.begin(9600);
  pinMode(luci,OUTPUT); // relè luci strada
  pinMode(led, OUTPUT); // led tastiera
  digitalWrite(luci,HIGH); imposto lo stato iniziale del relè


      }


void loop(){
  
   char key = keypad.getKey();
 if (i==0){
    Serial.println("inserisci il codice....");
    i++;
  }
  if (key != NO_KEY && j<3){
    Serial.print("*");
    //Serial.println(key);
    keyInsert[j]=key;
    j++;
  }
       //tasto da premere per accendere i led tastiera
       if(key == '#') {
      digitalWrite(led,HIGH);
     Serial.println("led acceso");
      delay(5000);
      digitalWrite(led,LOW);
     Serial.println("led spento");
        x=0;
        i=0;
        j=0;
      } 
      
   if(key == '*') {
      Serial.println();
      Serial.println("verifica del codice...");
      delay(1000);
      for(s=0; s<3;s++){
        if(keyInsert[s]==code[s]){
          x++;
      }
    } 
      
      if(x==3){
      Serial.println("Codice corretto"); 
      digitalWrite(luci,LOW);
      delay (5000); 
      digitalWrite (luci,HIGH);

        x=0;
        i=0;
        j=0;
      
      //TODO possibili ulteriori implementazioni
      }else{
         Serial.println("Codice non corretto, riprova");
         delay(2000);
         x=0;
         i=0;
         j=0;

   
     }
      
   }
    }

così alla veloce credo basti :

  • collegare il pulsante ad un ingresso della scheda;
  • all'inizio del loop azzerare una variabile creata ad hoc, poi verificare lo stato del pulsante e aggiornare la variabile relativa;
  • nella IF che verifica la condizione di accensione, aggiungere un OR con la variabile del pulsante, in modo tale che la luce si attivi anche nel caso di pressione;
  • alla fine del loop azzerare variabile .

(Scusa ma sto scrivendo dal cellulare e sono un po' impedito

Grazie per la tempestiva risposta credo di aver fatto una cosa del genere ma sicuramente ho sbagliato qualche passaggio appena hai tempo potresti indicarmi dal codice dove farlo?

gminga78:

#include <Keypad.h>

//tasto da premere per accendere i led tastiera
      if(key == '#') {
      digitalWrite(led,HIGH);
    Serial.println("led acceso");
      delay(5000);
      digitalWrite(led,LOW);
    Serial.println("led spento");
        x=0;
        i=0;
        j=0;
      }

Quando accendi il led rimane fermo per 5 sec senza poter acquisire un altro tasto; non rischi di digitare con la tastiera non illuminata ?

Buttato giù una bozza che però non ho provato :slight_smile:

  • Quando accende l'illuminazione del keybad il programma non si blocca con il 'Delay()'
  • il codice ha un tempo di validità all'interno del quale è possibile premere il pulsante dentro casa
  • Scaduto il tempo di validità del codice lo devi reinserire
#include <Keypad.h>
#define luci 13
#define led 12

const byte ROWS = 4; //quattro righe
const byte COLS = 3; //tre colonne
char keyInsert[4];
// Queste variabili servono come verifica del corretto inserimento del codice
int j = 0;
int s = 0;

// Codice segreto
char code[4]= "000";
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {8,7,6,5}; //i Pin a cui sono connesse le righe del KeyPad
byte colPins[COLS] = {4,3,2}; // i Pin a cui sono connesse le colonne del KeyPad



unsigned long previousMillis = 0;   
unsigned long currentMillis; //   Tiene conto del tempo trascorso dopo aver acceso i Leds del Keypad

unsigned long currentMillisLuci; // Tiene conto del tempo trascorso dopo aver acceso le luci
unsigned long previousMillisLuci = 0;   

unsigned long currentMillisCodice; // Svincolato dal tempo di accensione delle luci rende valido il codice per un certo tempo disponibile al pulsante di accensione manuale 
unsigned long previousMillisCodice = 0;   

int ledState = LOW;            
int luciState = LOW;            
int pulsante = 10;
const long interval = 1000;           // 1 secondo  di accensione per il led keypad
const long intervalLuci = 5000;       // 5 secondi  di accensione per le luci
const long intervalCodice = 30000;    // 30 secondi di validità per del codice inserito

bool timeLed;
bool ripeti;
bool codiceOk;
bool luciOk;

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
 
void setup()
{

  Serial.begin(9600);
  pinMode(luci,OUTPUT); // relè luci strada
  pinMode(led, OUTPUT); // led tastiera
  pinMode(pulsante, INPUT); // led tastiera
  
  digitalWrite(luci,HIGH); //imposto lo stato iniziale del relè

}

void loop()
{
 
  char key ;
  unsigned long currentMillis;

  j =0;
  ledState = LOW;
  ripeti = true;
  
                digitalWrite(led,ledState); 
 
  Serial.println("inserisci il codice....");
    while (key!=NO_KEY) key = keypad.getKey();   // Attende la pressione di un qualsiasi tasto senza fare altro
   
    while (ripeti)                               // inizia un nuovo ciclo perchè è stato premuto un tasto  ( non si sa ancora quale tasto)  
    {
      if(key == '#') { timeLed = true; ledState = HIGH; }  // Se prima di questo ciclo o durante , ho premuto '#' accendo il led per il tempo pari a 'intervallo'
      else
      if (j<3)    // Qualsiasi altro tasto lo considera un inserimento del codice purchè digitato massimo 3 volte
      {
        keyInsert[j++]=key;    
        Serial.print("*");
      }
      else      // Se ho superato il numero massimo di tre numeri digitati non memorizza più quale tasto digitato ( keyInsert[++j]=key; )
      {
        if (key == '*') // Se ho superato il numero massimo di tre numeri digitati ed ho premuto '*' verifica il codice
        {     
          Serial.println();
          Serial.println("verifica del codice...");
          delay(1000);
          for(s=0; s<3;s++)
          {          
            if(keyInsert[s]!=code[s]) ripeti = false;  // un solo errore interrompe 'while(ripeti)' e richiederà in seguito un altro codice
          }

          if (ripeti)             // ripeti = true perchè il codice inserito è corretto , si prepara per accendere le Luci 
          {      
            Serial.println("Codice corretto");
            luciState = HIGH;         // Aggiorna lo stato dell'uscita per le luci
            luciOk = true;          // Abilita un secondo timer per tenere accese le luci per un tempo pari a intervalloLuci 
            codiceOk = true;        // il codice che hai inserito è valido e lo sarà per un tempo pari a intervelloCodice
          }   
       }

        if (timeLed) currentMillis = millis();          // Aggiorna il tempo trascorso da quando abbiamo digitato '#' per l'accensione delle luci
        if (currentMillis - previousMillis >= interval) // Controlla se il tempo trascorso supera il tempo (intervallo) da noi impostato all'inizio prima di setup()
        {
          previousMillis = currentMillis;
          ledState = LOW;
          timeLed = false;
        }    

        if (luciOk) currentMillisLuci = millis();          // Inserito il codice corretto conta il tempo trascorso dopo aver acceso le Luci
        if (currentMillisLuci - previousMillisLuci >= intervalLuci) // Controlla se il tempo trascorso supera il tempo (intervallo2) da noi impostato all'inizio prima di setup()
        {
          previousMillisLuci = currentMillisLuci;
          ledState = LOW;
          timeLed = false;
          luciOk = false;
        }          

        if (codiceOk) currentMillisCodice = millis();          // Inserito il codice corretto conta il tempo trascorso dopo aver acceso le Luci
        if (currentMillisCodice - previousMillisCodice >= intervalCodice) // Controlla se il tempo trascorso supera il tempo (intervallo2) da noi impostato all'inizio prima di setup()
        {
          previousMillisCodice = currentMillisCodice;
          codiceOk = false;               // Scaduto il tempo di validità del codice
          ripeti = false ;                // richiedera al prossimo ciclo la ripetizione del codice. Da qui in poi il pulsante viene disabilitato.
        }          

      if (pulsante == HIGH && codiceOk) luciState = HIGH;  // se ho premuto il pulsante ed il codice è corretto aggiornato lo stato delle Luci
      
      digitalWrite(led,ledState);                   // aggiorna lo stato del Led
      digitalWrite(luci,luciState);                 // aggiorna lo stato delle Luci
      key = keypad.getKey();                        // prossimo tasto premuto

        
    }
  }  
}

ciao a tuttigrazie innanzitutto per le risposte e scusatemi se rispondo solo ora, praticamente ho cricato ilnuovo sketch ma non va, allora se premo il codicee premo * praticamente mi scrive verifica codice e non fa nulla invece se premoil # mi va in blocco e non mi fa fare nulla

Se ti riferisci al codice che ti ho inviato e perchè non l'ho provato ed ho solo un altro tipo di tastierino ( 13pin)
quindi non potrei inviarti il codice compatibile al 100%...

Quindi facendo un passo indietro perchè mi sa che ho complicato le cose , ho modificato quello originale

Si serve di un interrupt sul pulsante (PIN 2) che accende la luce solo quando il codice è corretto , ovvero quando
codiceOK = 1
e rimane accesa per un tempo indefinito.

Se crei un timeout per il codice e poni codiceOk = 0 , quando premerai nuovamente il pulsante non si accenderanno le luci, perchè devi reinserire il codice.
Siccome l'interrupt è sul pin2 devi scollegare da quel pin il tastierino e trovarne un altro libero ( io ho messo 9 ), come specificato nei commenti del programma

ciao

#include <Keypad.h>
#define luci 13
#define led 12

/*****************************************/
// Modifica 1
#define pulsanteINT 0                   // INTERRUPT sul DIGITAL PIN 2 
#define pulsante    2                   // DIGITAL PIN 2
int codiceOk = 0;                       // Abilita il pulsante
/*****************************************/


const byte ROWS = 4; //quattro righe
const byte COLS = 3; //tre colonne
char keyInsert[4];
// Queste variabili servono come verifica del corretto inserimento del codice
int i = 0;
int j = 0;
int s = 0;
int x = 0;
// Codice segreto
char code[4]= "000";
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {8,7,6,5}; //i Pin a cui sono connesse le righe del KeyPad
//*****************************
//Modifica 2 
byte colPins[COLS] = {4,3,9}; // i Pin a cui sono connesse le colonne del KeyPad <<---- scollega il tastierino dal pin2 e trova un pin libero ad esempio il 9
                                                                                        // perchè su questo pin ho configurato l'interrupt per il pulsante !
 
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

 
void setup(){
  Serial.begin(9600);
  pinMode(luci,OUTPUT); // relè luci strada
  pinMode(led, OUTPUT); // led tastiera
  //digitalWrite(luci,HIGH); // imposto lo stato iniziale del relè


//Modifica 3
pinMode(2, INPUT_PULLUP);                             // Attivo pull-up interno  per gestire il pulsante
attachInterrupt(pulsanteINT,leggiPulsante,CHANGE);    // Configuro l'interrupt per il pulsante , lo assegno al pin 2 (pulsanteINT) 
                                                      // e definisco la funzione leggiPulsante come ISR
}


void loop(){
 
char key = keypad.getKey();
 if (i==0){ Serial.println("inserisci il codice....");  i++;  }
 if (key != NO_KEY && j<3)
 {
    Serial.print("*");
    //Serial.println(key);
    keyInsert[j]=key;
    j++;
 }
   //tasto da premere per accendere i led tastiera
 if(key == '#')
 {
     digitalWrite(led,HIGH);
     Serial.println("led acceso");
     delay(5000);
     digitalWrite(led,LOW);
     Serial.println("led spento");
     x=0;
     i=0;
     j=0;
 }
     
 if(key == '*')
 {
      Serial.println();
      Serial.println("verifica del codice...");
      delay(1000);
      for(s=0; s<3;s++)
      {
        if(keyInsert[s]==code[s]) x++;
      }
     
      if(x==3)
      {
        Serial.println("Codice corretto");
        digitalWrite(luci,LOW);
        delay (5000);
        digitalWrite (luci,HIGH);
        // Modifica 5
        codiceOk = 1; //abilito il pulsante perchè il codice è corretto.
        x=0;
        i=0;
        j=0;
      }
      else
      {
       Serial.println("Codice non corretto, riprova");
       delay(2000);
       x=0;
       i=0;
       j=0;
       codiceOk = 0;  
      }
     
 }
 
}

//Modifica 4 Aggiunto l'isr
/*********************************/
// Interrupt Service Routine
/********************************/
void leggiPulsante() 
{
 
  if(digitalRead(pulsante) == LOW && codiceOk)   // se hai premuto il pulsante ed il codice è stato inserito correttamente...
  {

        digitalWrite (luci,HIGH);   // ...Accendo le luci  ( in questo caso il led , come conferma)
             
  
  }
}

Diciamo che in gran parte. Ho risolto anche. Con i vostri consigli adesso però. Il problema è un altro, dovrei aggiungere un oulsante per accendere le luci da dentro casa, io ho scritto tutto e funziona ma al contrario, praticamente se il pin 11 lo tengo a massa allora non succede nulla ma se lo stacco mi attiva le luci, invece dovrebbe essere il contrario cioè contatto normalmente aperto le luci sono spente e auando lo chiudo si dovrebbero accendere

dovresti ripostare il codice aggiornato ed il collegamento verso le luci

Ok appena rientro lo faccio grazie

adesso funziona tutto ma devo solo inserire un pulsante su un pin che mi accende le luci perché ho provato il classico modo ma non va

#include <Keypad.h>
#define luci 13
#define led 12


const byte ROWS = 4; //quattro righe
const byte COLS = 3; //tre colonne
char keyInsert[4];
// Queste variabili servono come verifica del corretto inserimento del codice
int i = 0;
int j = 0;
int s = 0;
int x = 0;
// Codice segreto
char code[2]= "6";
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {8,7,6,5}; //i Pin a cui sono connesse le righe del KeyPad
byte colPins[COLS] = {4,3,2}; // i Pin a cui sono connesse le colonne del KeyPad
 
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
 
void setup(){
  Serial.begin(9600);
  pinMode(luci,OUTPUT); // relè luci strada
  pinMode(led, OUTPUT); // led tastiera
digitalWrite(luci,HIGH);

}

void loop(){

char key = keypad.getKey();
 
 {
 if (i==0){
    Serial.println("inserisci il codice....");
    i++;
  }
  if (key != NO_KEY && j<1){
    Serial.print("*");
    //Serial.println(key);
    keyInsert[j]=key;
    j++;
  }
       //tasto da premere per accendere i led tastiera
       if(key == '#'){
       
      digitalWrite(led,HIGH);
     Serial.println("led acceso");
       x=0;
        i=0;
        j=0;
      
      while(0);
       }
      
   if(key == '*') {
      Serial.println();
      Serial.println("verifica del codice...");
      delay(1000);
      for(s=0; s<1;s++){
        if(keyInsert[s]==code[s]){
          x++;
      }
    } 
  
      if(x== 1){
      Serial.println("Codice corretto"); 
      digitalWrite (led,LOW);
      digitalWrite(luci,LOW);
      delay (5000); 
      digitalWrite (luci,HIGH);
      digitalWrite (led,LOW);
        x=0;
        i=0;
        j=0;
      
      //TODO possibili ulteriori implementazioni
      }else{
         Serial.println("Codice non corretto, riprova");
         delay(2000);
         x=0;
         i=0;
         j=0;
      }
   }
   }   
   }

Conunque la digital write nell ISR é una cosa un po' fastidiosa per il micro, sarebbe meglio inserire una Flag, però certo si accenderebbe non immediatamente come adesso