Erratic behavior whit push button and attachInterrupt() function

Hi all,

I have some trouble with the use of push buttons and interrupt function and I don’t understand why sometimes it’s working and sometimes not. I suspect the breadboard I use to be the source of the problems but I’m not sure. Attached is the circuit diagram and I use different value of zener voltage because that’s all I had available (like 8.2V, 150V and 200V).

And the code I write :

#include "Arduino.h"
#include "SoftwareSerial.h"


const int bleuPin = 22; 
const int vertPin = 24; 
const int jaunePin = 26;  
const int rougePin = 32; 
const int blancPin = 28; 
const int noirPin = 30; 

const int interruptPin = 21;


volatile unsigned long button_time = 0;
int debounce = 50; // debounce latency in ms

volatile int trigger = 0;




void setup() {
  
  pinMode(bleuPin, INPUT_PULLUP);
  pinMode(vertPin, INPUT_PULLUP);
  pinMode(jaunePin, INPUT_PULLUP);
  pinMode(rougePin, INPUT_PULLUP);
  pinMode(blancPin, INPUT_PULLUP);
  pinMode(noirPin, INPUT_PULLUP);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), detect_interrupt, FALLING);


  
}

void loop() {
  if (trigger != 0){
    

    if (trigger == 1){
     action 1;
    }

      
    if (trigger == 2) {
      action 2;
    }

    
    if (trigger == 3) {
     action 3;
    }


    if (trigger == 4) {
      if (count_pause == 1){action 4;}
      if (count_pause == 2){action 5; count_pause = 0;}  
    }


    if (trigger == 5) {
      action 6;
    }


    if (trigger == 6) {
      action 7;
    }
 }
}

void detect_interrupt() {
  if (button_time > millis()) return;
  delayMicroseconds(32000);
  if (!digitalRead(bleuPin)) trigger = 1;
  if (!digitalRead(vertPin)) trigger = 2;
  if (!digitalRead(jaunePin)) trigger = 3;
  if (!digitalRead(rougePin)) {trigger = 4; count_pause++;}
  if (!digitalRead(blancPin)) trigger = 5;
  if (!digitalRead(noirPin)) trigger = 6;
  button_time = millis() + debounce;
}

action X is actually only a analogWrite() with different value.

Is there anything wrong with my code or my wirring which could explain why it doesn’t work ?
Should I actually use diode with 5V zener voltage ?

Thank a lot for your help guys !

It's working and sometimes not.

What does 'working' and 'not working' mean? What should it do? What does it do instead?

What are all the diodes for?

By working I mean action attached to the button pushed is launched and sometimes not.

Zener diodes are for putting to the ground only the digital pin attached to the pushed button and the interrupt pin.

Zener diodes are for putting to the ground only the digital pin attached to the pushed button and the interrupt pin.

I don't understand that. Why do you think you need them? Why do you think you need an interrupt pin for several buttons? Why do you think the diodes should be zener diodes?

I need only one interrupt pin for simplicity because each of my buttons must trigged an interrupt. Then, depending on the button I press, digital pin attached drop to the ground while other pins wired in parallel must stay at +5V to determine which action the µC should execute.

Hope this is clear !

Edit: I guess diodes could be regular instead of zener, but I only have zener.

I need only one interrupt pin for simplicity because each of my buttons must trigged an interrupt.

This is a common subject on these forums, so I did some tests. I connected a simple, cheap push to make button to a resistor and a power supply and connected an oscilloscope across the button. With quick presses I typically measured a closed time for the button of around 150ms or more, with a bounce time of around 125μs. Maybe different people using different buttons will get different times, but I’ll go with what I have.
In detecting a button press you are looking for an event that lasts at least 150ms, this is an absolute age in terms of processor time. If you program is not getting completely round its loop in 10ms or less then you need to be asking why, and looking to either improve the code or using a faster processor. To be sure you are dealing with bounce you need to check the button input at least twice per press event; the first time you see it’s pressed, the second time you see it’s still pressed so you act on the press. 3 checks would be even better. So, given that a button press lasts at least 150ms, even if your code is rather slow and takes 50ms per loop, it is still going to be able to check the button input at least twice per loop, possibly 3 times.
An interrupt is what you use when you need something to be dealt with faster than your loop time. If you have an event that cannot wait 5ms or 10ms or 50ms or however long your loop takes THEN you use an interrupt. However, an interrupt is steeling time from your loop, so an interrupt has to be over and done very quickly, preferably in a time period measured in microseconds and quite possibly in less than the 125μs bounce I measured with my cheap button. Maybe another button will have even longer bounce. You should not have an interrupt taking this amount of time away from the loop. An interrupt is the wrong tool for button inputs and if you use an interrupt to detect and de-bounce a button press you are asking for trouble.

You can find a tutorial for de-bouncing at de-bounce tutorial, or you can try the code I have included below.

/* Simple button debounce for 4 buttons. Increments a count and sends the updated count to the serial monitor once per button press */
/* Tested on an Uno */
/* Connect simple push to make buttons between 0V and pin 2, 0V and pin 3, 0V and pin 4 and between 0V and pin 5 */

#define noOfButtons 4     //Exactly what it says; must be the same as the number of elements in buttonPins
#define bounceDelay 20    //Minimum delay before regarding a button as being pressed and debounced
#define minButtonPress 3  //Number of times the button has to be detected as pressed before the press is considered to be valid

const int buttonPins[] = {2, 3, 4, 5};      // Input pins to use, connect buttons between these pins and 0V
unsigned long previousMillis[noOfButtons];  // Timers to time out bounce duation for each button
uint8_t pressCount[noOfButtons];            // Counts the number of times the button is detected as pressed, when this count reaches minButtonPress button is regared as debounced 
uint8_t testCount[noOfButtons];             //Test count, incremented once per button press

void setup() {
  uint8_t i;
  uint32_t baudrate = 115200;
  Serial.begin(baudrate);
  Serial.println("");
  Serial.print("Serial port connected: ");
  Serial.println(baudrate);
  for (i = 0; i < noOfButtons; ++i) {
    pinMode(buttonPins[i], INPUT_PULLUP);
    Serial.print("Testcount ");
    Serial.print(i);
    Serial.print(" = ");
    Serial.println(testCount[i]);
  }
}

void loop() {
  debounce();
  delay(10);     //Your other code goes here instead of this delay. DO NOT leave this delay here, it's only for demonstration.
}

void debounce() {
  uint8_t i;
  unsigned long currentMillis = millis();
  for (i = 0; i < noOfButtons; ++i) {
    if (digitalRead(buttonPins[i])) {             //Input is high, button not pressed or in the middle of bouncing and happens to be high
        previousMillis[i] = currentMillis;        //Set previousMillis to millis to reset timeout
        pressCount[i] = 0;                        //Set the number of times the button has been detected as pressed to 0
      }
    else {
      if (currentMillis - previousMillis[i] > bounceDelay) {
        previousMillis[i] = currentMillis;        //Set previousMillis to millis to reset timeout
        ++pressCount[i];
        if (pressCount[i] == minButtonPress) {
          ++testCount[i];
          Serial.print("Button ");
          Serial.print(i);
          Serial.print(" testcount = ");
          Serial.println (testCount[i]);
        }
      }
    }
  }
}

I don't see where is the point of your post since in my code boucing effect is take into account. But thank for the code, I'll try it with my application and see if it's work properly.

delayMicroseconds(32000);

Read the documentation on delayMicroseconds

Currently, the largest value that will produce an accurate delay is 16383.

ISR's should execute very rapidly. What is the reason for such a large delay within the ISR? The suspension of interrupts for the extended period of the ISR is likely to lead to problems.

I don't see where is the point of your post since in my code bouncing effect is take into account.

Unless I misunderstood you think you need interrupts for reading button presses, you don't, as per my explanation. You also don't need the diodes. If that's not why you have the diodes and the interrupts then I don't understand what they are there for.

Hi , Ops diag. |500x349 What are the diodes for?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png? (Not a Fritzy!!)

Tom... :)