Problema con un ciclo while - RISOLTO

Ciao a tutti, sono nuovo del forum e alle prime armi con arduino. Sto realizzando un circuito di allarme con una tastiera che attiva un relè, un sensore PIR e un sensore da porta. Tutti e tre i componenti si comportano come interruttori, quindi ho deciso di usare le porte digitali e usare le uscite a 5V e 3.3V di arduino uno.
Il problema è che mentre il relè della tastiera rimane fisso in uno stato, quindi continuamente acceso o spento, gli altri due sensori sono paragonabili a dei pushbotton quindi cambiano stato per un breve tempo. Non riesco a far rimanere l'uscita alta quando i sensori tornano allo stato originale. Questo è il codice che ho scritto:

const int buttonPin = 2;    
const int ledPin =  13;     
const int sensMov = 3;
const int tastiera = 4;

int buttonState;       
int buttonState2;
int buttonState3;
int state;

void setup() {

  pinMode(ledPin, OUTPUT);      
  pinMode(buttonPin, INPUT);  
  pinMode(sensMov, INPUT); 
  pinMode(tastiera, INPUT); 

}

void loop(){

  buttonState = digitalRead(buttonPin);
  buttonState2 = digitalRead(sensMov);
  buttonState3 = digitalRead(tastiera); 
 
  


      
      if (buttonState3 == LOW && buttonState == LOW ){
                state++;
          }
      if (buttonState3 == LOW && buttonState2 == LOW ){
                state++;
          }
      
while(state > 0 && buttonState3 == LOW){
      digitalWrite(ledPin, HIGH);
      buttonState3 = digitalRead(tastiera); 
      state++;
      }
digitalWrite(ledPin, LOW);
state=0;
}

Non capisco perchè esce dal loop del while. Grazie in anticipo a tutti per l'aiuto.

Non capisco il codice, cioè lo capisco ma mi confonde il modo in cui l'hai scritto.

Mi pare di capire che è un allarme, composto da un tasto (no tastiera, solo un pulsante giusto?), un sensore PIR, un contatto magnetico porta, come segnali in Input. Mentre in output hai il relè, che deve attivarsi quando uno dei due segnali passa da uno stato considerato normale a quello considerato un'allarme. Il tasto serve per uscire dallo stato di allarmeme giusto?

Io userei delle costanti per definire lo stato, es stato = 0, non ce allarme, stato = 1 il pir ha rilevato qualcosa, stato = 2 il sensore porta.

#define NORMAL_STATE 0
#define ALLARM_PIR 1
#define ALLARM_PORTA 2
int currentState

loop() {

    if (currentState) { // se lo stato corrente è vero, cioè se currentState = 1 o a 2, sei in condizione di allarme
        buttonState3 = digitalRead(tastiera);
        if (buttonState3)   // se usi la pullup usa if (!buttonState3) 
            currentState = 0; // resetta la condizione di allarme;
    } else {
        buttonState = digitalRead(buttonPin);
        
        if (buttonState) {  // se usi la pullup usa if (!buttonState) 
            currentState = 2;
        } else {
            buttonState2 = digitalRead(sensMov);
            if (buttonState2)   // se usi la pullup usa if (!buttonState2) 
                currentState = 1;
        }
    }  
}

In questo modo solo quando sei in condizione di allarme controllo lo stato del tasto, altrimenti se non sei in condizione di allarme controlla prima il sensore porta se questo e normale controlla il sensore pir se questo è normale continua ripartendo a controllare dal sensore porta e così via.

Ciao.

io lo farei in modo ancora diverso :slight_smile:
secondo me è più efficente un codeice così:

#define ATTIVO 1//o 0 a seconda della logica che usi
#define INATTIVO 0 //o 1 a seconda della logica che usi
void setup ()
{
    pinMode(SENSOREPORTA,INPUT);
    pinMode(SENSOREPIR,INPUT);
    pinMode(TASTO,INPUT);
    pinMode(ALLARME,OUTPUT);
}

void loop()
{
    if(TASTO==ATTIVO)
        if(digitalRead(SENSOREPORTA)||digitalRead(SENSOREPIR))
            ALLARME==ATTIVO;
    if(TASTO==INATTIVO)
        ALLARME=INATTIVO;
}

gugu000:
Non capisco perchè esce dal loop del while. Grazie in anticipo a tutti per l'aiuto.

Esce dal loop perché incrementi state di continuo, però un int va in overflow dopo il valore 32767 e riparte da -32768 per cui ad un certo punto la condizione non è più vera, essendo state minore di 0.

Grazie a tutti per il supporto. Alla fine dopo varie prove sono giunto ad una mia soluzione che mi aiuterà anche nell'aggiunta in futuro di nuovi componenti.La mia soluzione è stata questa:

    const int SENSOREPORTA1 = 2;    
    const int ALLARME1 =  13;     
    const int SENSOREPIR1 = 3;
    const int TASTIERA = 4;
    const int ANTIEFFPORTA1 = 8;
    const int ANTIEFFPIR1 = 9;
    int stato;
    int porta;
    int pir;
    int tastiera;

void setup ()
{
  
  
    pinMode(SENSOREPORTA1,INPUT);
    pinMode(SENSOREPIR1,INPUT);
    pinMode(TASTIERA,INPUT);
    pinMode(ALLARME1,OUTPUT);
}

void loop()
{
while(digitalRead(TASTIERA)==LOW && digitalRead(SENSOREPORTA1)==LOW){
        digitalWrite(ALLARME1, HIGH);
        digitalRead(TASTIERA);
        }
while(digitalRead(TASTIERA)==LOW && digitalRead(SENSOREPIR1)==LOW){
        digitalWrite(ALLARME1, HIGH);
        digitalRead(TASTIERA);
        }
while(digitalRead(TASTIERA)==HIGH){
        digitalWrite(ALLARME1, LOW);
        digitalRead(TASTIERA);
        }        
}

Grazie ancora a tutti e spero che in futuro anche io possa essere d'aiuto per qualcuno del forum.

invio codice correttamente dopo prima esecuzione non accetta piu comandi serial Grazie

const byte md = 13;
const byte SensorPin1 = 6;
const byte SensorPin2 = 7;
const byte ms = 12;
int SensorState1 = 0;
int SensorState2 = 0;
char val = '0';

void setup()
{ delay(1000);
  Serial.begin (9600);
  pinMode (md, OUTPUT);
  pinMode (ms, OUTPUT);
  pinMode (SensorPin1, INPUT);
  pinMode (SensorPin2, INPUT);
}

void loop() {
  val = Serial.read ();
if (val == '2'  ) // invio comando
  while  (SensorState2 == 0)// Aspetto sensore alto
  {
    SensorState2 = digitalRead(SensorPin2);
    if ( SensorState2 == 1)
    {
      digitalWrite(md, LOW);
      digitalWrite(ms, HIGH);
      delay(200);
      while ( SensorState2 == 1 )
      {
        SensorState2 = digitalRead(SensorPin2);
        if ( SensorState2 == 0 )
        {
          digitalWrite(ms, LOW);
          delay(100); // fino qui perfetto
         val = Serial.read ();
        }
      }
    }
  }
  // comando 2 non prende comando non so perche forse non esce da while 
 //precedente
  if ( val == '1')
  while ( SensorState1 == 0 )
  {
    SensorState1 = digitalRead(SensorPin1);
    if ( SensorState1 ==  1)
    {
      digitalWrite(ms, LOW);
      digitalWrite(md, HIGH);
      delay(200);
      while ( SensorState1 == 1 )
      {
        SensorState1 = digitalRead(SensorPin1);
        if ( SensorState1 == 0  )
        {
          digitalWrite(md, LOW);
           val = Serial.read ();
        }
      }
    }
  }
}

Gegia, ma che stai facendo? Hai sbagliato thread forse?