Interrupt driven program only executes once

Hi all,

First time poster with a question. I have written a program and it's failing to execute how I had hoped. It only executes either openDoor() or ISR(ANALOG_COMP_vect) once and then requires a reset to run again or run the other routine. I must be missing something somewhere in my code... any suggestions?

//PIN DECLARATIONS
// this constant won't change:
const int relayPinClose = 14;       // the pin that the close relay is attached to
const int relayPinOpen  = 15;    //the pin that the open relay is attached to

//VARIABLES
volatile long delta_t;          //used for determining if rotor is rotating

//PROTOTYPES
void doorOpen(void);
int getrpm(void);


void setup() {
  //pins to control door latch motor
  pinMode(relayPinOpen, OUTPUT);
  pinMode(relayPinClose, OUTPUT);
  
  //make sure we're not opening/closing the latch
  digitalWrite(relayPinOpen,0);
  digitalWrite(relayPinClose,0);  
  
  //setup external interrupts
  //attachInterrupt(0,doorLockDisable,HIGH); //used later on - but it is being used -DON'T FORGET
  attachInterrupt(1,openDoor, FALLING);
  
  //setup Analog comparator
  ACSR = 
        (0<<ACD)   |   //analog comparator: enabled
        (0<<ACBG)  |   //analog comp bandgap select: AIN0 is positive input
        (1<<ACIE)  |   //analog comp interrupt: enabled
        (0<<ACIC)  |   //analog comp input capture: disabled
        (1<<ACIS1) | (0<<ACIS0);   //analog comp interrupt mode: rising
  DIDR1 = (1<<AIN1D) | (1<<AIN0D);  //disable digital input buffer (saves power)
  
  //setup interrupt for PCINT1
  PCICR = (0<<PCIE2) | (1<<PCIE1) | (0<<PCIE0);  //enable pins PCINT14..8 for pin change interrupt
  PCMSK1 = 
          (0<<PCINT14) |
          (0<<PCINT13) |
          (0<<PCINT12) |
          (0<<PCINT11) |
          (1<<PCINT10) | //enables PCINT10 (ADC2 pin 25) as external interrupt
          (0<<PCINT9)  |
          (0<<PCINT8);    
}



void loop() {
}

//when the open button is pressed the door will open if the system says it's safe
void openDoor()
{
  static unsigned long last_interrupt_time=0;
  unsigned long interrupt_time = millis();
  
  //if interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    
    //if time between rotor pulses is less than 1000ms - door safe to open
    //if(delta_t > 1000)
    //{
        digitalWrite(relayPinClose,0); //make sure we don't short the motor
        digitalWrite(relayPinOpen, 1);
        delay(200);
        attachInterrupt(0,doorLockDisable, HIGH);
    //}
  }
  
  last_interrupt_time = interrupt_time;
}

//when the door is closed turn the motor on to lock it closed
ISR(ANALOG_COMP_vect)
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  
  //if interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    digitalWrite(relayPinOpen,0); //make sure we don't short motor
    digitalWrite(relayPinClose, 1); //writes the output of the analog comp
    
    delay(200); //wait for lock switch to close (dual purpose switch)
    attachInterrupt(0,doorLockDisable, HIGH);  //enable the doorLocked interrupt
  }
  
  last_interrupt_time = interrupt_time;
}

//when the door is fully locked/unlocked (as indicated by the switch) disable
//the motor
void doorLockDisable()
{
  digitalWrite(relayPinOpen,0);
  digitalWrite(relayPinClose, 0);
  detachInterrupt(0);
}

ISR(PCINT1_vect)
{
  //determine time between pulses 
  static long last_time;
  long this_time;
  
  //get the current micros count
  this_time = millis();
  
  //time between pulses
  delta_t = this_time - last_time;
  
  //set last time
  last_time = this_time;
  
}
void openDoor()
{
...
        delay(200);

You will not be able to call delay in your interrupt service routine. Remove this line of code.

ISR(ANALOG_COMP_vect)
{
...
    delay(200); //wait for lock switch to close (dual purpose switch)

Ditto.

It looks like you will end up with a race condition between openDoor and PCINT1_vect.

As far as I can tell both openDoor and ANALOG_COMP_vect fail to perform their intended task if there IS a bounce or the human quickly presses the button twice. In other words, I believe your de-bounce strategy is flawed.

Why do you want to use interrupts for this application? I suspect it would be MUCH easier without using interrupts.

Yes I completely missed the delay issue in the routines. Thanks.

I don't see why there could be a race condition between those two routines. PCINT1_vect determines the time between edges of a set of pulses - then when the doorOpen routine runs it checks to make sure the time (or rather will - it's commented out atm) between the pulses is greater than a specified amount before unlocking the door.

If you meant there would be a problem between the doorOpen and ANALOG_COMP_vect (the door close routine) then I can see where I might have a problem with each routine fighting each other. The ANALOG_COMP_vect is triggered off a light sensor and the doorOpen button is triggered off a manual pushbutton - the debouncing should take care of any bouncing (and fighting) that might occur when the door is opening.

I choose interrupts to allow the immediate triggering of the latch. I thought it would be more straightforward for this type of situation. The buttons are only used intermittently.

I don't see why there could be a race condition between those two routines. PCINT1_vect determines the time between edges of a set of pulses - then when the doorOpen routine runs it checks to make sure the time (or rather will - it's commented out atm) between the pulses is greater than a specified amount before unlocking the door.

How will the Sketch behave if the pulses stop? Say there's a loose wire? Or the motor locks? Or the motor never starts?

I choose interrupts to allow the immediate triggering of the latch.

Interrupts have a considerable amount of overhead. The more "immediate" triggering will come from a Sketch that avoids interrupts. You will be better served to use Blink Without Delay as the model.

I thought it would be more straightforward for this type of situation.

When interrupts are involved the solution is rarely straightforward. For example: By using interrupts you are giving up the ability to debug your Sketch.