I like to test for a stable input. No need to guess at an ideal bounce period. Debounces on press or release of button. Here, I check for 40ms of stability representing 8 consecutive identical readings ...
Pushbuttons do not capriciously close their contacts unless going down, nor open them unless on the way up. Same with slide switches &c.
So there is no reason to delay 40 ms the recognition of either transition looking for stability.
If the switches and pushbuttons you use do misbehave in this way, I recommend getting better switches (!) or addressing what must be some other issue in the circuitry.
Unless you are looking to disallow a human input consisting of (in your view) too brief a press.
Like you want someone to really mean it. Which to me is odd. Buttons should work when you press them.
Sure, could easily use a shorter interval, but the interval is non-blocking, and a human just cannot react (or press a button) faster than ??? ms (try the test).
P.S. I wonder what interval the Arduino "debounce" example uses?
Having said all this, the code checks for stability ... the bounce time could be 100ms and as long as there's no stable period of 40 ms (5ms x 8 readings) while the contacts are bouncing, then the code return value will remain clean.
See above (or try the code). Very responsive, just please don't repeatedly press the button at a rate greater than 12.5Hz. Disclaimer: code is untested as I didn't have the time.
I noticed their encoder is perfect and have no bounce attribute. Of course we all know that there is no need to debounce a rotary encoder, so. Nevertheless, it would be nice if the encoder allowed s l o w l y t u r n i n g so all four phases of the quadrature signal would not fly by <click!> at once.
I suppose your trick could be used to examine the actual behaviour of the simukated encoder, or use the handy digital logic analyser that is available in wokwi that doesn't cost even $13.
Yes. Although we could wonder 'bout those knife switches that capriciously open and close by themselves... and I have no sympathy for anyone too lazy to use a real switch poking around with jumper wires! I think if the button was to launch the nuclear tipped misile, there'd probably be an argument for stability. Normally closed switches of some kinds have to be handled better, as you point out.
But it's software. No where in life is a general purpose anything the bast at all deployments, and no where else but software is the opportunity provided to easily supply the best solution on a use case by use case basis.
I've been abnormal all my life. One size fits all does not fit. Me. Libraries that have options up the wazoo (technical term there) can be hard to understand, often suck and take too much code space.
As for human reaction time, why add 40 ms to what is already an eternity of dozens if not hundreds? Besides noting that there is no reaction time involved when I go to press a button.
I see that this time I failed to mention that it was when working with musicians that I became very sensitive to how fast systems do (or do not) take action when requested.
If by
See above (or try the code).
you mean your clever "waiting for stability" code, I have used the technique and sure enough, it takes a predictable and excruciating N milliseconds to see a button go down. An eternity.
…please don't repeatedly press the button at a rate greater than 12.5Hz.
said the note on some thing I bought recently… not.
BTW thanks for linking this great paper, which I first saw on his website
Yes. I did some testing with both methods. I belong to the school that says you should register a switch closure immediately. When it is necessary to have a long debounce period, it's noticeable enough to be frustrating to a user, if the registration doesn't happen until after the time out. It's experienced as "sluggishness". Often the repetition rate will never be high, but this delay would still be noticeable if it's handled in that way. So you can have a really long debounce and nobody will think it's slow if the key press is reported immediately.
I once worked for a company, that had a lot of repair returns with bad keypads. The real problem was, the debounce was like that, the users became frustrated and pounded the membrane keys with pens, fingernails, and really hard, hoping to make it respond faster.
Also this whole thing about noise seems specious to me. Switches should not be producing noise when they are not active. If they are, there are some serious design problems that should be addressed before considering masking it with a debounce delay.
Yeah, I see the value of instant response (stopwatch, etc). Using the following code:
instant response (0 ms)
actual switch bounce time can be anything from 0 - 4294967295 ms with each contact "hit" or release (bounce) period lasting no longer than 40 ms.
example test: On an UNO, take a m/m jumper wire from pin 8 and rapidly touch the USB casing. There'll be no glitches in the printout (OFF-ON-OFF or ON-OFF-ON) sequences.
Ah: Need mechanism to pass defines to library cpp files
-- you can't use #define LIBRARY_CONDITIONAL in your sketches to control the compilation of the library referenced with the #include <library.h>. If you muck with the Bounce2.h file, you could enable the BOUNCE_LOCK_OUT behavior of Bounce2, but you can't control it from the sketch.
The Bounce2 library documentation is modified to reflect the need to modify the global Bounce2.h file with:
Also, look at the Bounce2 README and the references with
Your algorithm is asymmetrical. Fast switch down, delayed switch up.
Replace readPeriod with something long enough to see it.
But the odd way this handles time
if (timeChange >= readPeriod) {
// other code here
lastTime = millis();
}
means the average response to a button down event will take readPeriod / 2 ms. You are locking out the examination of the button every time you loop.
So this is not an edge catcher, it does not respond in minimal time.
I hope I did not damage your code when I added a few things to it.
Play with it here:
// https://forum.arduino.cc/t/leading-edge-debouncing/964407/28
const byte buttonPin = 8;
const byte lookingLED = 9;
const int readPeriod = 1000; // absurd. human scale so we can see what really goes on
byte buttonHistory = 0xFF;
unsigned long lastTime, timeChange;
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(lookingLED, OUTPUT);
}
void loop() {
timeChange = (millis() - lastTime);
digitalWrite(lookingLED, (timeChange >= readPeriod) ? HIGH : LOW); // locked out on time?
if (timeChange >= readPeriod) {
buttonHistory <<= 1;
buttonHistory |= digitalRead(buttonPin);
if (buttonHistory == 0xFF) tracePrint("OFF");
else if (buttonHistory) tracePrint("ON");
lastTime = millis();
}
}
// print a new message, and how many times you didn't print the last new message. or don't.
void tracePrint(char *s)
{
static unsigned long tCount;
static char traced[32];
if (strcmp(s, traced)) {
Serial.print(tCount);
Serial.print(" now ");
Serial.println(s);
strcpy(traced,s);
}
else tCount++;
}
Yes, ideal for a pushbutton circuit that connects the input to GND when pressed (normally high signal with button released).
Delayed switch up will vary. If monitoring a dry relay contact with bounce time on operate = 15 ms, then the switch up delay = 15 + 40 = 55 ms. If monitoring a push button with 2 ms bounce, then the switch up delay = 2 + 40 = 42 ms. Therefore the switch up delay is the time it takes for the signal to be stable HIGH for a 40 ms period + contact bounce period + ½ loop iteration period.
Not meant to be an edge catcher as with using an interrupt. Just basic polling where actual response is determined by the user's sketch that avoids any significant blocking code.
With both this and your example, millis() is on the left side of the operator, so there's no rollover problem, but yeah, it adds on avg ½ read period to the initial response which (to me) isn't concerning since we don't really need instantaneous.
Uh-oh, its uninsured!
EDIT:
Since the most common push button circuit would use INPUT_PULLUP which offers low drive current which is usually below the minimum specified level for switch contacts (some specifiy 10 mA min), this makes the input suseptible to noise, glitches, EMI, etc and adds to the "bounce" time.
In this case, a software improvement could be a small compromise, where there's 1-bit delay on press, 7-bit delay on release.
And hacking `#define BOUNCE_LOCK_OUT" into the Bounce2 library code.
I did like my Wokwi sims for comparing debouncing schemes and simulating noise (I don't like the hacking on Bounce2 I had to do to make its fast mode work):
and for simple code for reporting un-debounced buttons.
But to the original Q, the only popular library that catches the leading edge of a transition is Bounce2's BOUNCE_LOCK_OUT mode or BOUNCE_WITH_PROMPT_DETECTION, but that only works if you edit the installed library code to define the flag.
Besides having quality buttons, and good hardware filtering, another thought is that if you write good state-machine code, you don't need the debouncing because the states should take care of themselves. Like an industrial start-stop motor contactor, or a period of lockout on HVAC systems.