Arduino Forum

Using Arduino => General Electronics => Topic started by: Kuusou on Sep 08, 2019, 09:47 pm

Title: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 08, 2019, 09:47 pm
I was hoping that someone on these forums could double check my schematic to ensure this will work properly on my PCB.

I'm trying to debounce/deglitch three buttons using a schmitt trigger and rc circuit. I'm using a 74HC14. My question is, can I use R5(10k resistor) for all three buttons as a pull up resistor or does each button need to have its own? The image is rather small but that resistor is running to the 5v supply. I normally had the buttons attached to the trinket and used its built in pullup resistors but since I have to run through the 74HC14 on this design I can't use that feature. I just want to be sure that using this design will give me the desired result before I order the pcb's and wait several weeks for them to get here only to find I've made a mistake somewhere.

My other question is whether this rc circuit will have enough filtering to debounce the button or should I change the resistor or cap values to adjust the time? Thanks for your time!


(https://i.ibb.co/p3zMGJK/2019-09-08-14-54-16-Window.jpg)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 08, 2019, 09:59 pm
Do I need to say more?
(https://forum.arduino.cc/index.php?action=dlattach;topic=635278.0;attach=323734) (https://forum.arduino.cc/index.php?action=dlattach;topic=635278.0;attach=323734)

but since I have to run through the 74HC14 on this design I can't use that feature.
Why? Who's giving you that awkward requirement?
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 08, 2019, 10:07 pm
I'm just trying to follow this schematic
(https://i.ibb.co/yBv9dGq/proper-debouncing-sch.png)

I'm not sure what the highlighted red line means exactly, sorry i'm rather new to all this so i'm sorry if that's a stupid question.

No one is giving me that req, just that my understanding is that it needs to run through a schmitt trigger to properly debounce it and i'm not sure how i would use the pullup resistors on the trinket with this set up.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 08, 2019, 10:10 pm
I'm just trying to follow this schematic
Why? Just connect it to the Arduino :)

I'm not sure what the highlighted red line means exactly, sorry i'm rather new to all this so i'm sorry if that's a stupid question
It shows a connection which is made when the "bright" button is pressed. Do you want that connection ;)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 08, 2019, 10:16 pm
Why? Just connect it to the Arduino :)
Well before the buttons were attached to the trinket but I need to properly debounce/deglitch them using hardware. I'm aware of button debouncing in software but that's not an option for me. The buttons trigger interrupts within my software and as a result I'm not able to properly debounce them so i'm trying to use a hardware solution instead.


It shows a connection which is made when the "bright" button is pressed. Do you want that connection ;)
I see what you're saying, so in this case I'd need each button to have its own resistor to avoid that.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 08, 2019, 10:21 pm
So this should resolve that issue correct?

Is it possible to connect the buttons to the arduino and use the internal resistors and still get the debounce effect from the schmitt trigger???

(https://i.ibb.co/tDzHPK4/2019-09-08-16-19-43-Easy-EDA-A-Simple-and-Powerful-Electronic-Circuit-Design-Tool.jpg)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 08, 2019, 10:24 pm
The buttons trigger interrupts within my software
Now there is your problem ;) We humans push the buttons. We humans are dead slow. Interrupts are for fast things. Aka, an interrupt is ALWAYS* the wrong choice for a button ;)

I see what you're saying, so in this case I'd need each button to have its own resistor to avoid that.
Correct, classic newbie brain fart ;) Don't blame you, made them in the past as well.

But it also shows to me you don't have a real clue why you do this. So my suggestion, drop the interrupt, just poll and debounce in software, saves you the hardware and easier to change :)

PS Also, don't be evil and draw GND down. Only evil people drop it upwards ;)


* With the exception if it needs to wake the uC from sleep.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 08, 2019, 10:32 pm
Now there is your problem ;) We humans push the buttons. We humans are dead slow. Interrupts are for fast things. Aka, an interrupt is ALWAYS* the wrong choice for a button ;)
Correct, classic newbie brain fart ;) Don't blame you, made them in the past as well.

But it also shows to me you don't have a real clue why you do this. So my suggestion, drop the interrupt, just poll and debounce in software, saves you the hardware and easier to change :)

PS Also, don't be evil and draw GND down. Only evil people drop it upwards ;)


* With the exception if it needs to wake the uC from sleep.
I'm aware this probably looks like the XY problem.

I'm aware of the fact that its bad practice to use interrupts with buttons and have read a lot about it at this point. However my particular case (i need you to trust me on this) I need to have the interrupts attached to the buttons. A hardware solution is the only one I have. My program has some 13 different looping functions that I need to be able to switch between whenever a button is pressed. I was unable to find a better solution than to use interrupts and no one on this forum was able to help point me in another direction, other than to refer me to blink without delay, which didn't help me in my case or at least make me understand a better way to do it. At this point my program is already written and a hardware solution is the much easier option.

In this case, is my schematic as laid out as well as It can be?

Hahaha I wasn't aware evil people did that! I'll have to avoid that in the future
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 08, 2019, 10:37 pm
(i need you to trust me on this)
Sorry, I just can't ;) To me it points to a design flaw elsewhere ;)

One thing I'm missing, the 100nF for the chip itself! ;) Every chip wants a decoupling cap close by. Besides that and the evilness it should work.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 08, 2019, 10:41 pm
One thing I'm missing, the 100nF for the chip itself! ;) Every chip wants a decoupling cap close by. Besides that and the evilness it should work.
I'm not sure I following you on this. What do you mean? Is the 100nF too weak? Wrong type of cap?
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 08, 2019, 10:44 pm
Noting to do with the current caps, but something that applies for all chips, they want a 100nF ceramic cap over the power rail close by (aka, right next to the IC) so they have a clean power supply :)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 08, 2019, 10:51 pm
Noting to do with the current caps, but something that applies for all chips, they want a 100nF ceramic cap over the power rail close by (aka, right next to the IC) so they have a clean power supply :)
So something like this?
(https://i.ibb.co/3pvsvWc/2019-09-08-16-48-00-Easy-EDA-A-Simple-and-Powerful-Electronic-Circuit-Design-Tool.jpg)

attached like C4?
(https://i.ibb.co/L9pBXj2/2019-09-08-16-48-58-Easy-EDA-A-Simple-and-Powerful-Electronic-Circuit-Design-Tool.jpg)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: raschemmel on Sep 09, 2019, 12:38 am
Yeah, it's close on the schematic but he means physically close to the IC, as close as possible.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 09, 2019, 01:00 am
Yeah, it's close on the schematic but he means physically close to the IC, as close as possible.
I've been reading up on that, looks like my schematic above is slightly wrong though because the cap should go to ground.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: raschemmel on Sep 09, 2019, 02:22 am
Correct.
I didn't notice that it was connected to Vcc.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: runaway_pancake on Sep 09, 2019, 03:52 am
(http://i270.photobucket.com/albums/jj118/new_clear_days/e_chopper/btnckt01.jpg)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 09, 2019, 03:57 am
(http://i270.photobucket.com/albums/jj118/new_clear_days/e_chopper/btnckt01.jpg)
I'm not sure what I'm looking at here, is this the same concept but cutting out the extra resistors and doing a 20k instead of 2 seperate 10k's?
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: runaway_pancake on Sep 09, 2019, 04:41 am
What you're looking at is a circuit that I've actually used. Each Schmitt output goes to an input pin, but they also get diode OR'd before the INTerrupt pin. Any button-push results an interrupt where the sketch then determines which switch it was.
I used this to control a motor [increase/decrease PWM or Stop]. 
(I added a fail-safe in the sketch where two or more would stop the motor.)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 09, 2019, 05:52 am
I'm not sure I know how to recreate that. This is the final schematic that I have at this moment. I've got my PCB designed as well. Are there any changes I could make to this design to make it more efficient or component/space saving?

(https://i.ibb.co/y6TPqys/2019-09-08-23-50-07-Easy-EDA-A-Simple-and-Powerful-Electronic-Circuit-Design-Tool.jpg)

Thank you all for your time and help btw!
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: 6v6gt on Sep 09, 2019, 06:12 am
Even if you must use interrupts to handle button presses, maybe because you use delay() statements in your sketch and you need to "jump" over these, you can still use simple  software debouncing.
In the interrupt service routine, on a valid call, simply set a timer, say:
static uint32_t  isrLastCalledAtMs = millis() ;

However, if too little time has elapsed since the last valid call and the current call ( say less than 100mS ) then ignore the call because it is a bounce.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 09, 2019, 08:19 am
@Kuusou, yeah, like that, OVER the supply :) And important, on the actual layout they must be physically close to the chip.

And like runaway_pancake also showed, no real need for R1, R3 and R5.

And you are still drawing GND evil. Okay, a little less evil but still ;) Just flip all the caps! Then the GND can be down and in line! Room enough to do so. And all switches can easily share the GND that way. Same for C1 to C3. I would even have used pins 1-2 on the switch to go to GND just to make it all look way better.

@runaway_pancake, is it just me or am I really missing a pull down in that design?
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: runaway_pancake on Sep 09, 2019, 02:11 pm
@runaway_pancake, is it just me or am I really missing a pull down in that design?

Where?
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 09, 2019, 02:38 pm
On that INT pin. Nothing is ever pulling it low.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: wvmarle on Sep 09, 2019, 03:19 pm
However my particular case (i need you to trust me on this) I need to have the interrupts attached to the buttons. A hardware solution is the only one I have. My program has some 13 different looping functions that I need to be able to switch between whenever a button is pressed.
That's calling for a state machine, with buttons changing between the states. No interrupts needed, assuming you have done your programming properly. It sounds like debouncing is also not needed - if say button2 switches to loop2, bouncing doesn't matter as you're in loop2 already after the first contact is made. Debouncing is only needed when you have to count button presses.

I may be missing something, but that's basically what you're telling here. So all you need is buttons - no caps, no resistors (use the internal pull-ups), no Schmitt trigger.

So yeah, XY problem.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: runaway_pancake on Sep 09, 2019, 06:56 pm
On that INT pin. Nothing is ever pulling it low.

Is that required? It's designated 'RISING' in the sketch, I think that takes care of it.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 09, 2019, 08:24 pm
Yes, it's required :) It only looks for a rising edge, it does nothing to the state of the pin. Just like on any other input, just letting it float WILL include pick up noise thus it will include a rising edge.

You might get away with it because of reverse leakage current through the diodes. But that's in the order of 5 to 10nA for a 1N4148 @ 5V (aka, at best). Times three that might be enough to keep the pin at a LOW state but I would not count on it. Add some noise and you have a trigger for sure.

May I do A wild guess? You said you've used this design. Is the first thing you do in the ISR to check which of the normal pins fired the interrupt? So any false triggering can be hidden by that if you don't see a HIGH pin on those :-X If so, I think you fire that interrupt way more often then you think ;)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: MarkT on Sep 09, 2019, 09:09 pm
On that INT pin. Nothing is ever pulling it low.

Is that required? It's designated 'RISING' in the sketch, I think that takes care of it.
Absolutely required, you must never have an undefined input on an interrupt enabled pin, it might fire all the time from capacitive pickup.  With your circuit it might never fire as it stays HIGH all the time, or fire continuously, or only at the weekend, whatever.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 09, 2019, 10:56 pm
@Kuusou, yeah, like that, OVER the supply :) And important, on the actual layout they must be physically close to the chip.

And like runaway_pancake also showed, no real need for R1, R3 and R5.

And you are still drawing GND evil. Okay, a little less evil but still ;) Just flip all the caps! Then the GND can be down and in line! Room enough to do so. And all switches can easily share the GND that way. Same for C1 to C3. I would even have used pins 1-2 on the switch to go to GND just to make it all look way better.
Ok so remove resistors 1, 3, and 5 and replace resistors 2, 4, and 6 with a 20k. Make the caps/switches all share a ground. So how does this look?

(https://i.ibb.co/Jxnv9tx/2019-09-09-17-02-35-Easy-EDA-A-Simple-and-Powerful-Electronic-Circuit-Design-Tool.jpg)

The other thing I should mention is part of the problem I believe is button glitching, where i'm pressing the button and on release its registering multiple presses, these circuit are suppose to debounce at 1ms but is that enough? It seems to me that I should make the caps larger so as to increase the debounce time to avoid this issue. Does anyone have any thoughts on this? In programming it seems the normal is 50ms debounce but does follow over to hardware debounce?
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 09, 2019, 11:12 pm
That's calling for a state machine, with buttons changing between the states. No interrupts needed, assuming you have done your programming properly. It sounds like debouncing is also not needed - if say button2 switches to loop2, bouncing doesn't matter as you're in loop2 already after the first contact is made. Debouncing is only needed when you have to count button presses.

I may be missing something, but that's basically what you're telling here. So all you need is buttons - no caps, no resistors (use the internal pull-ups), no Schmitt trigger.

So yeah, XY problem.
This was my setup before but when the buttons are pressed they sometimes skip functions in the sequence on release, so its registering multiple interrupts extremely quickly. I've tried to debounce them in software but nothing seems to work.

My program has roughly 14 different LED functions. The PCB has three switches for effect, color, and brightness. Using interrupts I can switch between any looping function without delay or change the color or brightness at any point and it works great (except for this button issue). I had tried other programming but there was always an extremely bad delay on the button presses since the function would be looping. I'm also new to programming and self taught so while there may be a better way to do this its the only way i've been able to find that works. I've posted about this on these forums before but as I said, I would just get referred to blink without delay and honestly just couldn't figure it out. I have no idea how to have 14 looping functions within a loop and how to poll for buttons in such a way that they can be responsive. :(
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 09, 2019, 11:40 pm
Also another question I have is when designing the PCB do the individual components have to have traces between their GND connecting them or can they all just be left as is? My first PCB I just covered both sides of the PCB in copper as the grounding layer and that seemed to work just fine. I didn't have any ground traces.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Qdeathstar on Sep 10, 2019, 12:02 am
To be honest it sounds like you have coding issues...


I controlled 1600 leds with 30 different programs while also monitoring button presses and controlling a character lcd screen and had no need for interrupts...
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 10, 2019, 12:10 am
To be honest it sounds like you have coding issues...


I controlled 1600 leds with 30 different programs while also monitoring button presses and controlling a character lcd screen and had no need for interrupts...
As I said before, I'm new to coding and self taught. There are probably better ways to do it but I have no idea how and haven't been able to figure out a better way...

I'm using switch statements for the effects, color, and brightness. The issue is that some of the led effects run for a long time and I can't wait for the loop to finish before exiting and going to the next function/color/brightness

The only thing I can think of is using a interrupt to run every 5-10ms with a timer. It would constantly check for the state of the buttons and if a button has been pressed longer than 50ms then it could increment a counter for the button and switch the effect.

Is this something that could work, would the constant interrupt be noticeable in terms of a particular led effect running? If it is I'm not sure how to exit the function at the time its a valid press without waiting for it to finish. Does anyone have any thoughts or suggestions on this? Is this a better approach?
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: runaway_pancake on Sep 10, 2019, 02:21 am
@septillion, @MarkT
I understand your point, makes sense, I'm nodding in agreement.
But I aver that I've never had an instance (in several years now) where I had a failure to dec/inc or stop nor any inadvertent dec/inc or stop.
I pulled the box off the bike, to see if I'd placed a pulldown without noting it, but it has none. Maybe I'm lucking out on the ragged edge.

@Kuusou - Sorry for the... controversy.

FWIW
Code: [Select]
byte newLevel = 0;       // comparison
byte Accel_Btn = 4;      // alias - Accelerate btn
byte Decel_Btn = 5;      // alias - Decelerate btn
byte Zeropwr = 6;        // alias - "kill" button
byte motorpin = 11;      // pin alias, PWM to gate/MOT
byte Level [6] = {0,20,40,100,175,250};
volatile boolean Detect = false;  // Interrupt Note

void setup()
{
  pinMode(motorpin, OUTPUT);
  pinMode(Zeropwr, INPUT);
  pinMode(Accel_Btn, INPUT);
  pinMode(Decel_Btn, INPUT);
  //Serial.begin(9600);
  attachInterrupt(0,Activity,RISING);  // '0' means Ext_Int on D2
}

void loop()
{
  if (Detect == true)
  {
    Decode();
  }
  if (currentLevel != newLevel)
  {
    analogWrite(motorpin,Level[speed_idx]);
    currentLevel = newLevel;
  }
}

void Activity()   // this is the Interrupt !
{
  Detect = true;
}

void Decode()
{
  Detect = false;          // clear out "Detect"
  if (digitalRead(Zeropwr) == HIGH)
  {
    speed_idx = 0;
    newLevel = 0;
    //Display_it();
  }
  else if (digitalRead(Accel_Btn) == HIGH)
  {
    Accelerate();
  }
  else if (digitalRead(Decel_Btn) == HIGH) // Activity detected wasn't Zeropwr or Accel_Btn
  {
    Decelerate();   // default = (A' & Z')
  }
}

void Accelerate()

  if (speed_idx < 5)
  {
    speed_idx ++;
  }
  newLevel = Level[speed_idx];
}

void Decelerate()
{
  if (speed_idx >= 1)
  {
    speed_idx --;
  }
  newLevel = Level[speed_idx];
}


Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 10, 2019, 03:39 am
Ok guys, i'm trying to change my code to use the watchdog timer interrupt to check the state of my buttons every 15ms. What i'm trying to do is that every 3 interrupts (45ms) if the button in question is still in a high state then the effect will change and execute just like my old code. The issues is i'm getting crazy flashing off my leds, it appears to be rapidly changing the effects but i'm not touching the button.

Here is the code in the ISR i'm using. I'm sure my logic is flawed somewhere but just not sure where.

Code: [Select]
ISR (WDT_vect) {
  if (digitalRead (EFFECT_BUTTON) == HIGH ) {
    effect_count++;
  } else if (digitalRead (EFFECT_BUTTON) == LOW ) {
    effect_count == 0;
  }
  if (digitalRead (EFFECT_BUTTON) == HIGH && effect_count >= 3) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("jmp 0"); // force reset of micro controller at line 0
  }
}
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: wvmarle on Sep 10, 2019, 04:00 am
You are doing some really crazy, scary, and outright wrong things there.

For starters, the wrong things happen when you hold that button for longer than three WDT intervals - you continue to count after your reset.

That reset is simply the wrong way of doing things.

What you need is state change detection to count (so count when your button GOES down, not when it IS down as you're doing).

I have no idea what you're doing in the various routines or how you even call them so can't comment on that, really.

Your loop() may look a bit like this:

Code: [Select]

uint32_t lastPressed;
bool previousButtonState;
const uint8_t NPROGRAMS = 3;
uint8_t selectedEffect;

void loop() {
  if (digitalRead(EFFECT_BUTTON) == LOW) { // button is pressed
    if (previousButtonState == HIGH) { // but it was not
      previousButtonState = LOW;
      selectedEffect++; // increase the count.
      if (selectedEffect== NPROGRAMS) {
        selectedEffect= 0;
      }
      EEPROM.put(0, selectedEffect);
    }
      lastPressed = millis(); // record when it happens.
  }
  else if (millis() - lastPressed > 50) { //  Button is unpressed, and it's at least 50 ms since it last got pressed
    prevousButtonState = HIGH;
  }
  switch (selectedEffect) { // Select program.
    case 0:
      effects0();
      break;

    case 1:
      effects1();
      break;

    case 2:
      effects2();
      break;
  }
}


Now as long as you make sure those effectsn() functions return fast you don't need an interrupt, and you can count properly without crazy things like a reset - where did you even find that routine?
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: wvmarle on Sep 10, 2019, 04:04 am
And another thing: you're not allowed to use delay() until you know why that is.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 10, 2019, 04:18 am
And another thing: you're not allowed to use delay() until you know why that is.
You can't use delay in an ISR because it will screw up your time keeping and everything will be thrown off correct?


I see why my LEDS were acting that way. I'm idiot and had my states wrong. Low is when its pressed, not high.

I'm using the reset as a way to exit the function. Many of these functions aren't fast and this is a way to go back to 0, reset all my stuff, use EEPROM to figure out the effect for the switches, and go into the next effect. I see what you're saying though, holding down the button causes rapid switching through the effects.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: wvmarle on Sep 10, 2019, 04:29 am
You can't use delay in an ISR because it will screw up your time keeping and everything will be thrown off correct?
Never even thought of using delay() in an ISR, that's double bad. An ISR should return as fast as possible.

Delay is blocking. Nothing happens during delay. No button reads, nothing. That's why. Write your code without delay() or other blocking loops and you can return to loop() hundreds or many thousands of times a second to read that button.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: jremington on Sep 10, 2019, 04:33 am
Quote
You can't use delay in an ISR because it will screw up your time keeping
No, the Arduino will instantly freeze until you push the reset button.

delay() requires the interrupts to be running so that millis() runs, and those are turned off in an interrupt.

Really, learn to program without using interrupts. For beginners, interrupts create many more problems than they solve.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 10, 2019, 04:59 am
Never even thought of using delay() in an ISR, that's double bad. An ISR should return as fast as possible.

Delay is blocking. Nothing happens during delay. No button reads, nothing. That's why. Write your code without delay() or other blocking loops and you can return to loop() hundreds or many thousands of times a second to read that button.
That's the issue then, almost all of these led functions have a delay in them to get the desired effect, hence why i'm going this route.

 
I think I see the solution thanks to you. Using the WDT to increment a counter I can use a conditional statement like you've done to check and make sure the button has remained unpressed those 3 cycles and if it has then make the desired change.


Code: [Select]
if (wdt_counter == 0 || wdt_counter < 3) { // 45ms debounce delay
    wdt_counter++;
  } else if (wdt_counter > 3) {
    wdt_counter = 0;
  }





Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: wvmarle on Sep 10, 2019, 05:08 am
Still the wrong approach. #35 was not about ISRs.

Get rid of ALL those delay() calls, use millis() based timing and finite state machines instead. delay() is another major cause of problems - like you're experiencing.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 10, 2019, 06:33 am
This code works in that it reacts to button presses, only issue is holding down the button causes it to cycle through. I'm trying to apply the concept you were talking about, counting how long the since the button has been pressed, not counting while its pressed.

Code: [Select]
ISR (WDT_vect) {
  if (digitalRead (EFFECT_BUTTON) == LOW ) {
    effect_count++;
  } else if (digitalRead (EFFECT_BUTTON) == HIGH ) {
    effect_count == 0;
  }
  if (digitalRead (EFFECT_BUTTON) == LOW && effect_count >= 3) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("jmp 0"); // force reset of micro controller at line 0
  }
}






This is my attempt at that, but for some reason I can't get the logic to work out....what am I missing? When I push the button nothing happens. I know from the previous code though that the interrupt every 15ms is enough time to be responsive to the presses I just can't figure out what in this code is preventing this from working. I'm pulling my hair out at this point. If I can just get this section of code to work i'll be finished with the program  :smiley-confuse:
Code: [Select]
ISR (WDT_vect) {
  if (digitalRead (EFFECT_BUTTON) == LOW ) {
    previousButtonState == LOW;
    effect_count = 0;
  }

  if (digitalRead (EFFECT_BUTTON) == HIGH && previousButtonState == LOW ) {
    effect_count++;
  }

  if (digitalRead (EFFECT_BUTTON) == HIGH && effect_count >= 3) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("jmp 0"); // force reset of micro controller at line 0
  }
}
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 10, 2019, 06:42 am
It appears just changing

Code: [Select]
if (digitalRead (EFFECT_BUTTON) == LOW ) {
    previousButtonState == LOW;
    effect_count = 0;
  }


to this

Code: [Select]
if (digitalRead (EFFECT_BUTTON) == LOW ) {
    previousButtonState == LOW;
    effect_count++;
  }


in the code above solved the issue....but I don't understand why...
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 10, 2019, 06:54 am
Code: [Select]
ISR (WDT_vect) {
  if (digitalRead (EFFECT_BUTTON) == LOW ) {
    effect_count++;
  }

  if (digitalRead (EFFECT_BUTTON) == HIGH && effect_count >= 5) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("jmp 0"); // force reset of micro controller at line 0
  }
}


This code appears to be working perfectly but i'm not sure as to why...my guess is that 15ms as a rate of the interrupt and 3-5 cycles of that is a "sweet spot" in terms of how long a button is typically pressed down by a human. So because the controller is resetting each time those conditions are met and returning the counter to zero its in effect debounced/deglitched....
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Smajdalf on Sep 10, 2019, 07:21 am
No, the Arduino will instantly freeze until you push the reset button.
Are you sure? IIRC on Arduino Uno delay() with disabled interrupts generates shorter delay than expected. It polls for Timer0 Overflow Flag for some reason I don't remember and when the flag is not cleared by the ISR it keeps subtracting from the requested delay length. Or maybe delay() calls millis() which polls the flag?

@OP: In your last schematic you removed the WRONG set of resistors. Pressing a button will short Vcc to GND. Not a good design.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Kuusou on Sep 10, 2019, 07:27 am
@OP: In your last schematic you removed the WRONG set of resistors. Pressing a button will short Vcc to GND. Not a good design.
Thanks for catching that. Luckily it looks like I'll be able to avoid the need for the hardware debounce altogether!

Thanks to everyone for the help on this issue, you guys are great!
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 10, 2019, 09:22 am
So how does this look?
Way clearer! 8)

[edit]But indeed, as I typed/read on, Smajdalf is right, you left R1, R3 and R5 and removed the others :p[/edit]

where i'm pressing the button and on release its registering multiple presses, these circuit are suppose to debounce at 1ms but is that enough?
So you still have bounce with this circuit?

It seems to me that I should make the caps larger so as to increase the debounce time to avoid this issue.
Or the resistor for that matter.

Does anyone have any thoughts on this? In programming it seems the normal is 50ms debounce but does follow over to hardware debounce?
Why not? Bounce is bounce. I once saw an article about it and I think most switches where below 1ms.  And only one or so passes the 10ms mark. Bounce2 for example uses 10ms (by default) which should cover most switches. But you might have that unlucky type which can bounce >10ms.

I've tried to debounce them in software but nothing seems to work.
Then you must be doing something wrong.... 14 led functions sounds pretty easy. I would say, just grab a library like Bounce2.

My first PCB I just covered both sides of the PCB in copper as the grounding layer and that seemed to work just fine. I didn't have any ground traces.
Depends on the signal, but usually fine. But it's better to do use separated traces for high current tracks. That way they don't influence other components (by shifting their voltage a bit).

NOTE: at this point I noticed it's not just 2 - 3 replies I missed but 2 pages.... So hold on, it's going to be a write as I read kind of post!

@runaway_pancake: Like I said, is the first thing you do when the interrupt fires to check which pin caused it? Because if that's the case you will indeed not get any random inc/dec but the interrupt is probably firing away quite a lot.

@ Kuusou  Wait, what? Now you're even dragging the watch dog in? :o

Code: [Select]
asm volatile ("jmp 0"); // force reset of micro controller at line 0
What the.... Must say, seeing the must ugly code at the start of the day is refreshing... Even didn't finish my coffee yet! :D

Let me guess, the rest of your code is full of delay()'s? If so, that's where you went wrong ;)

For beginners, interrupts create many more problems than they solve.
AMEN!

Luckily it looks like I'll be able to avoid the need for the hardware debounce altogether!
But please please please, don't use interrupts or the WDT for that! That's just different lipstick on a pig!

The real fix is pretty simple, remove all delay()s! ;) And see it as a lesson learned, NEVER EVER use delay() (in a real program) ;)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: GolamMostafa on Sep 10, 2019, 11:21 am
I have assumed that that you are triggering INT0/INT1 interrupt at the falling edge of the incoming interrupting signal. I would think to employ the following hardware non-retriggerable one shot circuit instead of time delay to over come the bouncing times of the interrupting device. For more details, see this post (https://forum.arduino.cc/index.php?topic=635101.msg4299931#msg4299931).
(https://forum.arduino.cc/index.php?action=dlattach;topic=635101.0;attach=323594)

Functional Description: When K1 is closed at time t1, the signal-A goes LOW and then after a while the bouncing of the button begins which lasts for about 25 ms before the button makes the final sit. At the very first low-going edge of signal-A (at time t1), the signal-B assumes HIGH state and remains HIGH during the whole bouncing times of K1 (because 74LS221 is a non-retriggering one shot, it does not  respond to the bouncing transitions of K1). At time t2, the signal-B makes a transition from HIGH to LOW; as a result, the MCU is interrupted only once. The pulse width of signal-B (tw) is about: 0.7*R1*C1 = 0.7*4.7x103*10*10-6 ~= 33 ms (>25 ms).
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: septillion on Sep 10, 2019, 11:47 am
Or, just do it all in software ::)
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: GolamMostafa on Sep 10, 2019, 11:58 am
Or, just do it all in software ::)
It is definitely possible. There is a Debounce.h library; but, there are relative merits and demerits as to the use of hardware or software to overcome the bouncing times of the button -- a mechanical switch.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: wvmarle on Sep 10, 2019, 02:50 pm
I for one can't see any advantage to the hardware solution - especially not one as convulated as proposed in #47 - except when using interrupts (required if you want a button press to wake from sleep). And then a small capacitor is usually enough.

Another place I needed hardware debounce is with an encoder, as the library apparently doesn't handle bounce at all. A small cap was all that's needed to make the encoder behave properly.

Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: GolamMostafa on Sep 10, 2019, 03:08 pm
If the following one is a typical behavior of a mechanical switch, then you want to claim that the small capacitor (usually 0.1 uF) is going to absorb all those jitters and keep the line at HIGH (or LOW) state at least for 20 ms?
(https://forum.arduino.cc/index.php?action=dlattach;topic=635101.0;attach=323596)

There are some cases (especially in the firing fields) one demands that the firing pulse should be only for once and guaranteed; the Engineer does not go for any risk; he straight uses the non-retriggerable one-shot circuit that guarantees only one firing pulse in spite of hundreds of to-and-fro movements of the triggering switch.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: wvmarle on Sep 10, 2019, 03:28 pm
If the following one is a typical behavior of a mechanical switch, then you want to claim that the small capacitor (usually 0.1 uF) is going to absorb all those jitters and keep the line at HIGH (or LOW) state at least for 20 ms?
Taking care of the bounce, easy. The button press discharges the cap very fast (it basically shorts it out); the pull-up resistor takes almost 1xRC to reach a logic "high" level (guaranteed at 0.6 * Vcc on an ATmega - in 1x RC the cap charges to about 0.7 * Vcc). RC is 3 ms for a 100nF cap and the typical 30 kΩ value for the internal pull-ups, 5-6 times longer than the total time you mention, while the cap gets discharged every time the contacts make during that bounce period. In fact I found that to debounce a mechanical encoder 100 nF is too big, if you rotate it fast (by hand!) you miss pulses simply because the cap doesn't allow the voltage to go up enough.
For a human pressed button, it'd be quite hard to ask that human to produce a press shorter than 20 ms. No need for external circuits for that. Sure for some very specific applications you may want to guarantee that you record a press even if you have a superhuman pressing the button super short, and you care less about the added cost in hardware & PCB space.
Even so if you have so short button presses (i.e. pulses) to worry about and your code is too slow (20 ms is a very long time for a single iteration of loop()), add that cap to debounce your button and guarantee a single pulse, and then connect an interrupt to your button to guarantee you don't miss the pulse. That's what interrupts are for.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: GolamMostafa on Sep 10, 2019, 03:31 pm
Cool reading. (+).

(The natural behavior of a mechanical switch/button is such that when pressed, it makes a contact for a while and then starts bouncing which lasts for about 20 ms before it makes the final sit at the closing position. If the button is connected with an interrupt pin, it has to be ensured that the interrupt-pin receives only one active pulse out of these bouncing.)  
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: 6v6gt on Sep 10, 2019, 10:40 pm
Cool reading. (+).

(The natural behavior of a mechanical switch/button is such that when pressed, it makes a contact for a while and then starts bouncing which lasts for about 20 ms before it makes the final sit at the closing position. If the button is connected with an interrupt pin, it has to be ensured that the interrupt-pin receives only one active pulse out of these bouncing.)  
Of course the filtering of these bounces could also happen later. That is in the interrupt service routine.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: GolamMostafa on Sep 11, 2019, 03:45 am
Of course the filtering of these bounces could also happen later. That is in the interrupt service routine.
You wanted to say that let the MCU be interrupted at the very first falling edge that happens at time t1 (Fig-1) following the closure of the interrupting device (the button).
(https://forum.arduino.cc/index.php?action=dlattach;topic=635278.0;attach=323985)
Figure-1:

The ISR is very very short, and it usually contains only one line to set a flag like:
Code: [Select]
void ISRINT0()
{
    flag1 = true;
}


My intuition is this: before we start the process of filtering out the bounce pulses (by software delay or whatever may be) after arriving at the ISR, the ISR is done; the MCU returns to the main line program; the MCU is again interrupted by the next bounce pulse. There are multiple interrupts which we don't want to happen. The solution is to make an arrangement (either by software or by hardware) in such a way so that the MCU receives only one falling edge (the interrupting signal) at time t2 (Fig-1) from the button out of many bounces. That means that we have to crate a fence to block the 20 ms bouncing time , which is effectively built using oneshot circuit (Fig-2) by the Electronics Enthusiasts.  
(https://forum.arduino.cc/index.php?action=dlattach;topic=635278.0;attach=323987)
Figure-2:
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: wvmarle on Sep 11, 2019, 04:04 am
There are multiple interrupts which we don't want to happen.
That's one of the key reasons we don't want to use interrupts for button presses.

The next problem, if you just set a flag to true: in your main loop() you then have to check for the flag, clear it, and still subsequently ignore the flag being set for some time due to possible button bounce! So all you do is ADD the complexity of an interrupt while you STILL have to do software debouncing.

Quote
The solution is to make an arrangement (either by software or by hardware) in such a way so that the MCU receives only one falling edge (the interrupting signal) at time t2
The capacitor solution gives a single falling edge at t1, which is the only guaranteed one (how do you know which of the bounces is the last one? Buttons are not even guaranteed to bounce), after which you simply ignore new triggers for some time - 20-50 ms typically, a time that's long for a button's bouncing but short for a human operator.
Title: Re: Debouncing multiple buttons using schmitt trigger
Post by: Smajdalf on Sep 11, 2019, 07:08 am
If an interrupt and SW debounce is needed simply disable it in the ISR and enable it after the button is released again. You may use the enable bit instead of the SW flag.