Problema antifurto

Ciao a tutti!
Ho un problema. Sto cercando di fare un antifurto che possiede queste caratteristiche:
-una volta acceso/abilitato deve aspettare da 30 sec. a 1 minuto (da decidere con il trimmer tr1 collegato su A0) prima di essere operativo
-nel caso si apra la porta (su cui è presente un sensore magnetico NC, che nel caso di apertura apre anche il contatto) deve aspettare dai 30 sec a 1 minuto (da decidere con il trimmer tr2 collegato su A1) e poi far scattare una sirena (per ora mi basta che in uscita ci sia un livello alto in quanto avro poi un rele ecc..) con un tempo di attivazione che varia da 1 minuto a 5.
-durante quest'ultima parte se premo di nuovo il pulsante di abilitazione deve spegnersi tutto.

Ho 2 problemi:

  1. i 2 contatti (pulsante e contatto porta) li legge una volta ogni tanto, puo volerci niente come possono volerci 5 secondi, non capisco perchè
  2. non riesco a disattivare il tutto ripremendo il pulsante di abilitazione, sembra che non funzioni l'interrupt.

Qui sotto il codice:
(ho fatto in modo che il led sul pin 13 lampeggiasse a due frequenze differenti nella prima parte di attivazione e in quella in cui la porta risulta aperta, quindi con allarme inserito, giusto per vedere come stesse funzionando.)

boolean x1;
int tr1,tr2,tr3;
int t1,t2,t3;
int p1,p2;
int I1,I2,I3;

void setup() {                
x1=false;
digitalWrite(7,LOW);
pinMode(2,INPUT);
pinMode(13,OUTPUT);

}


void loop() {

  p1=digitalRead(2);
  if (p1==HIGH && x1==false){

    tr1=analogRead(A0);
    tr1=tr1/34;                          //1024/34 = 30 sec.
    t1=tr1+30;
    for(I1=0; I1<=t1; I1++){
       digitalWrite(13,HIGH);
       delay(500);
       digitalWrite(13,LOW);
       delay(500);
    }
    x1=true;
    digitalWrite(13,HIGH);
  } else {
    delay(100);
  }
 
  p2=digitalRead(8);

  if(x1==true && p2==LOW){
  
    //interrupts();
    attachInterrupt(0, disattiva, CHANGE );
 

    
    tr2=analogRead(A1);
    tr2=tr2/34;                          //1024/34 = 30 sec.
    t2=tr2+30;
    for(I2=0; I2<=t2; I2++){
       digitalWrite(13,HIGH);
       delay(250);
       digitalWrite(13,LOW);
       delay(250);
       digitalWrite(13,HIGH);
       delay(250);
       digitalWrite(13,LOW);
       delay(250);
    }
    
    digitalWrite(9, HIGH);

    
    tr3=analogRead(A2);
    tr3=tr3/4;                          //1024/4 = 256 sec.= circa 4 min.
    t3=tr3+60;
    for(I3=0; I3<=t3; I3++){
       digitalWrite(13,HIGH);
       delay(250);
       digitalWrite(13,LOW);
       delay(250);
       digitalWrite(13,HIGH);
       delay(250);
       digitalWrite(13,LOW);
       delay(250);
    }
    
       
} else {
  delay(100);
}

}

void disattiva(){
  x1=false;
  digitalWrite(7,LOW);
  digitalWrite(9,LOW);
  detachInterrupt(0);
  
}

Grazie mille a tutti quelli che mi aiuteranno! :slight_smile:

Per il codice leggi il punto 7 e modifica il tuo precedente post. ([REGOLAMENTO] Come usare questa sezione del forum - Italiano - Arduino Forum)
Grazie. :grin:

Grazie! sapevo che c'era un tasto con quella funzione ma prima non ero riuscito a trovarlo :smiley:

Sempre da regolamento, mettere "Aiuto" nel titolo di un thread aiuta solo ad attirare l'attenzione amorosa dei mod... ]:smiley:

Ok grazie, giuro che sarà l'ultima volta :smiley:

Ho modificato il codice dividendo le due funzioni

boolean x1;
int tr1, tr2, tr3;
int t1, t2, t3;
int p1, p2;
int I1, I2, I3;

void setup()
{
	x1 = false;
	digitalWrite(7, LOW);
	pinMode(2, INPUT);
	pinMode(13, OUTPUT);
}

void loop()
{
	p1 = digitalRead(2);
	p2 = digitalRead(8);
	if (x1 == false)
		checkbuttonone();
	else
		checkbuttontwo();
}

void disattiva()
{
	x1 = false;
	digitalWrite(7, LOW);
	digitalWrite(9, LOW);
	detachInterrupt(0);
}

void checkbuttonone()
{
	if (p1 == HIGH)
	{
		tr1 = analogRead(A0);
		tr1 = tr1 / 34;                      //1024/34 = 30 sec.
		t1 = tr1 + 30;
		for(I1 = 0; I1 <= t1; I1++)
		{
			digitalWrite(13, HIGH);
			delay(500);
			digitalWrite(13, LOW);
			delay(500);
		}
		x1 = true;
		digitalWrite(13, HIGH);
	}
	else
	{
		delay(100);
	}
}

void checkbuttontwo()
{
	if(p2 == LOW)
	{
		//interrupts();
		attachInterrupt(0, disattiva, CHANGE );
		tr2 = analogRead(A1);
		tr2 = tr2 / 34;                      //1024/34 = 30 sec.
		t2 = tr2 + 30;
		for(I2 = 0; I2 <= t2; I2++)
		{
			digitalWrite(13, HIGH);
			delay(250);
			digitalWrite(13, LOW);
			delay(250);
			digitalWrite(13, HIGH);
			delay(250);
			digitalWrite(13, LOW);
			delay(250);
		}
		digitalWrite(9, HIGH);
		tr3 = analogRead(A2);
		tr3 = tr3 / 4;                      //1024/4 = 256 sec.= circa 4 min.
		t3 = tr3 + 60;
		for(I3 = 0; I3 <= t3; I3++)
		{
			digitalWrite(13, HIGH);
			delay(250);
			digitalWrite(13, LOW);
			delay(250);
			digitalWrite(13, HIGH);
			delay(250);
			digitalWrite(13, LOW);
			delay(250);
		}
	}
	else
	{
		delay(100);
	}
}

Manca un x1=false; percio x1 una volta messo a true rimane così.
E poi è pieno di delay.
Ovvio che non ti prende i comandi... ci mette una vita a fare il loop.

SInceramente non so come potrei fare altrimenti..e poi con l'interrupt i delay non dovrebbero dare problemi, o sbaglio?

Ecco una guida per capire come mettere attese non bloccanti senza ricorrere ad interrupt.
http://www.leonardomiliani.com/2013/programmiamo-i-compiti-con-millis/

cexco:
SInceramente non so come potrei fare altrimenti..e poi con l'interrupt i delay non dovrebbero dare problemi, o sbaglio?

Se tu non abilitassi l'interrupt all'interno del loop e non lo disabilitassi all'interno della funzione di gestione dell'interrupt .. si
Per come hai implementato tu il tutto se l'interrupt è disabilitato e tu esegui una delay (e nella routine di gestione del led ne esegui un sacco) il valore degli input non verrà letto e la pressione del pulsante non verrà registrata ...
La attachInterrupt mettila nella setup, e cambia la logica del programma in modo tale che ogni volta che tu premi il pulsante la funzione che gestisce l'interrupt lo registri poi tu a seconda dello stato in cui ti trovi (allarme inserito -> stacca, allarme disinserito -> attacca) agisci di conseguenza.
In questo modo puoi evitare di perdere la pressione del pulsante (e puoi implementare logiche più complesse tipo premi due volte il pulsante in tot milli -> attacca, premi tre volte -> stacca) , ma devi comunque leggerti il post linkato da leo72 per evitare di avere ritardi nella reazione alla pressione del pulsante dovute al fatto che sei in un loop con un sacco di delay e non ne esci per 30 secondi/1 minuto ....

ok ho provato mettendo gli interrupt direttamente nel setup, ma non cambia nulla! il led continua a lampeggiare sempre, come se ripetesse all'infinito il "case 1"

int x1;
int tr1,tr2,tr3;
int t1,t2,t3;
int p1,p2;
int I1,I2,I3;
int ledout1=4;
int sirout=9;


void setup() {                
x1=0;
digitalWrite(7,LOW);
pinMode(2,INPUT);
pinMode(ledout1,OUTPUT);


digitalWrite(2,HIGH);
digitalWrite(3,HIGH);
attachInterrupt(0,attivazione,FALLING);
attachInterrupt(1,aperturaporta,FALLING);

}


void loop() {


  switch(x1) {
    
    case 0:
    digitalWrite(ledout1,LOW);
    
    case 1:
      tr1=analogRead(A0);
      tr1=tr1/34;                          //1024/34 = 30 sec.
      t1=tr1+30;
      for(I1=0; I1<=t1; I1++){
         digitalWrite(ledout1,HIGH);
         delay(500);
         digitalWrite(ledout1,LOW);
         delay(500);
      }
      x1=true;
      digitalWrite(ledout1,HIGH);
      break;
      
    case 2:
    
    tr2=analogRead(A1);
    tr2=tr2/34;                          //1024/34 = 30 sec.
    t2=tr2+30;
    for(I2=0; I2<=t2; I2++){
       digitalWrite(ledout1,HIGH);
       delay(250);
       digitalWrite(ledout1,LOW);
       delay(250);
       digitalWrite(ledout1,HIGH);
       delay(250);
       digitalWrite(ledout1,LOW);
       delay(250);
       
    }
    
    digitalWrite(sirout, HIGH);
    
    tr3=analogRead(A2);
    tr3=tr3/4;                          //1024/4 = 256 sec.= circa 4 min.
    t3=tr3+60;
    for(I3=0; I3<=t3; I3++){
       digitalWrite(ledout1,HIGH);
       delay(250);
       digitalWrite(ledout1,LOW);
       delay(250);
       digitalWrite(ledout1,HIGH);
       delay(250);
       digitalWrite(ledout1,LOW);
       delay(250);
    }
   default:
   digitalWrite(ledout1,LOW);
  }
}

void attivazione() {
  if(x1==0){
    x1=1;
  } else if (x1 != 0) {
    x1=0;
  }
}

void aperturaporta() {
  if(x1 != 0) {
    x1=2;
  }

}

Nel case 1 ad un certo punto c'è questo:

x1=true;
  1. non è concettualmente sbagliato perché "true" vale 1 per cui l'assegnazione è corretta, però a rigor di logica non va bene dato rendi difficile seguire il tuo codice dato che x1 l'hai dichiarata di tipo int ed un utente che usa il tuo codice si aspetta che ad x1 gli assegni appunto un numero; con "true" immagina che x1 sia di tipo boolean. Ripeto, non è del tutto sbagliato perché il tipo boolean è in realtà un byte però non è logico;
  2. a parte questo, se tu dentro al case 1, riassegni ad x1 il valore 1, e nessun interrupt arriva, x1 vale 1 quindi lo switch riesegue sempre quel case.

ho corretto il punto 1, ma niente da fare continua ad entrare in quel ciclo anche se x1 è uguale a 0

Non hai messo il break alla fine del case 0..... :stuck_out_tongue:

Una cosa così fatta al volo non potrebbe andare :

const int SensorePorta           = A1;
const int PulsanteOnOff          = A2;
int Allarme = 0;
int Sirena = 0;
  
void setup() {
  
  pinMode(SensorePorta, INPUT);     // pin on off allarme
  pinMode(PulsanteOnOff, INPUT);    // pin sensore porta
  

}

void loop() {

  // se il sensore rileva qualcosa e l'allarme e attivato  
  if ((analogRead(SensorePorta) >= 1000) || ( Allarme == 1)){
   
    TempoSirena();
    
  }
  // se premo il pulsante per l'allarme controllo lo stato di esso e lo cambio
  if ( analogRead(PulsanteOnOff) >= 1000 ){
   if ( Allarme == 1){
      // disattivo l'allarme
      Allarme = 0;
      // disativo la sirena
      Sirena = 0;
   }else{ 
      TempoAttivazione();
   } 
  }
}

void TempoAttivazione(){
  int ms = 30000;
  int refreshms = 250;
  for (int i = 1; i <= 30000 / refreshms ; i++){
    ms -= refreshms;    
    delay(refreshms);
    if (i == 30000 / refreshms)
    {
      //operazioni da eseguire alla fine del countdown
      ms = 30000;
      Allarme = 1;
    }   
  }    
}

void TempoSirena(){
  int ms = 30000;
  int refreshms = 250;
  for (int i = 1; i <= 30000 / refreshms ; i++){
    ms -= refreshms;    
    delay(refreshms);
    if (i == 30000 / refreshms)
    {
      //operazioni da eseguire alla fine del countdown
      ms = 30000;
      Sirena = 1 ; 
    }   
  }    
}

Ho scritto questo codice al volo e dovrebbe funzionare! L'esame del pulsante di abilitazione lo faccio continuamente con il codice di debounce così evito antirimbalzi, inoltre l'esame della pressione del pulsante di abilitazione avviene esclusivamente in due fasi: nel loop in cui la pressione del pulsante comporta l'inizio di tutto il ciclo, e nella funzione Allarme() dove la pressione del pulsante comporta l'interruzione del ciclo e il ritorno al loop e a quel punto si ha bisogno di un'altra pressione del pulsante di abilitazione per riattivare il ciclo. Se invece vuoi che una volta attivato il pulsante di abilitazione all'inizio si rimanga nel ciclo allora bisogna modificare il codice. Provalo e facci sapere, magari ho dimenticato qualcosa :slight_smile: xD Inoltre per vedere se funzione ho inserito due led di colori differenti (verde per la fase di attivazione alla pressione del pulsante e rosso per la fase di attivazione dell'allarme).

int sensor = 10; //contatto porta
int buttonPin = 2; //pulsante di abilitazione
int greenled = 4;
int redled = 5;
int buttonState;             
int lastButtonState = HIGH;
long lastDebounceTime = 0;  
unsigned long debounceDelay = 50;
int tr1 = A0;
int tr2 = A1;
int sirena = 12;
unsigned long temp = 0;
long readpot;
#define ALLARME 60000 //intervallo in cui deve rimanere accesa la sirena


void setup() {
  pinMode( sensor, INPUT);
  pinMode( tr1, INPUT);
  pinMode( tr2, INPUT);
  pinMode( buttonPin, INPUT_PULLUP);
  pinMode( sirena, OUTPUT);
  pinMode( greenled, OUTPUT);
  pinMode( redled, OUTPUT);
  digitalWrite( greenled, LOW);
  digitalWrite( redled, LOW);
  digitalWrite( sirena, LOW);
}

void loop() {
  int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) 
    lastDebounceTime = millis();
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == LOW) {
          readpot = analogRead(tr1);
          readpot = map(readpot, 0, 1023, 30000, 60000);
          digitalWrite( greenled, HIGH); 
          temp = millis();
          while( millis() - temp <= readpot ) {}
          Controllo();
      }
    }
  }
  
  lastButtonState = reading;
}

void Controllo(void) {
 boolean val = true;
 digitalWrite( greenled, LOW);
 do {
  if( digitalRead(sensor)) {
      readpot = analogRead(tr2);
      readpot = map(readpot, 0, 1023, 60000, 300000);
      digitalWrite( redled, HIGH); 
      temp = millis();
      while( millis() - temp < readpot) {}
      val = Allarme();
  }
 }while( val);
}

boolean Allarme (void) {
  digitalWrite(sirena, HIGH);
  while( millis() - temp < ALLARME) {
  temp = millis();
  int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) 
    lastDebounceTime = millis();
  
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == LOW) {
        break;
      }
    }
  }
  
  lastButtonState = reading;
  } 
  digitalWrite(sirena, LOW);
  digitalWrite(redled, LOW);
  return false;
}