I can't make interrupt to work

I'm using a UNO. A push button is conected between pin 2 and ground. Then I have this:

attachInterrupt(0,blink,LOW);

I understand that in this board I don't have to tell which pin is triggering the interrupt, as any between 2 and 3 will do (0 is the interrupt number).

and this is blink (besides the blinking, the variable autom should toogle between false and true);

void blink()
{
detachInterrupt(0);
delay(1000);
autom = not autom;
for (int i=1;i<=5;i++)
{
digitalWrite(13,HIGH);
delay(100);
digitalWrite(13,LOW);
delay(100);
}
attachInterrupt(0,blinkCambioModo,LOW);
Serial.print("autom ");Serial.println(autom);
}

Even detaching the interrupt at the beginning doesn't prevent the variable autom to change values three times, in most ocurrences, thus keeping the initial value;sometimes it works.

I tried with CHANGE to no avail.

?

Using LOW will cause the interrupt to fire repeatedly over and over as long as the pin is held low. Most likely that is not what you want. It's definitely not what you want if you want the ISR to fire once per button press.

Also those serial print statements in the ISR routine are a recipe for a lockup. If ever the serial buffer gets full and this fires the code will lock up waiting for a serial interrupt to make room in the buffer but that cannot happen as interrupts are disabled during the ISR. You should never ever have serial code in an ISR.

Additionally the delay calls can also lock you up as they too rely on timer interrupts. Interrupts should be super fast and are intended for things that happen so fast that they could be missed. Button presses really don't fit that description unless you are really capable of pressing and releasing a button in less than a few microseconds.

Why are you attaching and detaching interrupts inside an ISR? Also, delay() won't work inside in in ISR. It's also a terrible idea to allow an ISR to run for extended time periods.

Interrupt 0 only applies to pin 2, not pin 3 as well. Forever avoid any source of information that told you that.

something like this (untested):

#define DEBOUNCE_TIME 15  
volatile int flag = 0;
bool autom = false;

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, blink, FALLING);
}

void loop()
{
  if (flag)
  {
    delay(1000);
    autom = !autom;
    for (int i = 1; i <= 5; i++)
    {
      digitalWrite(13, HIGH);
      delay(100);
      digitalWrite(13, LOW);
      delay(100);
    }
    Serial.print("autom "); Serial.println(autom);
    flag--;
  }

}

void blink()
{
  static unsigned long lastMillis = 0;
  if (millis() - lastMillis > DEBOUNCE_TIME)
  {
    flag++;
    lastMillis = millis();
  }
}

Or even better:

Uncompiled and untested, but you get the point (ditch the interrupt)
I also added the missing Serial.begin.

#define DEBOUNCE_TIME 15  
boolean flag = 0;
bool autom = false;

void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  pinMode(2, INPUT_PULLUP);
}

void loop()
{
  static int lastState = HIGH;
  static unsigned long lastStateChange = millis();
  int buttonState = digitalRead(2);
  if(buttonState != lastState){
    lastStateChange = millis();
  }
  if(buttonState == LOW && millis() - lastStateChange >= DEBOUNCE_TIME){
    flag = true;
  }

  if (flag)
  {
    delay(1000);
    autom = !autom;
    for (int i = 1; i <= 5; i++)
    {
      digitalWrite(13, HIGH);
      delay(100);
      digitalWrite(13, LOW);
      delay(100);
    }
    Serial.print("autom "); Serial.println(autom);
    flag = false;
  }

}

Now all that needs is to change the blink part to not use delay.

Really, everyone should be making friends with the digitalPinToInterrupt() macro.

pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), blink, FALLING);

I'm trying to understand all of this.

rva1945:
I'm trying to understand all of this.

Good. Surprisingly often, that is not the case. :slight_smile:

I added Serial.print in order to see what whas happening as it was already failing to properly work.

rva1945:
I added Serial.print in order to see what whas happening as it was already failing to properly work.

And thereby almost guaranteeing that it would fail.

When you send a string to be printed, it is added character-by-character to a memory buffer of finite length.
If there is no space in the buffer, the print method must wait until there is.

When the UART signals that its transmit buffer is empty, and interrupt is generated, and the interrupt service routine takes a character from the buffer and writes it to the transmit register, and adjusts the buffer pointer to indicate that there is a space.

If your process is in your interrupt service routine, interrupts are disabled, so the UART cannot signal an empty register, so you'll keep adding characters tot the transmit buffer until it is full.
So, the print method will spin, waiting for space in the buffer, which will never happen, because nothing can empty the buffer.
Deadlock.