Solved. Multiple Pins Firing Interrupt (Argon)

Hi there,

I have 3 tactile buttons going to separate input pins- A1, A2, A3. Using a Particle Argon.

When the code digital reads all three buttons, and prints when HIGH, everything works as expected. Each button prints separately when they are pressed.

When the code has 3 interrupts for each of the 3 buttons, all of the interrupt callbacks are called regardless of which button is pressed.

When I comment out 2 of the interrupts, pressing any of the 3 buttons still results in that 1 interrupt firing and the callback being called.

This is not the expected behaviour, because each individual button works for polling, but the buttons do not work individually for interrupts.

Is there something that I did wrong? Any ideas on how to fix this?

Hi Erin,
I think someone will ask to see your code.
I’m just anticipating them :wink:
Cheers

2 Likes

Polling button test:

#include "Board.h"

void setup() {
    Serial.begin(9600);
    pinMode(PLAY_PIN, INPUT);
    pinMode(REV_PIN, INPUT);
    pinMode(FWD_PIN, INPUT);
}

void loop() {

    if(digitalRead(PLAY_PIN) == HIGH) {
        Serial.println("play");
    }
    
    if(digitalRead(REV_PIN) == HIGH) {
        Serial.println("rev");
    }
    
    if(digitalRead(FWD_PIN) == HIGH) {
        Serial.println("fwd");
    }
    
    delay(100);

}

Interrupt button test:

#include "Boards.h"

uint8_t button_pins[] = { PLAY_PIN, REV_PIN, FWD_PIN };
volatile uint8_t button_val[] = { 0, 0, 0 };
volatile uint8_t prev_button_val[] = { 0, 0, 0 };
volatile long button_debounce_start[] = { 0, 0, 0 };
enum buttons { PLAY, REV, FWD };

void buttonCallback(uint8_t i);
void playButtonCallback();
void revButtonCallback();
void fwdButtonCallback();


void setup() {

    Serial.begin(9600);

    // pin init
    pinMode(PLAY_PIN, INPUT);
    pinMode(REV_PIN, INPUT);
    pinMode(FWD_PIN, INPUT);
    
    // interrupt init
    attachInterrupt(PLAY_PIN, playButtonCallback, RISING);
    attachInterrupt(REV_PIN, revButtonCallback, RISING);
    attachInterrupt(FWD_PIN, fwdButtonCallback, RISING);

}

void loop() {

    for(uint8_t i=0; i<3; i++) {
        if(button_val[i] == 1) { // 1 set from interrupt callback
            Serial.print(millis());
            Serial.print(" button val = 1: ");
            Serial.println(i);
            button_val[i] = 0; // reset val
        }
    }

}



// callback from interrupt functions
void buttonCallback(uint8_t i) {
    //Serial.print("button callback: ");
    //Serial.println(i);
    if(button_val[i] == 0) { // only set the time if the flag was cleared
        button_debounce_start[i] = millis();
        button_val[i] = 1;
    }
}

void playButtonCallback() {
    buttonCallback(PLAY);
}

void revButtonCallback() {
    buttonCallback(REV);
}

void fwdButtonCallback() {
    buttonCallback(FWD);
}

Boards.h

#define KNOB_PIN      A0
#define PLAY_PIN      A1
#define REV_PIN       A2
#define FWD_PIN       A3
#define FREE_PIN      A4
#define DIP1_PIN       2
#define DIP2_PIN       3
#define DIP3_PIN       4
#define LED1_PIN       5   // right hand side. for step. has pwm. 
#define STEP_PIN       6
#define DIR_PIN        7
#define LED2_PIN       8   // left hand side. for direction. has pwm.

Ah! Beat me to it by 20 seconds! :slight_smile: The code is posted in the previous comment now.

2 Likes

I guess you have no external pull-resistors in place.
In that case you should use INPUT_PULLDOWN to prevent the pins from floating when no button is pressed (for digitalRead() too).

BTW, your button_debounce_start should be unsigned long - although you don’t seem to be using it for debouncing :wink:

Hello,

Thanks for having a look.

In that case you should use INPUT_PULLDOWN to prevent the pins from floating when no button is pressed (for digitalRead() too).

I have changed the pinMode to this:

pinMode(PLAY_PIN, INPUT_PULLDOWN);
    pinMode(REV_PIN, INPUT_PULLDOWN);
    pinMode(FWD_PIN, INPUT_PULLDOWN);

It did not solve the problem for the interrupts.

I guess you have no external pull-resistors in place.

There are 1k ohm pull down resistors for each button on the pcb. There is also a 0.1 uF cap for hardware debouncing for each button on the pcb.

BTW, your button_debounce_start should be unsigned long - although you don’t seem to be using it for debouncing :wink:

Button debouncing is in the full system code :wink:

The problem still exists

Maybe your enum declaration is missing an = 0 before being used as int?
This is what I would try after reading a bit:

enum buttons { PLAY = 0, REV, FWD };

1 Like

Can you show us your wiring? (diagram and hi-res photo)

BTW, when I try your interrupt code with my Argon and a mere push button closing to 3v3 it works as expected.

slightly altered code

#define B_ISR_NAME(_para) isr_ ## _para
#define B_ISR(_para) void B_ISR_NAME(_para) (void){ buttonCallback(_para); }

uint8_t button_pins[] = { PLAY_PIN, REV_PIN, FWD_PIN };
volatile uint8_t button_val[] = { 0, 0, 0 };
volatile uint8_t prev_button_val[] = { 0, 0, 0 };
volatile long button_debounce_start[] = { 0, 0, 0 };
enum buttons { PLAY, REV, FWD, btnCount };
char btnName[btnCount][12] = { "PLAY", "REV", "FWD" };

void buttonCallback(uint8_t i);
B_ISR(PLAY);
B_ISR(REV);
B_ISR(FWD);

void setup() {
    Serial.begin(9600);

    // pin init
    pinMode(PLAY_PIN, INPUT_PULLDOWN);
    pinMode(REV_PIN, INPUT_PULLDOWN);
    pinMode(FWD_PIN, INPUT_PULLDOWN);
    
    // interrupt init
    attachInterrupt(PLAY_PIN, B_ISR_NAME(PLAY), RISING);
    attachInterrupt(REV_PIN , B_ISR_NAME(REV ), RISING);
    attachInterrupt(FWD_PIN , B_ISR_NAME(FWD ), RISING);
}

void loop() {
    for(uint8_t i = 0; i < btnCount; i++) {
        if(button_val[i]) { // 1 set from interrupt callback
            Serial.printlnf("%s pressed\t(%lu)", btnName[i], millis());
            button_val[i] = 0; // reset val
        }
    }
}

// callback from interrupt functions
void buttonCallback(uint8_t i) {
    //Serial.print("button callback: ");
    //Serial.println(i);
    if(!button_val[i]) { // only set the time if the flag was cleared
        button_debounce_start[i] = millis();
        button_val[i] = 1;
    }
}
2 Likes

The issue comes back to: it works as expected for polling, but does not work as expected for interrupts.

For me it works both ways so it hasn't got anything to do with the code nor the Argon's default behaviour.
Consequently the next step would be to investigate the specifics of your HW setup.
Hence the above request for a hi-res photo of your setup.

Check out my comment above where I sent the photos of the setup as requested

Tore everything apart to test on a breadboard. Confirmed hardware problem. 1k ohm likely too weak. My interrupt code runs fine.

1 Like

@ScruffR Check out this comment. (The one that this comment is replying to.)

My code works. Hardware problem. Thanks for the help anyway.

I had seen that, but experience has taught me that a schematic often lacks the physical details of the actual setup :wink:

3 Likes

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