Problema allarme per casa domotica

Ciao a tutti. Io sto facendo una casa domotica(in un plastico) e sto programmando i vari sensori uno ad uno.

Oggi sto cercando di fare l'allarme ma non riesco a fare una parte.

Il mio allarme funziona così: per attivarlo devo premere un pulsante, una volta attivato l'allarme e la porta è chiusa non suona niente, quando invece la porta si apre inizia a suonare l'allarme e un LED lampeggia, per disattivare il suono e l'allarme devo premere il pulsante e una volta che l'ho premuto posso tranquillamente aprire e chiudere la porta senza che suoni niente fino a quando non lo ripremo.
Io riesco a fare il programma fino alla parte in cui suona il buzzer quando la porta si apre(senza il pulsante), se poi provo a farlo con i pulsanti non mi funziona più niente o funziona male. Mi potete aiutare per favore?
Ovviamente prima di scrivere qui, ho già visto su internet e nel forum ma non ho trovato niente che mi risolvesse il problema.
Di seguito vi metto il programma che ho fatto e il circuito realizzato.

// Stabilisco i pin dei componenti
const int ledPin=13;
const int piezoPin=9;
int porta=2;
int statoPorta=0;



void setup()
{
  Serial.begin(9600);
  // Definisco i seguenti componenti come OUTPUT
  pinMode(ledPin, OUTPUT);
  pinMode(piezoPin, OUTPUT);
  pinMode(porta, INPUT);



}

void loop()
{
  statoPorta=digitalRead(porta); //Leggo lo stato della porta
  if(statoPorta==LOW) //Se la porta è aperta eseguo le seguenti istruzioni
  {

    digitalWrite(ledPin,HIGH); // Accendo il led
    tone(piezoPin,900); // Suono "alto"
    delay(250); //Aspetto 250 millisecondi
    digitalWrite(ledPin,LOW); // Spengo il led
    tone(piezoPin,700); // Suono "basso"
    delay(250); //Aspetto 250 millisecondi
  }

  else if(statoPorta==HIGH) //Altrimenti se la porta è chiusa...
  {
     noTone(piezoPin); //Spengo l'allarme
     digitalWrite(ledPin,LOW); //Spengo il LED
  }

}

Prima di avventurarci nel codice ti vorrei dare un consiglio, sostituisci al cavo cortocircuito un interruttore Reed normalmente chiuso e un magnete sulla porta, in questo modo quando andrai ad aprire la porta il circuito si chiuderà, perché questo; perché la porta rimarrà prevalentemente chiusa per tanto col tuo sistema avresti un passaggio continuo di corrente, con il sistema reed il passaggio di corrente arriva solo quando la porta si apre riducendo il consumo del circuito, questa è solo una piccola modifica, non inciderà molto ma di sicuro non può che fare bene.

Passiamo al codice, impieghi tantissimo tempo per gestire il codice! quanto dura la pressione di un pulsante, 100ms, 200ms? Tu metti due delay da 250ms in un ciclo di lavoro del micro, è difficile che riuscirai ad intercettare la pressione del pulsante in disattivazione, devi sviluppare un codice piu ragionato, non puoi frezzare il micro per il 95% del tempo e sperare di beccare un valore high che dura pochi ms.
Allora le scelte sono due sostanzialmente:
-Sviluppi il codice in modo piu preciso, nel senso cerchi di eseguire per esempio tone una sola volta al cambio del valore della porta, salvando la posizione della porta in una variabile.
-Gestisci il pulsante con un extInterrupt (io ti consiglio questa scelta). Arduino UNO presenta due pin che possono generare interrupt al cambio di stato del suddetto pin, cosi quando lo stato del pulsante cambierà il codice in esecuzione verrà messo in pausa e potrai gestire la pressione del pulsante.

Ovviamente alla porta non metterò due fili come ho fatto in questo circuito, questo infatti è solo un circuito di prova.
Per quanto riguarda la programmazione ho provato a fare l'interrupt (togliendo anche il delay) però non mi ha funziona. Adesso provo un'altra volta, e se non dovesse andare proverò anche il primo metodo che mi hai consigliato.
Grazie dell'aiuto :smiley:

I delay sono messi per fare l'effetto lampeggiante del led, no? Perche dovresti toglierli se usi gli interrupt, in ogni caso posta il codice e vediamo dove sbagli.

Ti servono sostanzialmente 3 variabili di stato.
La prima è quella che memorizza lo stato dell'impianto di allarme, se on o off. A seconda di come è settata questa gestisci il resto del programma.
Il resto del programma usa le altre 2 variabili, la prima memorizza lo stato della porta, se aperta o chiusa, ed in caso di porta aperta fa suonare la sirena. L'ultima memorizza lo stato della sirena, per evitare di attivarla ogni volta che si verificano le 2 condizioni precedenti, ossia allarme on e porta aperta.
Ovviamente le istruzioni delay vanno ELIMINATE e sostituite con un codice basato su millis, dove il codice controlla con il passare del tempo le eventuali azioni da fare.

Per fare una cosa reattiva e sicura puoi agganciare il sensore della porta ad un interrupt, in modo che la lettura dell'apertura sia effettuata in ogni condizione, ma questo non è strettamente un vincolo perché con la gestione basata su millis puoi permetterti di fare un semplice digitalWrite, se il codice è molto semplice. Ovvio che se andiamo a realizzare un programma più complesso, l'input dalla porta potrebbe arrivare quando il programma non legge il pin e quindi perdersi l'evento.

Allora ragazzi, questo mese non ho avuto molto tempo, quindi ho ripreso il progetto oggi. Io sono andato un po' su internet e ho cercato di capire come si usa l'interrupt e quindi ho fatto una piccola modifica al programma(solo per provare l'interrupt) facendo in modo che una volta premuto il tasto il LED rimanesse accesso. Il problema è che non funziona, infatti il LED non si accende. Ecco il programma:

// Stabilisco i pin dei componenti
const int ledPin=13;
const int piezoPin=9;
int porta=2;
int statoPorta=1; 



void setup()
{
  
  Serial.begin(9600);
  // Definisco led e piezo come OUTPUT
  pinMode(ledPin, OUTPUT);
  pinMode(piezoPin, OUTPUT);
  pinMode(porta, INPUT);
  attachInterrupt(0, allarmeAttivo, CHANGE);


}

void loop()
{
  statoPorta=digitalRead(porta); //Leggo lo stato della porta
  if(statoPorta==LOW) //Se la porta è aperta eseguo le seguenti istruzioni
  {

    digitalWrite(ledPin,HIGH); // Accendo il led
    tone(piezoPin,900); // Suono "alto"
    //delay(250); //Aspetto 250 millisecondi
    digitalWrite(ledPin,LOW); // Spengo il led
    tone(piezoPin,700); // Suono "basso"
    //delay(250); //Aspetto 250 millisecondi
  }

  else if(statoPorta==HIGH) //Altrimenti se la porta è chiusa...
  {
     noTone(piezoPin); //Spengo l'allarme
     digitalWrite(ledPin,LOW); //Spengo il LED
  }
}

void allarmeAttivo()
  {
     digitalWrite(ledPin,HIGH);
  }

Dal file fritzing allegato al primo post, hai che il filo bianco (quello che simula la porta) è collegato al pin 1, tu dichiari come porta il pin 2, e come interrupt usi lo 0 (sempre pin 2) ...
L'HW reale è come lo schema? Potrebbe essere per quello che non funziona ...

Brado:
Dal file fritzing allegato al primo post, hai che il filo bianco (quello che simula la porta) è collegato al pin 1, tu dichiari come porta il pin 2, e come interrupt usi lo 0 (sempre pin 2) ...
L'HW reale è come lo schema? Potrebbe essere per quello che non funziona ...

Nono, non è quello l'errore. Il fatto è che, a quanto pare, mi sono sbagliato a collegare il filo su fritzing, ma nella realtà li ho collegati bene i fili :slight_smile:

innanzi tutto comincia a fare i collegamenti come si deve ed a insserire delle resistenze al posto giusto

ok, ho rifatto il circuito inserendo le resistenze. Ma rimane comunque il problema dell'interrupt che non funziona...
E mi sembra una cosa strana visto che con il PIC riesco a farlo funzionare (ovviamente modificando un po' il programma), con Arduino invece non funziona :cry:

attachInterrupt(0, allarmeAttivo, CHANGE); // Interrupt attivo su pin2
attachInterrupt(1, allarmeAttivo, CHANGE); // Interrupt attivo su pin3

su quale pin lo hai collegato ?

Errore trovato: praticamente quando ho fatto delle prove ho cambiato il filo dell'allarme attivo(quindi il filo del segnale che fa attivare l'interrupt) mettendolo nel pin 1 invece di metterlo nel pin 2. Adesso sembra funzionare il tutto. Grazie a tutti dell'aiuto :smiley:

Attento che il numero da passare alla funzione attachInterrupt non è il numero del pin ma il numero dell'interrupt
0 sta per INT0, che è sul pin D2 dell'Arduino
1 sta per INT1, che è sul pin D3 dell'Arduino.

fationgega:
Nono, non è quello l'errore. Il fatto è che, a quanto pare, mi sono sbagliato a collegare il filo su fritzing, ma nella realtà li ho collegati bene i fili :slight_smile:

Quindi non proprio bene ... :stuck_out_tongue: