[Update - SOLVED: See post from 2023-01-07 with solution. -Mark ]
Hi All,
Does anybody know of anything special with the MKR Zero related to using attachInterrupt? Details of my problem are below.
I'm trying to use attachInterrupt on a MKR Zero. As detailed below, either the code is stuck in a loop calling the ISR forever (even if the interrupt pin is hardwired to Vcc yet pinStatus is set to look for LOW). Or, the code does continue but the ISR is not called later when the pin goes low (when pinStatus=FALLING is used). Scenarios are driven by which pinStatus parameter is used.
Do note, in my circuit, I have a pull-up resistor on the wire attached to pin 1 digital. Voltage measures 3.7v at rest, and drops to 0.5v when the button connected to said wire is pressed.
The following code loops forever calling the ISR, even if the pin is hardwired to Vcc. Note use of PinStatus LOW. Also, a digitalRead test in the ISR confirms the pin is normally HIGH. So, why was the interrupt called?
extern void checkOffButton();
#define REQUEST_PIN 1
...
pinMode(REQUEST_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(REQUEST_PIN), checkOffButton, LOW);
// ISR checkOffButton() is called continuously, forever
The following code does not cause ISR to be called, ever.
extern void checkOffButton();
#define REQUEST_PIN 1
...
pinMode(REQUEST_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(REQUEST_PIN), checkOffButton, FALLING);
//Next line is reached and execution continues. But ISR never called.
The following DOES work. So, I'm going back to my original code to see if I'm calling the attachInterrupt() more than once.
Here's my test#2.
I have a second Mkr Zero. Nothing is attached at this time (except the USB cable). I have a jumper wire going from Vcc to pin 1 digital.
Here is the code I'm running.
#include <Arduino.h>
#define THE_PIN 1
void checkButton() {
Serial.println(F("In checkOffButton()")); // Serial does work in interrupt subroutine.
Serial.print(F("digitalRead="));
(digitalRead(THE_PIN)==LOW) ? Serial.println(F("LOW")) : Serial.println(F("HIGH"));
if (digitalRead(THE_PIN) == LOW) {
Serial.println(F("Button was pressed!"));
}
}
void setup() {
Serial.begin(9600);
while (!Serial)
delay(1000);
pinMode(THE_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(THE_PIN), checkButton, LOW); // LOW, HIGH, FALLING, RISING
}
void loop() {
Serial.println("Back in loop");
delay(1000);
}
With the jumper wire connected to VCC I see:
Back in loop
If I connect the jumper wire to GND, I see (as expected):
In checkOffButton()
digitalRead=LOW
Button was pressed!
In checkOffButton()
digitalRead=LOW
Button was pressed!
(Side note: Yes, even though it is documented Serial.print() requires an interrupt and hence shouldn't work in the ISR, it does work.)
I originally had a SPI TFT connected to my MKR Zero. I added an interrupt so when I pressed a button the interrupt was called. This worked fine.
I disconnected the interrupt when I switched to a parallel TFT while getting the TFT to work. When I added the interrupt back, I found I could use the TFT, or the interrupt, but not at the same time.
Note #1: you most likely want to use pinStatus mode = FALLING to call your interrupt service routine (ISR) one time, not continuously, as the button is pushed/held.
I thought there was a conflicting interrupt on the pin (I was using pin 1 digital), or some library was forcing pin 1 low. Neither was the case.
The issue turned out to be, each time I wrote to the parallel TFT, I was (re)setting the pin modes to OUTPUT for the TFT-used pins (digital pins 2 through 9), and to INPUT for the interrupt-used pins. The problem was, calling
pinMode({interrupt-pin}, INPUT_PULLUP)
after attachInterrupt() caused the interrupt to be cancelled/removed.