Seeeduino interrupt not working

Hey there, I'm working on an OLED timer that utilizes a rotary encoder and a button to change to different states to execute the reset, set time, and start time functions. I built it out on my Arduino Uno because it's a little easier to work with. And it works PERFECTLY. But now I'm wanting to shrink it down to work out the physical aspects of it and I've loaded everything onto the Seeeduino Xiao and the button interrupt feature no longer works. I've double (triple) checked the wiring, everything is 1 for 1 exactly the same. I even tried all new components, wires, breadboard, and a different Seeeduino board.

Does anyone have any experience working with these boards? Is this a common issue? Seeeduino claims that all pins can be used for an interrupt.
I have been tinkering with it for several days and I'm at my wit's end.
I'm a sporadic "maker" and know enough to be dangerous. Any help is greatly appreciated!

Here's my code:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

int Buzzer = 8;
int minutes_change=0;
int minutes=0;
int Current_Frame=1;

int buttonPin = 3;

const int ledPin =  LED_BUILTIN;

//encoder pins and variables
int clkPin = 7;
int dtPin = 6;

int encoderCount = 0;
int clkPinLast = LOW;
int clkPinCurrent = LOW;

// State values: 
//0 =reset
//1 =setup
//2 =countdown

int State=0;
long Timestamp_Button_Pressed;

unsigned long Countdown_start;

// Declaration for SSD1306 display connected using software SPI 
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//Images:
// 'TIMES_UP', 128x32px
const unsigned char TIMES_UP [] PROGMEM = {
0xdf, 0xff, 0xff, 0xef, 0xef, 0xef, 0xff, 0xf7, 0xf7, 0xf7, 0xf7, 0xff, 0xfb, 0xfb, 0xfb, 0xfb, 
0x8f, 0xcf, 0xcf, 0xc7, 0xc7, 0xc7, 0xe7, 0xe7, 0xe3, 0xe3, 0xe3, 0xf3, 0xf3, 0xf1, 0xf1, 0xf1, 
0xcf, 0xcf, 0xcf, 0xcf, 0xc7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf1, 0xf9, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0x38, 0x7e, 0x3c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0x38, 0x7c, 0x3c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0x38, 0x7c, 0x3c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0x38, 0x3c, 0x3c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x38, 0x38, 0x1c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x38, 0x38, 0x1c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x38, 0x38, 0x1c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x38, 0x38, 0x1c, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x38, 0x10, 0x1c, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x38, 0x10, 0x1c, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x30, 0x10, 0x1c, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x30, 0x10, 0x1c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x30, 0x00, 0x1c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x30, 0x80, 0x1c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x30, 0x82, 0x1c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x30, 0x82, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x30, 0xc2, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x30, 0xc6, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0x78, 0xe7, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
0xcf, 0xcf, 0xcf, 0xcf, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf1, 0xf9, 
0x8f, 0xcf, 0xcf, 0xc7, 0xc7, 0xc7, 0xe7, 0xe7, 0xe3, 0xe3, 0xe3, 0xf3, 0xf3, 0xf1, 0xf1, 0xf1, 
0xdf, 0xdf, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xfb, 0xfb, 0xfb, 0xfb
};

//Functions:

//Timer start:
void Press_B_Button(){
  if (millis() - Timestamp_Button_Pressed>200){
    if (State==1){//add minutes mode
      Countdown_start=millis();
      State=2; //start countdown mode
      digitalWrite(ledPin, HIGH);
    }
    else{//if state is 2(count) then go to state 1(add minute) and "minutes"=0
      State=0;//reset mode
      delay(2000);
      Serial.println((String)"Button B Press");      
    }
  }
}

void Ring_Bell(int Frame =0){
  display.clearDisplay();
    int analogValue = analogRead(A0);
    if (analogValue<=50){
    display.clearDisplay();
    display.invertDisplay(true);
    }
    else{
    display.clearDisplay();
    display.invertDisplay(false);
    }

  if (Frame==1||2||3||4)display.drawBitmap(0,0,TIMES_UP,128,32,1);
  display.display();
  if (Frame>1){
    delay(200);
    digitalWrite(Buzzer,LOW);
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(Buzzer,HIGH);
    digitalWrite(ledPin, LOW);
    delay(1000); 
  }
}

//Current time function
String CurrentTime(unsigned long MsLeft){
  String Result;
  int M;
  int S;
  M=(long)MsLeft/60000;
  Serial.print(MsLeft);
  Serial.print(";");
  Serial.println(M);
  if (M<10) Result=(String)"0"+ M + ":";else Result=(String)M+":";
  S=(long)((MsLeft-M*60000)/1000);
  if (S<10) Result=(String)Result + "0"+ S ;else Result=(String)Result +S;
  return Result;
}

//////////////////////////// 
void setContrast(int contr){
    int prech;
    int brigh; 
    switch (contr){
      case 000 ... 255: prech= 0; brigh= contr; break;

      default: prech= 16; brigh= 255; break;}
      
    display.ssd1306_command(SSD1306_SETPRECHARGE);      
    display.ssd1306_command(prech);                            
    display.ssd1306_command(SSD1306_SETCONTRAST);         
    display.ssd1306_command(brigh);                           
}


void setup() {

  attachInterrupt(digitalPinToInterrupt(3), Press_B_Button,RISING);

//Encoder pin setup:
  pinMode(clkPin, INPUT);
  pinMode(dtPin, INPUT);

//Button pin setup:
  pinMode(buttonPin, INPUT); //init button pin to input
  pinMode(ledPin, OUTPUT); // initialize the LED pin as an output: 
  
  Timestamp_Button_Pressed=millis();

//Buzzer pin setup:
  pinMode(Buzzer, OUTPUT);
  digitalWrite(Buzzer, LOW);
  int Frame =0;
  
  //OLED Pin setup:
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3c
  Serial.begin(9600);

  display.clearDisplay();
  display.display();
}


void loop() {
 //Set contrast level
  int analogValue = analogRead(A0);// variable resistor adjusts OLED brightness
  if (analogValue <=600){
  setContrast(analogValue);
  }


  //////////////////Reset//////////////////////////
  if (State==0){//reset state
    digitalWrite(Buzzer,LOW);
    digitalWrite(ledPin, LOW);
    minutes = 0;
    display.invertDisplay(false);
    display.clearDisplay();
    display.setTextSize(2);            
    display.setCursor(5,0);
    display.setTextColor(SSD1306_WHITE);
    display.println((String)minutes+" min");
    display.display();
    State=1;
  }

  ////////////////////Encoder////////////////////////
  if (State==1){//set time mode

   clkPinCurrent = digitalRead(clkPin);
    if ((clkPinLast == LOW) && (clkPinCurrent == HIGH)) {
      if (digitalRead(dtPin) == HIGH) {
        if(minutes<=0){ //don't count below 0
        minutes=0;      // 
        }               //
        else {
        minutes=minutes-1;//decrease minutes
        }
      }
      else {
      minutes=minutes+1;//increase minutes
      }
      display.clearDisplay();
      display.setTextSize(2);            
      display.setCursor(5,0);
      display.setTextColor(SSD1306_WHITE);
      display.println((String)minutes+" min");
      display.display();
      Serial.println(minutes);
    }
      clkPinLast = clkPinCurrent;
  }

  ///////////////////////countdown/////////////////////////////
  if(State==2){
    if(minutes*60000 >(millis()-Countdown_start)){
      display.clearDisplay();
      display.setCursor(5,0);
      display.setTextSize(4);            
      display.setTextColor(SSD1306_WHITE);
      display.println(CurrentTime((minutes*60000-(millis()-Countdown_start)))); 
      display.display();
    } 
    else {
     Ring_Bell(Current_Frame); 
     Current_Frame=Current_Frame+1;
     if (Current_Frame==5) Current_Frame=1;
    }
  }
}

What if you move the pinMode(3, INPUT) before the attachInterrupt?

:man_facepalming: Thank you so much! That worked!

Great! The reason I suspected that this might help (now that I'm at a real keyboard) is that the SAMD chips have something called a "PINMUX setting" that is used to control which function a particular pin will "present." Normally this is relatively obvious - GPIO vs USART vs Timer output.
But it turns out that "GPIO" and "GPIO that can generate an interrupt" are also different settings, and I guessed that pinMode() would just change the setting to "GPIO", and attachInterrupt() would be responsible for changing the setting. So my calling pinMode() later, it undoes what attachInterrupt() has done.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.