Interrupts won't re-enable

Thanks for taking a look!

Hardware for this project is a Nano, but if different hardware would make this easier, I’m open to suggestions.

The desire on this sketch is to have two buttons, the first one pressed will light an LED, and disable the other button. A 3rd button will re-enable the buttons.

Everything works, except for the re-enable part - I see the button press, and an LED blink confirms it’s in the part of the code to re-enable, but the buttons don’t come active.

I’ve tried cli()/sei() and attach/detach interrupts, neither of which worked out well, generally gave compile errors due to hardware.

Thanks for your input, I appreciate it.

Code Below:

#define EI_ARDUINO_INTERRUPTED_PIN
#include <EnableInterrupt.h>
#include <avr/power.h>

#define D10 13
#define D11 14
#define D12 15

void blink13(int len){
  digitalWrite(13, HIGH);   
  for (int x=1; x<len; x++){
    delay(1000);                   //  Gets ignored for some reason
  } 
  digitalWrite(13, LOW); 
}

void interruptFunction() {
  switch(arduinoInterruptedPin){
  case 13:  
    //  Reset Button pressed
    enableInput();
  break;
  case 14:  
    // Player 1 Wins!
    disableInput();
    blink13(100);
  break;
  case 15:  
    // Player 2 Wins!
    disableInput();
    blink13(100);
  break;
  
  default:
    blink13(10);
  break; 
  }
}

void setup() {
   clock_prescale_set(clock_div_1);
   pinMode(D10, INPUT_PULLUP);  //  Reset
   pinMode(D11, INPUT_PULLUP);  //  Player 1
   pinMode(D12, INPUT_PULLUP);  //  Player 2
   enableInterrupt(D10, interruptFunction, CHANGE);
   enableInterrupt(D11, interruptFunction, CHANGE);
   enableInterrupt(D12, interruptFunction, CHANGE);
   digitalWrite(13, LOW);    // turn the LED off 
}

void enableInput(){
  digitalWrite(arduinoInterruptedPin, HIGH);
  blink13(50);
  //pinMode(D10, INPUT_PULLUP);  //  Reset     //Should be enabled already
  pinMode(D11, INPUT_PULLUP);  //  Player 1
  pinMode(D12, INPUT_PULLUP);  //  Player 2
  blink13(50);
  //enableInterrupt(D10, interruptFunction, CHANGE);  // Should be enabled already
  enableInterrupt(D11, interruptFunction, CHANGE);
  enableInterrupt(D12, interruptFunction, CHANGE);
  blink13(200);
}

void disableInput(){
// disableInterrupt(D10);    // Don't disable the Admin!
   disableInterrupt(D11);    // Disable Player1 
   disableInterrupt(D12);    // Disable Player 2
}

void loop() {
}

I can see problems.

In your ISR you call your blink13() function which in turn uses the delay() function. The delay() function uses interrupts but they are disabled whilst in an ISR

    delay(1000);                   //  Gets ignored for some reason

I am also somewhat bemused by

#define D10 13
#define D11 14
#define D12 15

What is that all about ?

As a matter of interest, why are you using interrupts for such a simple task ? In fact, as there is nothing in the loop() function what exactly is being interrupted ?

I am not familiar with the EnableInterrupt library but it looks like a complicated solution to a simple requirement.

Thanks for the reply!

That explains the delay - not a huge deal, and honestly, it was a quick-and-dirty way to blink the LED to see where I was in the sketch.

The #Define stuff corrects the physical pin to the logical name - Totally cosmetic, but aligns my head to the pin layout. :-)

The reason for interrupts is two-fold; it's something I've never done before, but see a lot of potential with, and this project is a prototype for a larger project. Wanted to get the small chunk working before trying to debug something larger.

Thanks again!

pin 13 ?? input or output?

The #Define stuff corrects the physical pin to the logical name - Totally cosmetic, but aligns my head to the pin layout.

It sounds like a way of confusing yourself, but each to their own

   pinMode(D10, INPUT_PULLUP);  //  Reset

etc is in great danger of seeming as if Arduino pin 10 is being defined as an output and

  enableInterrupt(D10, interruptFunction, CHANGE);

looks for all the World as though you are enabling an interrupt on Arduino pin 10.

I assume that the library uses pin change interrupts to enable more than 2 interrupts to be used and on pins other than the normal hardware interrupt pins.

Pin13 is only connected to the on-board LED, so it should be output.

The pinMode / enableInterrupt sequence was based on: https://github.com/GreyGnome/EnableInterrupt/blob/master/examples/AllPins328/AllPins328.ino (code snip is from that file)

#define setupInterrupt(x) \
  EI_printPSTR("Add pin: "); \
  EI_printPSTR(#x); \
  EI_printPSTR("\r\n"); \
  pinMode( x, INPUT_PULLUP); \
  enableInterrupt( x, interruptFunction##x, CHANGE)

As I understand it, it sets the pin HIGH; physically, the pin is wired to one side of a momentary switch, the other side is wired to GND. The pin goes LOW when the button is pressed, triggering the pin CHANGE that is detected. (Please correct me if this is wrong)

Take look of your code as you wrote it :

#define EI_ARDUINO_INTERRUPTED_PIN
#include <EnableInterrupt.h>
#include <avr/power.h>

#define D10 13
#define D11 14
#define D12 15

void setup() {
   clock_prescale_set(clock_div_1);
   pinMode(D10, INPUT_PULLUP);  //  Reset
   pinMode(D11, INPUT_PULLUP);  //  Player 1
   pinMode(D12, INPUT_PULLUP);  //  Player 2
   enableInterrupt(D10, interruptFunction, CHANGE);
   enableInterrupt(D11, interruptFunction, CHANGE);
   enableInterrupt(D12, interruptFunction, CHANGE);
   digitalWrite(13, LOW);    // turn the LED off
}

(I removed the non interesting part)

Here is as appear to the compiler after pre-processing :

void setup() {
   clock_prescale_set(clock_div_1);
   pinMode(13, 0x2); //  Reset
   pinMode(14, 0x2); //  Player 1
   pinMode(15, 0x2); //  Player 2
   enableInterrupt(13, interruptFunction, 1);
   enableInterrupt(14, interruptFunction, 1);
   enableInterrupt(15, interruptFunction, 1);
   digitalWrite(13, 0x0); // turn the LED off
}

(the file in my system (linux) is in /tmp/build[some_numbers]/preproc/ctags_target_for_gcc_minus_e.cpp , at the very end of the file)

Is more clear now?

Cheers, Ale.

Well....not really. The buttons attached to D11/D12 (14/15) work the first time, so I'm thinking that setup() is working.

When one of those buttons is pressed, disableInput() is called, and it looks like the other button is disabled.

Pressing D10 (13) calls enableInput(), the LED blinks, and it should run through enableInterrupt() for the D11/D12 (14/15) pins.

The problem is - at this point, pressing either of these doesn't do anything, it looks like the interrupt is still disabled.

Actually, your code in setup does :

  1. set pin 13 to input with pull-up
  2. digitalWrite(13, LOW) ; this (*) AFAIK just take the pull-up away

If you really mean to use a pin for input and output (and you can’t of course have it at the same time) you must esplicity change it with pinMode().

(*) I’m quite sure of the opposite, if you digitalWrite(x,HIGH) a pin in input mode you activate the pull-up.

Cheers, Ale.

I see where you're thinking now - let me rebuild that to use D9/12 instead of D10/13.