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