Interrupcion no se ejecuta "del todo"

Hola:

Haciendo pruebas me encuentro con el siguiente detalle al ejecutar una interrupcion

He aqui el codigo que supuestamente aplicaremos para un lavavajillas:

volatile int vaciado = 8;
volatile int llenado = 6;
volatile int bobinaA = 10;
volatile int bobinaT = 11;
int puerta = 2; 
  
void setup() { 
  Serial.begin(9600);  
  pinMode(vaciado, OUTPUT);
  pinMode(llenado, OUTPUT);
  pinMode(bobinaA, OUTPUT);
  pinMode(bobinaT, OUTPUT);  
  attachInterrupt(digitalPinToInterrupt(puerta), PuertaAbierta, LOW);
}

void PuertaAbierta() {
  digitalWrite(bobinaT, LOW);    //detenemos bobina trabajo
  digitalWrite(bobinaA, LOW);    //detenemos bobina arranque
  digitalWrite(llenado, LOW);     //paramos carga de agua
  digitalWrite(vaciado, LOW);    //paramos vaciado 
}


void loop() {        
        //////////////////////////////////////////////////////////////////////////////////// VACIADO
        for (int a = 0; a<=100; a++){      //bucle de vaciado
          digitalWrite(vaciado, HIGH);     //vaciamos  agua
          Serial.println ("Vaciado");          
          delay (250);                     //tiempo de vaciado
          }
          digitalWrite(vaciado, LOW);      //paramos vaciado de agua
          Serial.println ("Paramos vaciado");     
          delay (2000);
        //////////////////////////////////////////////////////////////////////////////////// LLENADO 
        for (int a = 0; a<=140; a++){      //bucle de llenado
          digitalWrite(llenado, HIGH);     //cargamos de agua
          Serial.println ("Llenado");          
          delay (250);                     //tiempo de llenado
          }
          digitalWrite(llenado, LOW);      //paramos carga de agua
          Serial.println ("Paramos llenado");     
          delay (2000);
        ////////////////////////////////////////////////////////////////////////////////////  BOBINAS MOTOR
        for (int i = 0; i<=50; i++){         //bucle de prelavado          
            digitalWrite(bobinaT, HIGH);     //arrancamos bomba
            Serial.println ("Arracamos BT");
            digitalWrite(bobinaA, HIGH);     //arrancamos bomba
            Serial.println ("Arrancamos BA");           
            delay (250);            
        }
        digitalWrite(bobinaT, LOW);         //paramos bomba
        digitalWrite(bobinaA, LOW);         //paramos bomba
        Serial.println ("Paramos bomba");       
        
}

Tal cual tenemos el codigo al ejecutar la interrupcion los digitalWrite de la interrucion se ejecutan pero los bucles "for" que se encuentran en el loop se siguen ejecutando, avanzando el codigo el el loop.

Como cosa curiosa si le coloco un Serial.println dentro de la interrupcion esta se ejecuta correctamente.

void PuertaAbierta() {
  digitalWrite(bobinaT, LOW);    //detenemos bobina trabajo
  digitalWrite(bobinaA, LOW);    //detenemos bobina arranque
  digitalWrite(llenado, LOW);     //paramos carga de agua
  digitalWrite(vaciado, LOW);    //paramos vaciado
  Serial.println ("ParadaEmergencia");
}

Detalle a comentar que si por ejemplo en la interrupcion eliminio uno o mas de los digitalWrite (de los cuatro que hay) ya se ejecuta esta correctamente.

Mi no entender....

Mi tampoco entender.
A ver si no digo ninguna burrada, cuando entra la interrupción, se ejecuta PuertaAbierta, una vez termina los 4 digitalWrite el programa sigue por donde se encontraba.
Entonces los las salidas digitales que tienes en loop te cambian a HIGH cuando les toca ya que el programa continúa.
Igual tu crees que no se ejecuta correctamente pero el problema es que cambian demasiado rápido y crees que no se ha ejecutado la interrupción correctamente.
Te propongo un cambio, y si dentro de la interrupción miras como está la entrada que la causa y si sigue activa no dejas al programa que salga del PuertaAbierta??
Sería algo así:

volatile int vaciado = 8;
volatile int llenado = 6;
volatile int bobinaA = 10;
volatile int bobinaT = 11;
int puerta = 2; 
int abierta = 0;
  
void setup() { 
  Serial.begin(9600);  
  pinMode(vaciado, OUTPUT);
  pinMode(llenado, OUTPUT);
  pinMode(bobinaA, OUTPUT);
  pinMode(bobinaT, OUTPUT);  
  attachInterrupt(digitalPinToInterrupt(puerta), PuertaAbierta, LOW);
}

void PuertaAbierta() {
  abierta = digitalRead(puerta);
  digitalWrite(bobinaT, LOW);    //detenemos bobina trabajo
  digitalWrite(bobinaA, LOW);    //detenemos bobina arranque
  digitalWrite(llenado, LOW);     //paramos carga de agua
  digitalWrite(vaciado, LOW);    //paramos vaciado 
  if (abierta == HIGH)  
  {
      PuertaAbierta();
  }
  }



void loop() {        
        //////////////////////////////////////////////////////////////////////////////////// VACIADO
        for (int a = 0; a<=100; a++){      //bucle de vaciado
          digitalWrite(vaciado, HIGH);     //vaciamos  agua
          Serial.println ("Vaciado");          
          delay (250);                     //tiempo de vaciado
          }
          digitalWrite(vaciado, LOW);      //paramos vaciado de agua
          Serial.println ("Paramos vaciado");     
          delay (2000);
        //////////////////////////////////////////////////////////////////////////////////// LLENADO 
        for (int a = 0; a<=140; a++){      //bucle de llenado
          digitalWrite(llenado, HIGH);     //cargamos de agua
          Serial.println ("Llenado");          
          delay (250);                     //tiempo de llenado
          }
          digitalWrite(llenado, LOW);      //paramos carga de agua
          Serial.println ("Paramos llenado");     
          delay (2000);
        ////////////////////////////////////////////////////////////////////////////////////  BOBINAS MOTOR
        for (int i = 0; i<=50; i++){         //bucle de prelavado          
            digitalWrite(bobinaT, HIGH);     //arrancamos bomba
            Serial.println ("Arracamos BT");
            digitalWrite(bobinaA, HIGH);     //arrancamos bomba
            Serial.println ("Arrancamos BA");           
            delay (250);            
        }
        digitalWrite(bobinaT, LOW);         //paramos bomba
        digitalWrite(bobinaA, LOW);         //paramos bomba
        Serial.println ("Paramos bomba");       
        
}

No veo uno o varios pulsadores, o un encoder, tampoco una pantalla lcd o de 7 segmentos.
Olvida la interrupción porque tu código no es un programa de lavavajillas mas o menos logrado.

Deberías solicitar ayuda desde cero, pero ofreciendo todo el material necesario para saber como funciona lavadora suponiendo que lo que intentas hacer es reconstruir una vieja máquina lavaplatos.

Recientemente he reconstruido a nuevo una lavadora de ropas Siemens de 18 años, reemplazando el programador mecánico por un arduino. El cambio de giro, o centrifugado, como la válvula de agua y bomba de desagote se activan con relay. La jabonera se maneja con un servo.

Para que veas como he hecho el soft con dos programa de lavado, ropa normal y delicada, con las opciones de centrifugar, flotar y temperatura del agua te dejo el skech donde la interrupción la uso para detectar el fallo de energía y poder retomar en el mismo lugar por donde iba el programa de lavado.

Básicamente "el programa de lavado" consta de dos datos mediante un arreglo de pasos. Un dato es un número que traducido a binario interpreta el estado de los relay y el otro dato es la cantidad de segundos que mediante un multiplicador "por default 1000" nos dice la cantidad de milisegundos entre un paso y el siguiente. Es con el uso de millis() como deberías escribir tu soft.

WP_20181108_12_36_43_Pro.jpg

WP_20181108_12_36_16_Pro.jpg

Lavadora.ino (35.9 KB)

Pregunta: En que arduino estas trabajando?

Esto es curioso

int puerta = 2;

Aplicable tal vez a un MEGA pero no a un UNO/NANO.

IMPORTANTE
Intenten al momento de escribir un programa iniciar con un comentario en el código que diga al menos.

// Arduino : Uno
// Sensor 1 tal cosa1
// Sensor 2 tal cosa2
// etc etc

// librerias http://www.github.com/XXXXXXXXX

Deben dar información de lo contrario nosotros tenemos que adivinar cada vez que plantean una duda.

Yo creo que int puerta = 2; es correcto ya que llama a la interrución con: digitalPinToInterrupt(puerta)
osea que esta le está diciendo que utilice la interrupción "0".

Tienes razón.

De todos modos, el programa no entiendo para que usa una itnerrupción. Lo he dicho 100 veces y lo voy a volver a repetir.

Usar una interrupción no tiene sentido a menos que no sepas programar (es mi opinión y claro que pueden no compartirla).

Se puede hacer todo sin necesidad de interrupciones que fueron pensadas para otra cosa y que ademas actuan sin discriminar rebotes.

Entonces.... estamos ante un código con multiples delay() lo cual a mi ya no me gusta.

Asi que dejaré a otros que opinen porque lo he dicho tantas veces que ya no tengo ganas de repetirlo.

Si quieres prestarme atención entonces ve a Documentación => indice de temas tutoriales y lee millis() y máquinas de estado.

Si quieres seguir el consejo de attiny128 que te ha regalado su trabajo tal vez tengas todo resuelto con su cordial aporte.

Y de lo contrario alguien podrá brindarte ayuda en la linea que llevas.

surbyte:
Usar una interrupción no tiene sentido a menos que no sepas programar (es mi opinión y claro que pueden no compartirla).

As dado en el clavo... me resulta mucho mas comodo la interrupcion dado mi desconocimiento en programacion

Lo que estoy usando es arduino UNO. Perdon, para la proxima lo pongo desde el principio.

attiny128:
No veo uno o varios pulsadores, o un encoder, tampoco una pantalla lcd o de 7 segmentos.
Olvida la interrupción porque tu código no es un programa de lavavajillas mas o menos logrado.

El programa se que esta imcompleto pero solo pego la parte donde tengo el problema. Es por ponerlo mas simple.

Sereno:
Mi tampoco entender.
A ver si no digo ninguna burrada, cuando entra la interrupción, se ejecuta PuertaAbierta, una vez termina los 4 digitalWrite el programa sigue por donde se encontraba.
Entonces los las salidas digitales que tienes en loop te cambian a HIGH cuando les toca ya que el programa continúa.
Igual tu crees que no se ejecuta correctamente pero el problema es que cambian demasiado rápido y crees que no se ha ejecutado la interrupción correctamente.

Voy intentar explicarlo bien, cuando pulso el interruptor de la interrupcion (queda pulsado) entra la interrupcion permanentemente hasta que yo actue otra vez en el interruptor. Mientras este activado se deberia ejecutar en bucle el codigo de la interrupcion, y ningun otro codigo mas.
Esto sucede asi pues los digitalWrite pasan de HIGH a LOW, no obtante el codigo del void loop me sigue avanzado. Es decir, que cuando yo "despulso" el interruptor para desactivar la interrupcion No me empieza donde se produjo la interrupcion.... si no mas adelante.

No se si me explico bien.

Muchas gracias a todos por responder. Soy consciente del uso de delay y de los antirebotes. Para el proximo sketch los aplicare. Me resulta todo un poco complicado.
Gracias otra vez

ArduMyth:
No sé de donde has ido cogiendo la información pero es que ya de entrada con ver los pines declarados cómo volatile hacen saltar las alarmas... si ahorro de memoria querías usa #define... y es que además dichos valores no los vas a modificar. Lo suyo es que sean constantes usando const unsigned int o const byte o #defiine.

Habia leeido en unos tutos que cuando se usan variables tanto el el loop como en la interrpcion pues que era recomendable declararlas asi.

Esta claro que de programacion ni idea... lo hago sacando cosasa de aqui y alla.

Gracias por responder