Problemas con Interrupciones

Hola tengo un problema con esta programación lo explico brevemente.
Cuando cargo el programa al arduino Uno y comienzan a funcionar las sentencias de la función Loop funcionan a la primera, pero cuando presiono el pushbuton para activar la interrupción y volver la variable banderaAlarma = LOW no sale de la función Do - While continua allí infinitamente.
Como puedo solucionarlo gracias por sus comentarios.

boolean banderaAlarma = HIGH;
int pinBuzzer = 15; 
int pinLed1 = 16;
int pinLed2 = 8;
int pinBoton = 2; // Terminal usado como Interrupcion del arduino uno
int rep;
int numRep = 10;
int tiempoEnc = 600;
int tiempoApag = 400;
int tiempoEspera = 9900;

void setup() {
  pinMode(pinBuzzer, OUTPUT);
  pinMode(pinLed1, OUTPUT);
  pinMode(pinLed2, OUTPUT);
  pinMode(pinBoton, INPUT);
  attachInterrupt(digitalPinToInterrupt(pinBoton),Interruptor,RISING);
}

void loop() {
  digitalWrite(pinLed2,HIGH);
  delay(1000);
  digitalWrite(pinLed2,LOW);
  delay(1000);
  banderaAlarma = HIGH;
  do {
    Alarma();
  }
  while (banderaAlarma == HIGH);
}


void Alarma() {
  for (rep = 0; rep < numRep; rep++) {
    digitalWrite(pinBuzzer, HIGH);
    digitalWrite(pinLed1, HIGH);
    delay(tiempoEnc);
    digitalWrite(pinBuzzer,LOW);
    digitalWrite(pinLed1,LOW);
    delay(tiempoApag);
  }
  delay(tiempoEspera);
}

void Interruptor(){
  banderaAlarma = LOW;
}

Hola
Vea lo que sucede con su código:
Al iniciar el bucle (), después de parpadear el pinLed2,
establece "banderaAlarm = HIGH;" e ingrese el DO ().
DO () llama a la rutina "Alarm ()" que sigue parpadeando "pinLed1", activando el zumbador por "numRep" veces.
al final espera un tiempo "tiempoEspera" y vuelve a la DO.
Al presionar el botón en el pin 2, se produce la interrupción, pero solo hará alguna acción si está fuera de la rutina "Alarm ()", es decir, dentro del DO.
Al volver al DO el valor de "banderaAlarm" = falso, y salir del DO,
y vuelve al inicio del loop (), parpadeando el pinLed2, haciendo de nuevo banderaAlarm = HIGH, entrando y permaneciendo dentro del DO.
No sé si lo tuve claro.

¿Cómo le gustaría que funcione su código?

1 Like

Exacto así deseo que funcione pero el problema que tengo es que por más que presione el pushbutton se queda en do-while y ya no vuelve a parpadear el led2, lo realicé la simulación en tinkercad y da como indicas y como deseo que funcione, pero al pasar al arduino real no funciona como deseo.

En principio banderaAlarma tiene que ser volatile

volatile boolean banderaAlarma = HIGH;

ya que la modifica en la interrupción.

Por otro lado, sacando el detalle anterior, el código está bien. Modifique la definición de banderaAlarma y seguramente haga lo que quiere.

Saludos

1 Like

Pues lo lógico sería sin olvidar el comentario de @gatul modificar la interrupción asi

void Interruptor(){
  banderaAlarma != banderaAlarma;
}

y quitando en el loop banderaAlarma = HIGH;

void loop() {
  digitalWrite(pinLed2,HIGH);
  delay(1000);
  digitalWrite(pinLed2,LOW);
  delay(1000);
  // banderaAlarma = HIGH;
  do {
    Alarma();
  }
  while (banderaAlarma == HIGH);
}

Coloca esto en la última línea del setup

banderaAlarma = HIGH;

Y luego dependerá de como bascules el pulsador.
Si presionas cambia a low y queda asi.
Si presionas de nuevo pasa a HIGH y queda asi.

1 Like

Pero eso no es lo que el PO quiere lograr. :roll_eyes:

Saludos

Muchas gracias por su respuesta lo modificaré e intentaré nuevamente.
:mechanical_arm: :robot:

Muchas gracias por su comentario voy a revisar su programación, pero viendo paso a paso mi simulación en tinkercad funciona el problemas es que al pasarlo a mi arduino y realizar el circuito ya no realiza lo simulado sino que se queda en do y no sale de allí.

En las simulaciones todo puede funcionar hermoso o no funcionar para nada, no es más que eso, una simulación y como tal hay cosas que pueden no ser exactamente igual a la realidad.

Te doy un ejemplo, en Proteus las interrupciones hardware del ATMega328 solo trabajan por LOW, siendo que en la realidad pueden reaccionar a tres estados diferentes (LOW, HIGH y change). Otra, I2C entre 2 arduinos, el esclavo solo puede recibir, el envio de datos del esclavo no funciona.

Es probable que en tinkercad no importe que una variable no se declare volatile y funcione igual, pero en la realidad es necesario declararla sino genera problemas (la hoja de datos del micro es clara en eso).

Saludos

1 Like

Genial muchas gracias cada vez aprendo más de sus experiencias, agradecido por las recomendaciones y experiencias que me brindan, si funciona según como indica tenía que colocar
volatile boolean banderaAlarma = HIGH;