antifurto 433mhz + display e tastiera

salve, ho realizzato un piccolo sistema di allarme formato da un display una tastiera 4*4 e per ora un solo sensore pir 433mhz che comunica con arduino con una ricevente 433mhz.
questo è il codice che ho scritto:

#include <LiquidCrystal.h>
#include <Password.h>
#include <RCSwitch.h>
#include <Keypad.h>

#define codice_pir 1497466  // codice sensore pir 433mhz

RCSwitch mySwitch = RCSwitch();
LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);
Password password = Password("123A");

byte LunghezzaMaxPassword = 4;
byte LunghezzaPasswordCorrente = 0;
const byte ROWS = 4; // Quattro righe
const byte COLS = 4; // Quattro colonne
int AllarmeAttivo=0;
// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {
  6, 5, 4, 3 }; // Connessione delle righe: Riga0, Riga1, Riga2 e Riga3 ai pins di Arduino.
byte colPins[COLS] = {
  10, 9, 8, 7 }; // Connessione delle colonne: Colonna0, Colonna1 , Colonna2 e Colonna3 ai pins di Arduino. 
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Creazione della tastiera



void setup()
{
 pinMode(11,OUTPUT);
 pinMode(12, INPUT);
 Serial.begin(9600);
 lcd.begin(16, 2);
 //lcd.print("DIGITA PASSWORD: ");
 mySwitch.enableReceive(0);  //riceve sul pin 2 modulo 433mhz 
}

void loop ()
{
  Controllo_Password ();
  controllo();
}

int Controllo_Password ()
{
  char key = kpd.getKey();
  if (key != NO_KEY) {
      delay(60);
      Serial.print(key);
      lcd.print("*");
      LunghezzaPasswordCorrente++;
      password.append(key);
      if (LunghezzaPasswordCorrente == LunghezzaMaxPassword) {
        if (password.evaluate()) {
          Serial.println(" PASSWORD ESATTA");
          lcd.clear();
          lcd.print("PASSWORD ESATTA");
          delay(2000);
          lcd.clear();
          AllarmeAttivo=1;
        } 
        else {
          Serial.println(" PASSWORD ERRATA");
          lcd.clear();
          lcd.print("PASSWORD ERRATA");
          delay(2000);
          lcd.clear();
          AllarmeAttivo=0;
        }
        password.reset();
        LunghezzaPasswordCorrente = 0;
       }
  }
}

void controllo() 
{  
  if (AllarmeAttivo== 1) {
    if (mySwitch.available()) {
        unsigned long lettura = mySwitch.getReceivedValue();     
        if (lettura == codice_pir) {
            Serial.print(" ");
            Serial.print(lettura);
            Serial.println();
            allarme ();       
          }
      }
     mySwitch.resetAvailable();    
  }
   
}

void allarme ()
{
  tone(11,10);
  delay(150);
  noTone(11);
  delay(150);
}

lo scopo è quello di attivare l'allarme quando viene inserita la password giusta, poi se il sensore rileva movimento invia un codice e la sirena dovrebbe suonare fino a quando non viene reinserita la password esatta. Siccome che il sensore invia un solo codice quando rileva il movimento la sirena suona una sola volta e non fino a quando viene reinserita la password corretta. Sapreste dirmi come posso correggere??
grazie in anticipo.
PS. se ho sbagliato qualche altra cosa ditemelo pure, cercherò di capire e correggere l'errore.

--- ti ricordo che da regolemanto è permesso fare "up" solo dopo almeno 48 ore dall'ultimo post. grazie. - gpb01

cosmo96:
... attivare l'allarme quando viene inserita la password giusta, poi se il sensore rileva movimento invia un codice e la sirena dovrebbe suonare fino a quando non viene reinserita la password esatta. Siccome che il sensore invia un solo codice quando rileva il movimento la sirena suona una sola volta e non fino a quando viene reinserita la password corretta. ...

Utilizza una "flag" ... quando il sensore scatta la mette "vera", se si digita il codice giusto la metti "falsa" e, se il sistema è inserito e la flag è vera ... devi suonare la sirena finché non la ritrovi falsa.

Guglielmo

gpb01:
Utilizza una "flag" ... quando il sensore scatta la mette "vera", se si digita il codice giusto la metti "falsa" e, se il sistema è inserito e la flag è vera ... devi suonare la sirena finché non la ritrovi falsa.

Guglielmo

ho provato in questo modo:

#include <LiquidCrystal.h>
#include <Password.h>
#include <RCSwitch.h>
#include <Keypad.h>

#define codice_pir 1497466  // codice sensore pir 433mhz

RCSwitch mySwitch = RCSwitch();
LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);
Password password = Password("123A");

byte LunghezzaMaxPassword = 4;
byte LunghezzaPasswordCorrente = 0;
const byte ROWS = 4; // Quattro righe
const byte COLS = 4; // Quattro colonne
int AllarmeAttivo = 0;
bool flag = false;
bool flag2 = false;
// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {
  6, 5, 4, 3
}; // Connessione delle righe: Riga0, Riga1, Riga2 e Riga3 ai pins di Arduino.
byte colPins[COLS] = {
  10, 9, 8, 7
}; // Connessione delle colonne: Colonna0, Colonna1 , Colonna2 e Colonna3 ai pins di Arduino.
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Creazione della tastiera



void setup()
{
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  //lcd.print("DIGITA PASSWORD: ");
  mySwitch.enableReceive(0);  //riceve sul pin 2 modulo 433mhz
}

void loop ()
{
  Controllo_Password ();
  if (password.evaluate())
    if (mySwitch.available()) {
      unsigned long lettura = mySwitch.getReceivedValue();
      if (lettura == codice_pir)
        flag = true;
      
      while ((Controllo_Password ()!=true) && (flag == true)) {
        Serial.print(flag);
        Serial.print(" ");
        Serial.print(Controllo_Password ());
        Serial.println();
        //Serial.print(lettura);
        //Serial.println();
        allarme ();
      }
    }
  mySwitch.resetAvailable();

}

bool Controllo_Password ()
{
  char key = kpd.getKey();
  if (key != NO_KEY) {
    delay(60);
    Serial.print(key);
    lcd.print("*");
    LunghezzaPasswordCorrente++;
    password.append(key);
    if (LunghezzaPasswordCorrente == LunghezzaMaxPassword) {
      if (password.evaluate()) {
        Serial.println(" PASSWORD ESATTA");
        lcd.clear();
        lcd.print("PASSWORD ESATTA");
        delay(2000);
        lcd.clear();
        //AllarmeAttivo=1;
        return flag2 = true;
      }
      else {
        Serial.println(" PASSWORD ERRATA");
        lcd.clear();
        lcd.print("PASSWORD ERRATA");
        delay(2000);
        lcd.clear();
        //AllarmeAttivo=0;
        return flag2 = false;
      }
      password.reset();
      LunghezzaPasswordCorrente = 0;
    }
  }
}

void controllo()
{


}

void allarme ()
{
  tone(11, 10);
  delay(150);
  noTone(11);
  delay(150);
}

ma una volta che scatta l'allarme può essere disattivato alla pressione di un qualsiasi codice, come posso risolvere?

Ciao,
se fai il return all'interno dell'if quando viene eseguito il codice dopo l'if? (in Controllo_Password () -> if (password.evaluate()) {... )

questo mi lascia un po' perplesso...
return flag2 = true;
return flag2 = false;
non sono sicuro che faccia quello che vuoi... prova solo con return true; e return false;

poi volendo essere pignoli, con i valori booleani non serve mettere == o !=
il while si può abbreviare così

while (!Controllo_Password() && flag)

dinodf:
Ciao,
se fai il return all'interno dell'if quando viene eseguito il codice dopo l'if? (in Controllo_Password () -> if (password.evaluate()) {... )

quindi cosa devo cambiare per risolvere?

Ciao,
non so se il problema sia solo quello del return all'interno dell'if/else, quello mi è saltato all'occhio, per evitare che la password e la lunghezza non vengano mai resettati basta che all'interno dell'if e dell'else lasci il "flag2 = true/false" e metti "return flag2" dopo "LunghezzaPasswordCorrente = 0;"

NON so se funzionerà, non mi sono studiato tutto il codice.

Dino

dinodf:
Ciao,
non so se il problema sia solo quello del return all'interno dell'if/else, quello mi è saltato all'occhio, per evitare che la password e la lunghezza non vengano mai resettati basta che all'interno dell'if e dell'else lasci il "flag2 = true/false" e metti "return flag2" dopo "LunghezzaPasswordCorrente = 0;"

NON so se funzionerà, non mi sono studiato tutto il codice.

Dino

ho provato a fare cosi, ma nulla da fare sembra che il programma rimane bloccato sulla funzione Controllo_Password()

Ciao,
in effetti credo ci sia un grosso problema in quella funzione (Controllo_Password() intendo) perché all'interno resetti la password e subito dopo (nel loop()) chiami password.evaluate()? il valore non sarà mai vero dato che hai appena resettato la password!
Sistema quel punto e dovrebbe migliorare (utilizza il valore restituito dalla funzione Controllo_Password()).

Dino

dinodf:
Ciao,
in effetti credo ci sia un grosso problema in quella funzione (Controllo_Password() intendo) perché all'interno resetti la password e subito dopo (nel loop())

allora anch'io avevo pensato che il problema stesse in "password.reset();" ma in realtà non è cosi perchè se cosi fosse l'if all'interno del loop "if(password.evaluate())" risulterebbe sempre falsa e il programma non passerebbe mai a leggere lo stato del sensore. Invece noi qua stiamo parlando che il programma si blocca nel momento che voglio disattivare l'allarme (ovvero si disattiva digitando qualsiasi tasto pure se sbagliato), comunque nonostante ciò ho provato a cambiare quel "password.reset()" come hai detto tu.
Non ti viene nessun'altra soluzione in mente? Magari potresti farmi il piacere di eseguire personalmente il codice, simulando l'invio dei segnali dal sensore pir, visto che solo tu hai pensato di aiutarmi?
grazie in anticipo

Ciao,
ho simulato così:

#include <Password.h>

#define PININ  7

Password password = Password("123A");

byte LunghezzaMaxPassword = 4;
byte LunghezzaPasswordCorrente = 0;

void setup()
{
  Serial.begin(500000);
  pinMode(11, OUTPUT);
  pinMode(PININ, INPUT);      // pin con il quale simulo la ricezione dell'allarme 
  digitalWrite(PININ, HIGH) ; // pull-up attivo 
}

void loop() {
  bool flag = false;
  /*
   * Simulo il codice nell'if sottostante con la lettura di un pin
   */
//  if (mySwitch.available()) {
//      unsigned long lettura = mySwitch.getReceivedValue();
//      if (lettura == codice_pir)
//        flag = true; 
//  }
    flag = digitalRead(PININ);            // se il pin non è cortocircuitato a GND ho ricevuto il segnale di allarme (pin libero) 

    while (flag) {
        allarme();
        if (Serial.available()) {         // necessario altrimenti simulando via seriale la lettura blocca l'allarme (suona una sola volta)
          flag = (!Controllo_Password()); // esco dal while se ho inserito correttamente la password 
        }
    }
}

bool Controllo_Password ()
{
  bool flag2;
  char key; 
  
  while(true) {               // questo while è bloccante! Finchè non si inserisce tutta la password l'allarme si blocca (non suona più)
    if (Serial.available()) { // simulo la pressione dei tasti sul tastierino con la lettura via seriale 
      key = Serial.read();
      Serial.print(key);
      LunghezzaPasswordCorrente++;
      password.append(key);
      if (LunghezzaPasswordCorrente == LunghezzaMaxPassword) {
        if (password.evaluate()) {
          Serial.println(" PASSWORD ESATTA");
          flag2 = true;
        } else {
          Serial.println(" PASSWORD ERRATA");
          flag2 = false;
        }
        password.reset();
        LunghezzaPasswordCorrente = 0;
        return flag2;
      }
    }
  }
}

void allarme ()
{
  tone(11, 10);
  delay(150);
  noTone(11);
  delay(150);
  Serial.print("E' scattato l'allarme!!!\n");
}

e mi pare funzioni.
Non è il massimo come codice, poco ordinato e un po' macchinoso ma come base di partenza dovrebbe andare, ora scriviti la funzione per leggere il codice inviato via wireless e sostituiscilo alla lettura del pin (naturalmente bisogna fare molta attenzione alle situazioni bloccanti, ad esempio se scatta l'allarme (ricevi il segnale via wireless) ed una volta inserita la password corretta l'allarme persiste (continui a ricevere il segnale dal sensore wireless) la condizione si verifica nuovamente e il cicalino continua a suonare, come se non collegassi mai il pin a GND con il mio codice.
Altra cosa da controllare è che dopo un tot di secondi la password venga resettata, ad esempio se inserisci 5 caratteri nel mio esempio il 5° rimane salvato e non è corretto.

Altre cose ci saranno ma non mi vengono in mente al momento.

Ciao
D

dinodf:

ho provato il tuo codice ma nemmeno riesco a farlo funzionare, ho fatto anche delle modifiche al mio e niente, c'è qualcun'altro disposto ad aiutarmi?

#include <LiquidCrystal.h>
#include <Password.h>
#include <RCSwitch.h>
#include <Keypad.h>

#define codice_pir 1497466  // codice sensore pir 433mhz

RCSwitch mySwitch = RCSwitch();
LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);
Password password = Password("123A");

byte LunghezzaMaxPassword = 4;
byte LunghezzaPasswordCorrente = 0;
const byte ROWS = 4; // Quattro righe
const byte COLS = 4; // Quattro colonne
int AllarmeAttivo = 0;
bool flag = false;
bool flag2 = false;
// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {
  6, 5, 4, 3
}; // Connessione delle righe: Riga0, Riga1, Riga2 e Riga3 ai pins di Arduino.
byte colPins[COLS] = {
  10, 9, 8, 7
}; // Connessione delle colonne: Colonna0, Colonna1 , Colonna2 e Colonna3 ai pins di Arduino.
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Creazione della tastiera



void setup()
{
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  //lcd.print("DIGITA PASSWORD: ");
  mySwitch.enableReceive(0);  //riceve sul pin 2 modulo 433mhz
}

void loop ()
{
  //Controllo_Password ();
  //if (password.evaluate())
  if (Controllo_Password ()==1) //se uguale a 1 allora l'antifurto è attivo
    if (Lett_Sensore ()==1)
    //Serial.println("lettura sensore: ");
    //Serial.println(Lett_Sensore());//vede se il segnale ricevuto è uguale a quello memorizzato
      while (Controllo_Password ()==1) {
        Controllo_Password ();
        allarme ();
      }
    
  
   
      
     /* while ((Controllo_Password ()!=true) && (flag == true)) {
        Serial.print(flag);
        Serial.print(" ");
        Serial.print(Controllo_Password ());
        Serial.println();
        //Serial.print(lettura);
        //Serial.println();
        allarme ();
      }
    }
  mySwitch.resetAvailable();
*/
}

int Controllo_Password ()
{
  char key = kpd.getKey();
  if (key != NO_KEY) {
    delay(60);
    Serial.print(key);
    lcd.print("*");
    LunghezzaPasswordCorrente++;
    password.append(key);
    if (LunghezzaPasswordCorrente == LunghezzaMaxPassword) {
      if (password.evaluate()) {
        Serial.println(" PASSWORD ESATTA");
        lcd.clear();
        lcd.print("PASSWORD ESATTA");
        delay(2000);
        lcd.clear();
        //AllarmeAttivo=1;
        return flag2 = 1;
      }
      else {
        Serial.println(" PASSWORD ERRATA");
        lcd.clear();
        lcd.print("PASSWORD ERRATA");
        delay(2000);
        lcd.clear();
        //AllarmeAttivo=0;
        return flag2 = 0;
      }
      password.reset();
      LunghezzaPasswordCorrente = 0;
    }
  }
}

int Lett_Sensore ()  
{
  int stato= 0;
  unsigned long lettura;
  if (mySwitch.available()) {
      lettura = mySwitch.getReceivedValue();
      if (lettura == codice_pir)
        return stato= 1;
  }
  mySwitch.resetAvailable();
}

void allarme ()
{
  tone(11, 10);
  delay(150);
  noTone(11);
  delay(150);
}

cosmo96:
ho provato il tuo codice ma nemmeno riesco a farlo funzionare

L'ho provato (il codice che ho postato) su una 2009 e funziona perfettamente quindi il problema che riscontri sta da un' altra parte, forse sbagli qualcosa nella programmazione.

Ragazzi per favore aiutatemi, ancora non sono riuscito a risolvere il mio problema (cioè quello di riuscire a disattivare correttamente il sistema), ho riscritto da capo tutto il codice in maniera più ordinata e facendo vari cambiamenti. E' da più di un mese che sto impazzendo e chiedo il vostro aiuto, sarebbe un peccato per me rinunciare a un progetto a cui tengo molto.
questo è il nuovo codice:

#include <LiquidCrystal.h>
#include <Password.h>
#include <RCSwitch.h>
#include <Keypad.h>

#define codice_pir 1497466  // codice sensore pir 433mhz

RCSwitch mySwitch = RCSwitch();
LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);
Password password = Password("1234");

byte LunghezzaMaxPassword = 4;
byte LunghezzaPasswordCorrente = 0;
const byte ROWS = 4; // Quattro righe
const byte COLS = 4; // Quattro colonne
int statoAllarme = 0; //con = 0 l'allarme è disattivato, con = 1 l'allarme è attivo
bool flag = false;
bool flag2 = false;
// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {
  6, 5, 4, 3
}; // Connessione delle righe: Riga0, Riga1, Riga2 e Riga3 ai pins di Arduino.
byte colPins[COLS] = {
  10, 9, 8, 7
}; // Connessione delle colonne: Colonna0, Colonna1 , Colonna2 e Colonna3 ai pins di Arduino.
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Creazione della tastiera



void setup()
{
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  //lcd.print("DIGITA PASSWORD: ");
  mySwitch.enableReceive(0);  //riceve sul pin 2 modulo 433mhz
}

void loop ()
{
  gestioneTastiera ();
  if ((gestioneTastiera ()==true) && (statoAllarme==0))
    statoAllarme=1;
  else statoAllarme=0;
  
  if ((statoAllarme==1) && (letturaPIR()==true)) {
    while (password.evaluate()) {
      allarme ();
      gestioneTastiera ();   
    }
  }
     
}

bool letturaPIR () {
  flag = false;
  if (mySwitch.available()) {
      unsigned long lettura = mySwitch.getReceivedValue();
      if (lettura == codice_pir)
        flag = true;
  }
  return flag;
  mySwitch.resetAvailable();
}

bool gestioneTastiera ()
{
    char key = kpd.getKey();
    if (key != NO_KEY) {
      delay(60);
      Serial.print(key);
      LunghezzaPasswordCorrente++;
      password.append(key);
    }
  
    if (LunghezzaPasswordCorrente == LunghezzaMaxPassword) {
      if (password.evaluate()) {
        Serial.println(" PASSWORD ESATTA");
        flag2= true;
        //delay(2000);
      }
      else {
        Serial.println(" PASSWORD ERRATA");
        flag2= false;
        //delay(2000);
      }
      return flag2;
      password.reset();
      LunghezzaPasswordCorrente = 0;
    }
}

void allarme ()
{
  Serial.println(" ALLARMEE!!!");
  tone(11, 10);
  delay(150);
  noTone(11);
  delay(150);
}

Da un primo controllo veloce, mi suonano strane un paio di cose:

  • all'inizio chiami 2 volte gestioneTastiera()... Sicuro sia corretto? Per il controllo nell'if forse conviene salvare il risultato della prima chiamata in una variabile e usare quella per il confronto nell'if.
  • in un paio di funzioni ci sono delle righe di codice dopo il return... Non sono sicuro che vengano eseguite

fratt:
Da un primo controllo veloce, mi suonano strane un paio di cose:

  • all'inizio chiami 2 volte gestioneTastiera()... Sicuro sia corretto? Per il controllo nell'if forse conviene salvare il risultato della prima chiamata in una variabile e usare quella per il confronto nell'if.
  • in un paio di funzioni ci sono delle righe di codice dopo il return... Non sono sicuro che vengano eseguite

Ciao, innanzitutto grazie per aver risposto, ho seguito i tuoi consigli ed effettivamente qualche errorino c'era, ho fatto anche altre modifiche ma ancora non funziona. Di seguito ti metto il nuovo codice cosi nel caso volessi continuare ad aiutarmi, come ho già detto per me sarebbe un peccato rinunciare a questo piccolo progettino.

#include <LiquidCrystal.h>
#include <Password.h>
#include <RCSwitch.h>
#include <Keypad.h>

#define codice_pir 1497466  // codice sensore pir 433mhz

RCSwitch mySwitch = RCSwitch();
LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);
Password password = Password("1234");

byte LunghezzaMaxPassword = 4;
byte LunghezzaPasswordCorrente = 0;
const byte ROWS = 4; // Quattro righe
const byte COLS = 4; // Quattro colonne
int statoAllarme = 0; //con = 0 l'allarme è disattivato, con = 1 l'allarme è attivo
bool flag = false;
bool flag2 = false;

// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {
  6, 5, 4, 3
}; // Connessione delle righe: Riga0, Riga1, Riga2 e Riga3 ai pins di Arduino.
byte colPins[COLS] = {
  10, 9, 8, 7
}; // Connessione delle colonne: Colonna0, Colonna1 , Colonna2 e Colonna3 ai pins di Arduino.
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); // Creazione della tastiera

void setup()
{
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  //lcd.print("DIGITA PASSWORD: ");
  mySwitch.enableReceive(0);  //riceve sul pin 2 modulo 433mhz
}

void loop ()
{
  gestioneTastiera ();
  if ((flag2==true) && (statoAllarme==0)) {
    //letturaPIR ();
    statoAllarme=1;
  } 
  else statoAllarme=0;
  
  if (statoAllarme==1) {
    letturaPIR ();
    if (flag==true) {
      do{
        allarme ();
        gestioneTastiera ();   
      }
      while (password.evaluate()); 
    }   
  }
}

void letturaPIR () {
  Serial.println("IL CONTROLLO PASSWORD E' ANDATO A BUON FINE");
  flag = false;
  if (mySwitch.available()) {
      unsigned long lettura = mySwitch.getReceivedValue();
      if (lettura == codice_pir) {
        Serial.println(lettura);
        flag = true;
      }
  }
  mySwitch.resetAvailable();
  //return flag;
}

void gestioneTastiera ()
{
  while (LunghezzaPasswordCorrente != LunghezzaMaxPassword) {
    char key = kpd.getKey();
    if (key != NO_KEY) {
      delay(60);
      Serial.print(key);
      LunghezzaPasswordCorrente++;
      password.append(key);
    }
    if (LunghezzaPasswordCorrente == LunghezzaMaxPassword)
      if (password.evaluate()) {
        Serial.println(" PASSWORD ESATTA");
        flag2= true;
      }
      else {
        Serial.println(" PASSWORD ERRATA");
        flag2= false;
      }
  }
  password.reset();
  LunghezzaPasswordCorrente = 0;
}

void allarme ()
{
  Serial.println(" ALLARMEE!!!");
  tone(11, 10);
  delay(150);
  noTone(11);
  delay(150);
}

Ciao,
secondo me, come già spiegato in precedenza, il fatto che il tuo codice non faccia ciò che vorresti è dato dal fatto che hai delle funzioni che bloccano l'esecuzione ed in più resetti alcune variabili secondo me in modo, ad esempio ragioniamo sulla funzione loop():

void loop ()
{
  gestioneTastiera ();
  if ((flag2==true) && (statoAllarme==0)) {
    //letturaPIR ();
    statoAllarme=1;
  } 
  else statoAllarme=0;
  
  if (statoAllarme==1) {
    letturaPIR ();
    if (flag==true) {
      do{
        allarme ();
        gestioneTastiera ();   
      }
      while (password.evaluate()); 
    }   
  }
}

come prima cosa chiami gestioneTastiera() quindi l'esecuzione del codice nella funzione loop() si blocca nell'attesa che tu digiti qualcosa sul tastierino, la funzione gestioneTastiera a sua volta chiama un loop (while (LunghezzaPasswordCorrente != LunghezzaMaxPassword))
quindi finché non digiti tutti i caratteri che compongono la password il programma non va avanti.

Faccio una parentesi spiegandoti un altro errore che hai commesso all'interno della funzione che copio:

void gestioneTastiera ()
{
  while (LunghezzaPasswordCorrente != LunghezzaMaxPassword) {
    char key = kpd.getKey();
    if (key != NO_KEY) {
      delay(60);
      Serial.print(key);
      LunghezzaPasswordCorrente++;
      password.append(key);
    }
    if (LunghezzaPasswordCorrente == LunghezzaMaxPassword)
      if (password.evaluate()) {
        Serial.println(" PASSWORD ESATTA");
        flag2= true;
      }
      else {
        Serial.println(" PASSWORD ERRATA");
        flag2= false;
      }
  }
  password.reset();
  LunghezzaPasswordCorrente = 0;
}

all'interno del while() hai un if() che rifà lo stesso controllo del while quindi potresti semplicemente eliminare quell'if() ed eseguire il settaggio di flag2 direttamente all'uscita del while() perché appena uscito sicuramente la condizione sarà vera.
Quindi il codice migliorato sarà:

void gestioneTastiera ()
{
  while (LunghezzaPasswordCorrente != LunghezzaMaxPassword) {
    char key = kpd.getKey();
    if (key != NO_KEY) {
      delay(60);
      Serial.print(key);
      LunghezzaPasswordCorrente++;
      password.append(key);
    }
  }
  flag2 = password.evaluate();
  if (flag2)
    Serial.println(" PASSWORD ESATTA");
  else 
    Serial.println(" PASSWORD ERRATA");
  LunghezzaPasswordCorrente = 0;
  password.reset();
}

fine parentesi.
Ammettiamo che tu inserisca la password corretta, a questo punto l'esecuzione del codice nella funzione loop() riprende, andiamo a vedere cosa farà:
praticamente verrà eseguito l'if()

if ((flag2==true) && (statoAllarme==0)) {
    //letturaPIR ();
    statoAllarme=1;
  } 
  else statoAllarme=0;

che non fa altro che copiare il valore di flag2 in statoAllarme quindi possiamo tranquillamente eliminare quell'if ed utilizzare direttamente flag2 per i controllo successivi.
Avevamo supposto che la password inserita fosse corretta quindi a questo punto del codice abbiamo statoAllarme = 1 ed 'eseguiremo il codice nell'if() successivo, ammettiamo anche questa volta che il codice letto da mySwitch.getReceivedValue() sia identico a codice_pir (non so né cosa né quando i tuoi sensori inviino il codice quindi prendo per buono il tuo codice, anche se credo non sia corretto) a questo punto viene settato flag a true e resettato mySwitch, la funzione letturaPIR () finisce e l'esecuzione torna al codice in loop(), flag è uguale a true quindi inizia l'esecuzione del codice lel loop do-while:

 do{
        allarme ();
        gestioneTastiera ();   
      }
      while (password.evaluate());

viene eseguita la funzione allarme() e successivamente richiamata la funzione gestioneTastiera(), che come detto prima ha al suo interno un loop che blocca l'esecuzione in attesa che tu digiti la password.
Credo che a questo punto hai capito che non è la strada corretta, che senso ha che tu debba continuamente digitare la password per far avanzare il programma?
Tralascio la spiegazione del codice in caso di inserimento di password errata o mancato ricevimento del segnale wireless tanto abbiamo capito che non funzionerà mai.

La funzione loop() si chiama così proprio perché viene eseguita all'infinito, una volta terminata viene immediatamente richiamata ed il codice al suo interno eseguito nuovamente, quindi se non strettamente necessario elimina tutti i loop che hai infilato nelle varie funzioni chiamate da loop() che altrimenti bloccano l'esecuzione del codice in attesa che qualcosa si verifichi.

Iniziamo a studiare bene cosa deve fare il sistema:

  • per prima cosa devi devi controllare se l'allarme è inserito
  • se è inserito l'allarme controlla se il sensore ti segnala che è "scattato l'allarme" suonando la sirena, NON sapendo nulla non posso garantirti che sia corretto quello che hai ipotizzato; sicuro che il sensore pir invii il codice solo quando scatta l'allarme?
  • se è scattato l'allarme fai suonare la sirena
  • se inserisci la password corretta e l'allarme sta suonando disattiva la sirena
  • se inserisci la password corretta e l'allarme non sta suonando disinserisci l'allarme

Credo sia tutto chiaro.
Il codice potrebbe essere:

#include <Password.h>
#include <RCSwitch.h>
#include <Keypad.h>

#define CODICE_PIR 1497466 // codice sensore pir 433mhz
#define LUNGHEZZA_PASSWD 4
#define PASSWORD "1234"
#define ROWS  4
#define COLS  4

RCSwitch mySwitch = RCSwitch();
Password password = Password(PASSWORD);

byte lunghezzaPasswordCorrente = 0;
bool allarmeArmato = false;
bool allarmeScattato = false;

// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {
  6, 5, 4, 3
}; // Connessione delle righe: Riga0, Riga1, Riga2 e Riga3 ai pins di Arduino.

byte colPins[COLS] = {
  10, 9, 8, 7
}; // Connessione delle colonne: Colonna0, Colonna1 , Colonna2 e Colonna3 ai pins di Arduino.

Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // Creazione della tastiera

void setup()
{
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  Serial.begin(9600);
  mySwitch.enableReceive(0);  //riceve sul pin 2 modulo 433mhz
}

void loop()
{
  // controllo se l'allarme è armato 
  if (allarmeArmato) {
    // controllo se ricevo il segnale di allarme 
    if (letturaPIR()) {
      allarmeScattato = true;
    }
    // se è scattato l'allarme faccio suonare la "sirena"
    if (allarmeScattato) {
      allarme(); // faccio suonare la "sirena"
    }
  }

  // controllo se viene inserita la password corretta 
  if (gestioneTastiera()) {
    // se l'allarme non è armato lo armo 
    if (!allarmeArmato) {
      allarmeArmato = true;
    } else {
      // se è armato ed è scattato l'allarme lo spengo
      if (allarmeScattato)
        allarmeScattato = false;
      // se non è scattato l'allarme disarmo l'allarme
      else 
        allarmeArmato = false;
    }
  }
}

bool letturaPIR() {
  if (mySwitch.available() && mySwitch.getReceivedValue() == CODICE_PIR) {
    mySwitch.resetAvailable();
    return true;
  } else {
    return false;
  }
}

bool gestioneTastiera() {
  char key = kpd.getKey();
  if (key != NO_KEY) { // ho premuto un tasto 
    Serial.print(key);
    lunghezzaPasswordCorrente++; // conteggio il tasto appena premuto 
    password.append(key); 
    // controllo se ho inserito tutti i caratteri che compongono la password 
    if (lunghezzaPasswordCorrente == LUNGHEZZA_PASSWD) {
      lunghezzaPasswordCorrente = 0;
      // controllo se la password inserita è corretta 
      if (password.evaluate()) {
        password.reset();
        return(true);
      } else { 
        password.reset();
        return(false);
      }
    }
  } else {
    // non ho inserito tutta la password quindi non può essere corretta :)
    return(false);
  }
}

void allarme ()
{
  Serial.println("ALLARME!!!");
  tone(11, 10);
  delay(150);
  noTone(11);
  delay(150);
}

un consiglio che ti do è quello di commentare SEMPRE il codice, utilizza diversi caratteri per discriminare tra variabili e direttive al compilatore (io preferisco le variabili con caratteri minuscoli e le direttive in maiuscolo) non utilizzare variabili quando non servono.

Dino

dinodf:
Il codice potrebbe essere:

#include <Password.h>

#include <RCSwitch.h>
#include <Keypad.h>

#define CODICE_PIR 1497466 // codice sensore pir 433mhz
#define LUNGHEZZA_PASSWD 4
#define PASSWORD "1234"
#define ROWS 4
#define COLS 4

RCSwitch mySwitch = RCSwitch();
Password password = Password(PASSWORD);

byte lunghezzaPasswordCorrente = 0;
bool allarmeArmato = false;
bool allarmeScattato = false;

// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {
6, 5, 4, 3
}; // Connessione delle righe: Riga0, Riga1, Riga2 e Riga3 ai pins di Arduino.

byte colPins[COLS] = {
10, 9, 8, 7
}; // Connessione delle colonne: Colonna0, Colonna1 , Colonna2 e Colonna3 ai pins di Arduino.

Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // Creazione della tastiera

void setup()
{
pinMode(11, OUTPUT);
pinMode(12, INPUT);
Serial.begin(9600);
mySwitch.enableReceive(0); //riceve sul pin 2 modulo 433mhz
}

void loop()
{
// controllo se l'allarme è armato
if (allarmeArmato) {
// controllo se ricevo il segnale di allarme
if (letturaPIR()) {
allarmeScattato = true;
}
// se è scattato l'allarme faccio suonare la "sirena"
if (allarmeScattato) {
allarme(); // faccio suonare la "sirena"
}
}

// controllo se viene inserita la password corretta
if (gestioneTastiera()) {
// se l'allarme non è armato lo armo
if (!allarmeArmato) {
allarmeArmato = true;
} else {
// se è armato ed è scattato l'allarme lo spengo
if (allarmeScattato)
allarmeScattato = false;
// se non è scattato l'allarme disarmo l'allarme
else
allarmeArmato = false;
}
}
}

bool letturaPIR() {
if (mySwitch.available() && mySwitch.getReceivedValue() == CODICE_PIR) {
mySwitch.resetAvailable();
return true;
} else {
return false;
}
}

bool gestioneTastiera() {
char key = kpd.getKey();
if (key != NO_KEY) { // ho premuto un tasto
Serial.print(key);
lunghezzaPasswordCorrente++; // conteggio il tasto appena premuto
password.append(key);
// controllo se ho inserito tutti i caratteri che compongono la password
if (lunghezzaPasswordCorrente == LUNGHEZZA_PASSWD) {
lunghezzaPasswordCorrente = 0;
// controllo se la password inserita è corretta
if (password.evaluate()) {
password.reset();
return(true);
} else {
password.reset();
return(false);
}
}
} else {
// non ho inserito tutta la password quindi non può essere corretta :slight_smile:
return(false);
}
}

void allarme ()
{
Serial.println("ALLARME!!!");
tone(11, 10);
delay(150);
noTone(11);
delay(150);
}

ho provato il tuo codice ma nemmeno funziona:

  1. l'antifurto entra in funzione alla pressione di qualsiasi codice (anche una sola cifra)
  2. dopo aver inserito questa password sbagliata e il PIR rileva movimento inizia a suonare (ma non dovrebbe dato che la password non è corretta)
  3. a questo punto che l'antifurto si mette a suonare si può disattivare con il codice sbagliato (anche una sola cifra)
  4. se il PIR rileva altro movimento fa riscattare l'allarme (qui proprio non riesco a capire il perchè lo faccia dato che si dovrebbe reinserire la password)
  • se è inserito l'allarme controlla se il sensore ti segnala che è "scattato l'allarme" suonando la sirena, NON sapendo nulla non posso garantirti che sia corretto quello che hai ipotizzato; sicuro che il sensore pir invii il codice solo quando scatta l'allarme?

allora il sensore pir invia il codice (1497466) per una frazione di secondi ogni qual volta rileva movimento, io lo posso capire dato che si accende un led rosso sul sensore, quello che posso dire è che il sensore funziona veramente bene da quando lo sto provando e non invia falsi movimenti. Il sensore in questione è:

  • se è scattato l'allarme fai suonare la sirena
  • se inserisci la password corretta e l'allarme sta suonando disattiva la sirena
  • se inserisci la password corretta e l'allarme non sta suonando disinserisci l'allarme

non è proprio corretto:

  1. se inserisci la password corretta ATTIVA/DISATTIVA l'antifurto (a seconda dello stato attuale)
  2. a questo punto se il sensore pir rileva movimento invia il segnale e arduino fa suonare la sirena

cosmo96:
ho provato il tuo codice ma nemmeno funziona:

  1. l'antifurto entra in funzione alla pressione di qualsiasi codice (anche una sola cifra)

Impossibile che l'antifurto scatti inserendo la password sbagliata, meno ancora che lo faccia inserendo un solo carattere

...
bool allarmeArmato = false;
...

void loop()
{
  // controllo se l'allarme è armato 
  if (allarmeArmato) {
    // controllo se ricevo il segnale di allarme 
    if (letturaPIR()) {
      allarmeScattato = true;
    }
    // se è scattato l'allarme faccio suonare la "sirena"
    if (allarmeScattato) {
      allarme(); // faccio suonare la "sirena"
    }
  }

come vedi all'avvio allarmeArmato è false e in loop() la funzione che fa suonare l'allarme è dentro all'if(allarmeArmato) che essendo false non viene eseguito.
Quindi o sbagli qualcosa tu nel caricare lo sketch e continui ad utilizzare quello che è già presente nell'Arduino oppure c'è qualche errore nel cablaggio o nell'uso del tastierino.
Alla pressione dei tasti sul tastierino cosa leggi via monitor seriale?

Ho simulato la tastiera ed il sensore wireless ed il codice funziona alla perfezione!
Puoi fare anche tu questa prova?

  1. Collega il pin 7 dell'Arduino a GND
  2. Carica lo sketch:
#include <Password.h>
#include <RCSwitch.h>
#include <Keypad.h>

#define CODICE_PIR 1497466 // codice sensore pir 433mhz
#define LUNGHEZZA_PASSWD 4
#define PASSWORD "1234"
#define ROWS  4
#define COLS  4

#define PININ  7 // pin per la simulazione della ricezione dell'allarme 

RCSwitch mySwitch = RCSwitch();
Password password = Password(PASSWORD);

byte lunghezzaPasswordCorrente = 0;
bool allarmeArmato = false;
bool allarmeScattato = false;

// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {
  6, 5, 4, 3
}; // Connessione delle righe: Riga0, Riga1, Riga2 e Riga3 ai pins di Arduino.

byte colPins[COLS] = {
  10, 9, 8, 7
}; // Connessione delle colonne: Colonna0, Colonna1 , Colonna2 e Colonna3 ai pins di Arduino.

Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // Creazione della tastiera

void setup()
{
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  Serial.begin(9600);
  mySwitch.enableReceive(0);  //riceve sul pin 2 modulo 433mhz

  pinMode(PININ, INPUT);      // pin con il quale simulo la ricezione dell'allarme 
  digitalWrite(PININ, HIGH) ; // pull-up attivo 
}

void loop()
{
  delay(250); // attesa per evitare di scrivere in continuazione sulla seriale 
  // controllo se l'allarme è armato 
  if (allarmeArmato) {
    Serial.print("L'allarme è armato\n");
    // controllo se ricevo il segnale di allarme 
    if (letturaPIRSimulato()) {
      Serial.print("L'allarme è armato ed ho ricevuto il segnale di allarme\n");
      allarmeScattato = true;
    }
    // se è scattato l'allarme faccio suonare la "sirena"
    if (allarmeScattato) {
      allarme(); // faccio suonare la "sirena"
    }
  } else {
    Serial.print("L'allarme è disarmato\n");
  }

  // controllo se viene inserita la password corretta 
  if (gestioneTastieraSeriale()) {
    // se l'allarme non è armato lo armo 
    if (!allarmeArmato) {
      Serial.print("ARMO l'allarme\n");
      allarmeArmato = true;
    } else {
      // se è armato ed è scattato l'allarme lo spengo
      if (allarmeScattato) {
        Serial.print("SCATTATO L'ALLARME\n");
        allarmeScattato = false;
      // se non è scattato l'allarme disarmo l'allarme
      } else {
        Serial.print("DISARMO l'allarme\n");
        allarmeArmato = false;
      }
    }
  }
}

bool letturaPIR() {
  if (mySwitch.available() && mySwitch.getReceivedValue() == CODICE_PIR) {
    mySwitch.resetAvailable();
    return true;
  } else {
    return false;
  }
}

bool letturaPIRSimulato() {
  // se il pin non è cortocircuitato a GND ho ricevuto il segnale di allarme (pin libero) 
  if (digitalRead(PININ)) {
    return true;
  } else {
    return false;
  }
}

bool gestioneTastiera() {
  char key = kpd.getKey();
  if (key != NO_KEY) { // ho premuto un tasto 
    Serial.print("Hai premuto: ");
    Serial.println(key);
    lunghezzaPasswordCorrente++; // conteggio il tasto appena premuto 
    password.append(key); 
    // controllo se ho inserito tutti i caratteri che compongono la password 
    if (lunghezzaPasswordCorrente == LUNGHEZZA_PASSWD) {
      lunghezzaPasswordCorrente = 0;
      // controllo se la password inserita è corretta 
      if (password.evaluate()) {
        password.reset();
        return(true);
      } else { 
        password.reset();
        return(false);
      }
    }
  } else {
    // non ho inserito tutta la password quindi non può essere corretta :)
    return(false);
  }
}

bool gestioneTastieraSeriale() {
  char key; 
  if (Serial.available()) {   // simulando via seriale la lettura del tastierino
    key = Serial.read();
    Serial.print("Hai premuto: ");
    Serial.println(key);
    lunghezzaPasswordCorrente++; // conteggio il tasto appena premuto 
    password.append(key); 
    // controllo se ho inserito tutti i caratteri che compongono la password 
    if (lunghezzaPasswordCorrente == LUNGHEZZA_PASSWD) {
      lunghezzaPasswordCorrente = 0;
      // controllo se la password inserita è corretta 
      if (password.evaluate()) {
        password.reset();
        return(true);
      } else { 
        password.reset();
        return(false);
      }
    }
  } else {
    // non ho inserito tutta la password quindi non può essere corretta :)
    return(false);
  }
}


void allarme ()
{
  Serial.println("ALLARME!!!");
  tone(11, 10);
  delay(150);
  noTone(11);
  delay(150);
}
  1. Apri il monitor seriale
  2. Digita anche molto lentamente se vuoi verificare bene 1234[invio] nel monitor seriale (armi l'allarme)
  3. Digita nuovamente 1234 (disarmi l'allarme)
  4. Digita nuovamente 1234 (riarmi l'allarme)
  5. Scollega il pin 7 da GND (il sensore segnala che c'è stato un movimento)
  6. Ricollega il pin 7 a GND (il sensore invia un segnale solo, non in continuazione)
  7. Digita 1234 (taciti il buzzer ma l'allarme rimane attivo)
  8. Digita 1234 (disarmi l'allarme)

vedrai che funziona alla grande. (se non funziona come indicato significa che commetti degli errori nel caricare lo sketch)

D

questo è l'output del monitor seriale simulando il sensore pir con il pin 7 a massa:

ovviamente la password l'ho inserita tramite la tastiera del pc