Bot Interrupt Pins quit working.

Hey Guys

For some reason my Arduino Nano's Interrupt pin 0 and 1 work really well the FIRST time. Before I implemented Interrupt pin 1 I only had 0 working and I could Interrupt it all I wanted to and how many times I wanted to as well. But for some reason after implementing 1 as well they stop working after I pulsed PIN 1. It does its job and then just goes off and after that neither of the Interrupts work.

Does anyone have an explanation for this?

Thanks guys

There's no general explanation for weird behaviour when ISRs are involved.

Post your code.

Hmm ok heres the Code.

const int led = 13;
const int Op1 = 8;
const int Op2 = 9;
const int Op3 = 10;
const int Op4 = 11;

const int bt1 = 2; //Interrupt 0;
const int bt2 = 3; //Interrupt 1;
int ledState = LOW;
int buttonState =0;
unsigned long previousMillis = 0,P1=0,P2=0,P3=0,P4=0,PS=0,preInt=0;
long interval = 1000;
long GTime = 10; 
int StateFunc =1;
int StateFunc2 =0;
int ZRan=1,ZCop=1;
int i=0;
int Enabler=0,Enabler1=0,Enabler2=0,Enabler3=0,Enabler4=0,EnablerS;
unsigned long PreMcounter =0;
unsigned long MilliCounter =0;

void setup()
  {
    // digital pins=output
    pinMode(led, OUTPUT);
    pinMode(Op1, OUTPUT);
    pinMode(Op2, OUTPUT);
    pinMode(Op3, OUTPUT);
    pinMode(Op4, OUTPUT);
    pinMode(bt1, INPUT);
    pinMode(bt2, INPUT);
    attachInterrupt(0, SC, LOW);
    attachInterrupt(1, Func, LOW);
  }
  
  void loop()
    {  
      

       
          
            switch (ZRan)
              {
              case 1:
                {
                  if (StateFunc == 1)
                  {
                   Flash();
                Op1F(1000);
                break;
                }
                else{
                  digitalWrite(Op1, LOW);
                  break;
                  }
                }
                
                //--------------------------------
              case 2:
              {
                if (StateFunc == 1)
                  {
                   Flash();
                Op2F(1000);
                break;
                }
                else{
                digitalWrite(Op2, LOW);
                break;
                }
                }
              
                //--------------------------------
              case 3:
              {
                if (StateFunc == 1)
                  {
                   Flash();
                Op3F(1000);
                break;
                }
                else{
                 digitalWrite(Op3, LOW);
                break;
                  }
                }
               
                //--------------------------------
              case 4:
                {
                if (StateFunc == 1)
                  {
                   Flash();
                Op4F(1000);
                break;
                }
                else{
                   digitalWrite(Op4, LOW);
                break;
                }
                //-------------------------------
                case 5:
                { if (StateFunc == 2)
                  {
                    ZCop = ZRan;
                   Op1F(10000);
                   break;
                  }
                }
                }
               
                //--------------------------------
            
            
          
    }
   Flash();
    }
//----------------------------------------------------------------------------
//Special Zone function on Op1
int ZoneSpec1(int c)
  {
      if (EnablerS==0)
        {
          PS = millis();
          EnablerS=1;
        }
        
        
       unsigned long curMS = millis();
      if(curMS - PS < c) 
      {
       
      digitalWrite(Op1, HIGH);
      digitalWrite(Op2, LOW);
      digitalWrite(Op3, LOW);
      digitalWrite(Op4, LOW);
     
      }
      else 
      {
        digitalWrite(Op1, LOW);
        EnablerS =0;
        StateFunc = 0;
      }
    
    }

//----------------------------------------------------------------------------
//Zone Functions
int Op1F(int c)
    {
      if (Enabler1==0)
        {
          P1 = millis();
          Enabler1=1;
        }
        
        
       unsigned long curM1 = millis();
      if(curM1 - P1 < c) 
      {
       
      digitalWrite(Op1, HIGH);
 
      }
      else 
      {
        digitalWrite(Op1, LOW);
        Enabler1 =0;
        ZRan = 2;
      }
    
    }
    
 //---------------------------------------------------------------------------------   
    int Op2F(int c)
    {
      if (Enabler2==0)
        {
          P2 = millis();
          Enabler2=1;
        }
        
        
       unsigned long curM2 = millis();
      if(curM2 - P2 < c) 
      {
        
      digitalWrite(Op2, HIGH);
          
      }
      else 
      {
        digitalWrite(Op2, LOW);
        Enabler2 =0;
        ZRan = 3;
      }
    }
    
//-----------------------------------------------------------------------------------    
    int Op3F(int c)
    {
      if (Enabler3==0)
        {
          P3 = millis();
          Enabler3=1;
        }
        
        
       unsigned long curM3 = millis();
      if(curM3 - P3 < c) 
      {
        
      digitalWrite(Op3, HIGH);
          
      }
      else 
      {
        digitalWrite(Op3, LOW);
        Enabler3 = 0;
        ZRan = 4;
      }
    }
    
  
  //-------------------------------------------------------------------------------------
    
   int Op4F(int c)
    {
      if (Enabler4==0)
        {
          P4 = millis();
          Enabler4=1;
        }
        
        
       unsigned long curM4 = millis();
      if(curM4 - P4 < c) 
      {
        
      digitalWrite(Op4, HIGH);
          
      }
      else 
      {
        digitalWrite(Op4, LOW);
        Enabler4 =0;
        ZRan = 1;
        StateFunc = 0;
      }
    }
//---------------------------------------------------------------------------------------------
//LEDBlink Storie
void Flash()
{
  unsigned long currentMillis = millis();
 if(currentMillis - previousMillis > interval) {
            // save the last time you blinked the LED 
            previousMillis = currentMillis;   
        
            // if the LED is off turn it on and vice-versa:
            if (ledState == LOW)
              ledState = HIGH;
            else
              ledState = LOW;
        
            // set the LED with the ledState of the variable:
            digitalWrite(led, ledState);


    } 
}
    
//----------------------------------------------------------------------------------------------    
//PORTED CODE !
 void Func()
{  ZCop = ZRan;
  if (StateFunc == 0)
    {
      StateFunc = 2;
      ZRan = 5;
     // digitalWrite(led, HIGH);
     
    }
    else if(StateFunc == 1)
     {
       StateFunc = 2;
        ZRan = 5;       
      // digitalWrite(led, LOW);
     
     }
}

/* void StateFunc(int x)
    {
      for (int i=0;i<x+1;i++)
      {
      if (StateFunc == 1)
        {}
        else if(StateFunc == 0)
        {break;}
      }  
  }*/

  /*
  int Op1F(int c)
    {
      unsigned long preM = previousMillis;
      unsigned long curM = millis();
      if ((curM - preM) <= c)
      {
        curM = millis();
       digitalWrite(Op1, HIGH);
       //SC();
       ZRan = 1;
       previousMillis = preM;
      }
      else if ((curM - preM) > c)
      {
        digitalWrite(Op1, LOW);
        //SC()
        ZRan = 2;
        previousMillis = preM;
      }
    }
    */
    
    void SC()
      { 
          if (StateFunc == 0)
          {
        StateFunc = 1;
        Enabler =0;
       // digitalWrite(led, HIGH);
          }
          else if(StateFunc == 1)
          {
          StateFunc = 0;
          //digitalWrite(led, LOW);
        }
      }

Hey Tux,

Finally my Code seems to work accept for the Interrupt that seems to just stop every other interrupt from ever happening again.

I'm sorry but I don't understand your code.

You could make it more readable: Press CTRL-T to have better indentation. Use variable names that describe their role or function.

What is driving the interrupt input pins? It may be that you should use interrupt mode FALLING instead of LOW.

Well at the moment Im literally using my hand and a grounded wire. Sometimes I interrupt it like 3 times to fast for my hand. Still looking for a way around that though. How would I smooth out reoccurring interrupts?

Even with LOW replaced with FALLING it still seems to do the same :(

I tried to remove some excess blank lines and give it a saner indentation…

//Interrupt implemenation.

const int led = 13;
const int zone1 = 8;
const int zone2 = 9;
const int zone3 = 10;
const int zone4 = 11;

const int in1 = 2; //Interrupt 0;
const int in2 = 3; //Interrupt 1;
int ledState = LOW;
int buttonState =0;
unsigned long previousMillis = 0,preM1=0,preM2=0,preM3=0,preM4=0,preMS=0,preInt=0,preUni;
long interval = 1000;
unsigned long UniTime = 1000; //60*60*60*1000; 
int StateCheck =1;
int StateCheck2 =0;
int ZoneCheck=1,ZoneCopy=1;
int i=0;
int Track=0,Track1=0,Track2=0,Track3=0,Track4=0,TrackS,TrackUni;
unsigned long PreMcounter =0;
unsigned long MilliCounter =0;


void setup() {
    // digital pins=output
    pinMode(led, OUTPUT);
    pinMode(zone1, OUTPUT);
    pinMode(zone2, OUTPUT);
    pinMode(zone3, OUTPUT);
    pinMode(zone4, OUTPUT);
    pinMode(in1, INPUT);
    pinMode(in2, INPUT);
    attachInterrupt(0, StateChange, LOW);
    attachInterrupt(1, Check, LOW);
}


void loop() {
    switch (ZoneCheck) {
    case 1:
        if (StateCheck == 1) {
            Flash();
            Zone1F(UniTime);
        }
        else {
            digitalWrite(zone1, LOW);
        }
        break;

    case 2:
        if (StateCheck == 1) {
            Flash();
            Zone2F(UniTime);
        }
        else {
            digitalWrite(zone2, LOW);
        }
        break;


    case 3:
        if (StateCheck == 1) {
            Flash();
            Zone3F(UniTime);
        }
        else {
            digitalWrite(zone3, LOW);
        }
        break;


    case 4:
        if (StateCheck == 1) {
            Flash();
            Zone4F(UniTime);
        }
        else{
            digitalWrite(zone4, LOW);
        }
        break;


    case 5:
        if (StateCheck == 2) {
            ZoneCopy = ZoneCheck;
            Zone1F(10000);
        }
        break;
    }

    Flash();
}


//----------------------------------------------------------------------------
//Special Zone function on Zone1
int ZoneSpec1(int c)
{
    if (TrackS==0)
    {
        preMS = millis();
        TrackS=1;
    }

    unsigned long curMS = millis();
    if(curMS - preMS < c) 
    {
        digitalWrite(zone1, HIGH);
        digitalWrite(zone2, LOW);
        digitalWrite(zone3, LOW);
        digitalWrite(zone4, LOW);

    }
    else 
    {
        digitalWrite(zone1, LOW);
        TrackS =0;
        StateCheck = 0;
    }
}

//----------------------------------------------------------------------------
//Zone Functions
int Zone1F(int c)
{
    if (Track1==0)
    {
        preM1 = millis();
        Track1=1;
    }

    unsigned long curM1 = millis();
    if(curM1 - preM1 < c) 
    {
        digitalWrite(zone1, HIGH);
    }
    else if (curM1 - preM1 > c)
    {
        digitalWrite(zone1, LOW);
        Track1 =0;
        ZoneCheck = 2;
    }
}

//---------------------------------------------------------------------------------   
int Zone2F(int c)
{
    if (Track2==0)
    {
        preM2 = millis();
        Track2=1;
    }

    unsigned long curM2 = millis();
    if(curM2 - preM2 < c) 
    {
        digitalWrite(zone2, HIGH);
    }
    else 
    {
        digitalWrite(zone2, LOW);
        Track2 =0;
        ZoneCheck = 3;
    }
}

//-----------------------------------------------------------------------------------    
int Zone3F(int c)
{
    if (Track3==0)
    {
        preM3 = millis();
        Track3=1;
    }

    unsigned long curM3 = millis();
    if(curM3 - preM3 < c) 
    {
        digitalWrite(zone3, HIGH);
    }
    else
    {
        digitalWrite(zone3, LOW);
        Track3 = 0;
        ZoneCheck = 4;
    }
}


//-------------------------------------------------------------------------------------

int Zone4F(int c)
{
    if (Track4==0)
    {
        preM4 = millis();
        Track4=1;
    }

    unsigned long curM4 = millis();
    if(curM4 - preM4 < c) 
    {
        digitalWrite(zone4, HIGH);
    }
    else
    {
        digitalWrite(zone4, LOW);
        Track4 =0;
        ZoneCheck = 1;
        StateCheck = 0;
    }

}
//---------------------------------------------------------------------------------------------
//LEDBlink Storie
void Flash()
{
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > interval) {
        // save the last time you blinked the LED 
        previousMillis = currentMillis;   

        // if the LED is off turn it on and vice-versa:
        if (ledState == LOW)
            ledState = HIGH;
        else
            ledState = LOW;

        // set the LED with the ledState of the variable:
        digitalWrite(led, ledState);
    } 
}

//----------------------------------------------------------------------------------------------    
//PORTED CODE !
void Check()
{  
    ZoneCopy = ZoneCheck;
    if (StateCheck == 0)
    {
        StateCheck = 2;
        ZoneCheck = 5;
        // digitalWrite(led, HIGH);
        detachInterrupt(1);
        attachInterrupt(1, Check, LOW);
    }
    else if(StateCheck == 1)
    {
        StateCheck = 2;
        ZoneCheck = 5;       
        // digitalWrite(led, LOW);
        detachInterrupt(1);
        attachInterrupt(1, Check, LOW);
    }
}

//--------------------------------------------------------------------------------------------------
int UniDelay(int c)
{
    int i=0;
    if (TrackUni==0)
    {
        preUni = millis();
        TrackUni=1;
    }
    int t = (c*10000);

    unsigned long curUni = millis();
    if(curUni - preUni < t) 
    {
        i++;
    }
    else
    {
        TrackUni =0;
    }
}
//--------------------------------------------------------------------------------------------------

/* void StateCheck(int x)
 {
 for (int i=0;i<x+1;i++)
 {
 if (StateCheck == 1)
 {}
 else if(StateCheck == 0)
 {break;}
 }  
 }*/

/*
  int Zone1F(int c)
 {
 unsigned long preM = previousMillis;
 unsigned long curM = millis();
 if ((curM - preM) <= c)
 {
 curM = millis();
 digitalWrite(zone1, HIGH);
 //StateChange();
 ZoneCheck = 1;
 previousMillis = preM;
 }
 else if ((curM - preM) > c)
 {
 digitalWrite(zone1, LOW);
 //StateChange()
 ZoneCheck = 2;
 previousMillis = preM;
 }
 }
 */

void StateChange()
{ 
    if (StateCheck == 0)
    {
        StateCheck = 1;
        Track =0;
        // digitalWrite(led, HIGH);
    }
    else if(StateCheck == 1) {
        StateCheck = 0;
        //digitalWrite(led, LOW);
    }
}

Uh ?

detachInterrupt(1);
attachInterrupt(1, Check, LOW);

Still quite puzzling code, especially without any comment.
You should either add copious comments or describe what you’re trying to achieve.

detachInterrupt(1); attachInterrupt(1, Check, LOW);

Yea sorry this was only something i tried to get the interrupts to work again.Didn't work though.

I really don't get why the Interrupts will just become useless like that ?

I just read about Interrupts get stuck in a Dead lock.Causing them to be unresponsive since they're already inside an interrupt but stuck. What can I do to make sure my Interrupts finish and one interrupt doesn't try and interrupt while inside another interrupt? Because this sure sounds like the problem I am having.

I too have this problem. My code is much simpler, so maybe this will help: (code fragments)

int rings = 0; ...

void setup(){ ... attachInterrupt(0,offHook,LOW); // Second ring, go off-hook. Ring tone output connected to pin 2 on the Arduino to trip interrupt. It goes low with rings ... }

/* ======== this is the interrupt function call ======= */ void offHook() { rings++; Serial.println(); Serial.print("Incoming rings: "); Serial.println(rings); if(rings == 2) { analogWrite(OH, 0); // Place a low on Off-Hook optical relay to close circuit rings = 0; // Reset rings for next time a call comes in detachInterrupt(0); //Without this line, the code stalls here after doing the analogWrite (Off-Hook LED comes on), but code does not continue. //With this line, the code works fine until the session is over and back On-Hook ready for the next LOW to trip the interrupt. // The interrupt fires twice, because the printout counts rings correctly. Once it reaches 2 the detachInterrupt(0) // breaks back to code as desired, but interrupt never works again in this session. // I've tried adding another attachInterrupt(0,offHook,LOW); statement in the code // before completing a cycle. I've tried adding it in the interrupt function after the detachInterrupt line, and I've tried to // use the noInterrupts(), interrupts() commands to try to revive this interrupt. The only thing that works is a reboot. } } // end interrupt function

This appears to be a Catch-22. You have to use detachInterrupt to get the function to release back to code, but once done, the only recourse is to pass through the setup() function again on reboot.

There must be a simple answer to this, since any programmer needs this functionality. Or a software reset would work. It tried that also and the only way I can control the "reset" pin is through a relay to ground. Any Arduino pin used to go from high-to-low and back high just sets off an endless loop of resets.

In a word: HELP

J. Wolf


I've discovered my error. One must declare variables used in an interrupt callback as "volatile" also can't use the delay statement inside the callback function. Once I corrected these things, the code worked fine.

LargoLobo: I too have this problem. My code is much simpler, so maybe this will help: (code fragments)

Serial prints don't work inside ISRs and any variables that have there value changed inside an ISR need to be declared volatile.

Unless one wants to specifically learn about interrupts, my suggestion is to leave them alone until their theory of operation is fully understood. Instead of asking why a particular ISR doesn't work or stalls, it's much better to describe the problem one is trying to solve and ask for help about how to solve it. Chances are interrupts won't be needed in most cases.

LargoLobo: I too have this problem. My code is much simpler, so maybe this will help: (code fragments)

Your problem is caused by a combination of calling Serial.print from an ISR, and using a level-triggered interrupt without removing the source of the interrupt in the ISR. When you exit the ISR, the ring signal will still be low; so the ISR will be re-entered. All those serial prints will fill up the serial buffer, which causes the Serial.print call to block, and it will never return because the serial buffer can't be emptied until interrupts are re-enabled.

So you need to do 2 things:

  1. Remove the Serial.print calls from the ISR. Instead, set a flag inside the ISR. In loop() watch for the flag to be set; when it is set, do the Serial.print calls and clear it.

  2. Use interrupt mode FALLING instead of LOW.

The problem is solved by properly addressing the variable name as "volatile" per requirements for an interrupt. I'm not sure why it works for a while and then decides not to. Either the compiler drops the variable, because it doesn't show up in the code as being used or doesn't... Seems like it records the variable, but later decides it was changed and that's a bad thing and stops using it. Maybe the compiler actually registers it as Static. I don't know, but all is well if it is declared "volatile."

I sometimes just do a delayMicroseconds(1000) inside the ISR to debounce buttons if it’s not a really time-criticle tasks, 1ms is acceptable delay.

not really power-efficient, tho, you waste 1ms in busy-loop.

void buttonInterrupt()
{
  detachInterrupt(0); // disable interrupts to disallow nested interrupt
  delayMicroseconds(1000);

  // do button handling stuff here

  attachInterrupt(0, buttonInterrupt, LOW);
}

I think it's a bad idea to detach/attach interrupts inside the ISR. You won't get nested interrupts anyway unless you re-enable interrupts inside the ISR, and doing that is best avoided. A more professional solution to the problem you are trying to solve is to use an edge-triggered interrupt (i.e. mode FALLING instead of LOW), and to record the time at which the interrupt occurred. You can do this by calling micros() within the ISR and storing the returned value. Then in the ISR you can do nothing if not enough time has elapsed since the last interrupt. I agree that in simple systems with very little else going on (e.g. no serial I/O), calling delayMicroseconds inside the ISR may be an inelegant but simple way of debouncing.

However, it is generally simpler to handle pushbuttons by polling, except in the case where the button is used to wake up the mcu from power down mode. In that case, I use the interrupt only to wake up the mcu, and poll it the rest of the time.

dc42: I think it's a bad idea to detach/attach interrupts inside the ISR. You won't get nested interrupts anyway unless you re-enable interrupts inside the ISR, and doing that is best avoided. A more professional solution to the problem you are trying to solve is to use an edge-triggered interrupt (i.e. mode FALLING instead of LOW), and to record the time at which the interrupt occurred. You can do this by calling micros() within the ISR and storing the returned value. Then in the ISR you can do nothing if not enough time has elapsed since the last interrupt. I agree that in simple systems with very little else going on (e.g. no serial I/O), calling delayMicroseconds inside the ISR may be an inelegant but simple way of debouncing.

However, it is generally simpler to handle pushbuttons by polling, except in the case where the button is used to wake up the mcu from power down mode. In that case, I use the interrupt only to wake up the mcu, and poll it the rest of the time.

edge triggered interrupt is not really acceptable because it doesn't wake the device up from sleeping.

polling is not really energy efficient, you're doing stuff that can be done in hardware with software.

Palatis: polling is not really energy efficient, you're doing stuff that can be done in hardware with software.

There is nothing at all wrong with doing in software what can be done in hardware, that is what microcontrollers are all about. If the mcu is running at full power anyway then energy efficiency doesn't come into it. I've already said that I use an interrupt where I want to wake up the mcu from power down mode.