debounce buttons with a analog pin?

Hi all!
My project will be using a bunch of buttons, and that debounce code is everything but neat..

So im trying to figure out other ways to measure the buttons (simple momentary push buttons, directly connected to arduino nano digital pins, with pull-up resistors active).

The idea is to tie each button to its dedicated digital pin, but also, thru a schottky diode (have a bunch), connect it to a analog pin.

So all the buttons (about 6 in total) are connected to D3 thru D9, as well as A0 (thru 6 schottky diodes), to isolate each "channel".

The idea is then to read the digital pin(thisPin) AND analog pin 0, if A0 is NOT between 1V and 3.5V, (schottky voltage drop of about 0.5v, 1v margin of error, project is on 5V) detect the button as is, if LOW; then PRESSED.
else if A0 = 1-3.5v, repeat read_inputs block

To explain in a different way, the analog pin is supposed to detect a floating signal (not Vss or Vcc), and if it detects a floating signal, it nullifies the digital pin read, forcing the program to repeat the read input block.

Now, the question is; will this actually work?
Will a analog read, in combination with a digital read (on the same button) result in a non-bouncing input signal?

Ive had a similar idea, but instead of the analog pin, tie the schottky diodes to digital pin 2 or 3, witch supports interrupts.
I would then be able to use interrupt to initiate the read_input codeblock, and compare thisPinRead with interruptPinRead, if same, then allrightie then, else button is bouncing.

Since i figure that eventually, the bouncing will stop, rendering the interuptpin and thisPin equal, witch in turn returns the correct button state.

Would this be a better option? If so, why? If not, why? (im trying to learn here.. :slight_smile: )

Are there other ways to eliminate the button debounce issue?

I´ve seen some suggestions towards hardware debouncing, how much PCB real-estate does it cost?
Is it unfeasible for most projects, or is it just a few SMD parts?

So all these crazy ideas using diodes and extra pins are because a piece of code is not neat? Post the code and we will help you make it neat.

Well, yes, to be simple, i dont like debounce, and would like to find another way to reliably read the button states.

And posting my code would not help in any way, you guys would laugh at my incompetence, suggest i take a programming course and have me read the debounce tutorial or something.. :slight_smile:

The thing is that i do not want to debounce each button separately, since it requires more ram, but i havent had much luck in debouncing ALL buttons in one go eather, mostly because of ram usage.
Im trying to keep the hardware usage to a bare minimum at this stage, since all of the features are not inplemented yet..

Regarding the "normal" way of debouncing, it demands that i keep track of time elapsed, debounce time values, this&lastbuttonRead and so on...
This works fine for a single button, but this isnt very neat when dealing with multiple buttons of different types, and it requires a whole bunch of variables, values and so on to be stored in memory.

I also need short/longclicks, as well as HOLD-clicks, witch makes the software a bit more of a hazzle..

So please dont loose focus, this thread is about ways to skip the debounce shite, not to fix it. :slight_smile:

Yet another way to "debouce" would be to have the main loop to read each button, if pressed; add 1 to button[thisPin] array, if not pressed, set button[thisPin] to = 0.

If button[thisPin] >= 3, button is pressed and "debounced".

So, what do you guys say, is there a (reasonable) way work around the debounce shite?

And a final and off-topic note, i can not for the life of me understand why one has to debounce a button manually, i figure this should be done in hardware in the Atmega chip...
This current debounce requirement feels like someone cut (at least) one corner too many in the development stage..

And yes, i understand what bouncing buttons are, but i fail to understand why the controller doesnt incorporate bouncing filters.

No chip designer is going to waste silicon on something as simple to achieve in software as button debouncing.

Tell us more about the buttons. How many (7)? What type? What kind of usage will they get? Are they together like a keypad, a control panel or a music keyboard? Will they be pressed one at a time or simultaneously in rapid combinations, and if so how important is it to recognise each press in sequence and in length?

The reason buttons often have to be debounced is because microcontrollers are so fast that they can pick up on the bouncing, if they constantly check the input pin. If you slow down that process, like only checking the buttons 10 or 20 times per second, the bouncing is not a problem. But there is then a danger of missing very short presses. So that's why it's important to know how the buttons will be used.

I expect to get reamed for suggesting it, but consider hardware debounce A 0.1uf cap across the switch is all that it takes to debounce it. If not the switch is probably bad.

groundFungus:
I expect to get reamed for suggesting it, but consider hardware debounce A 0.1uf cap across the switch will debounce it. If not the switch is probably bad.

This works well.

.

Ehm.. are you guys kidding me?? is a tiny capacitor enough to debounce the button??

Well, this feels awkward, how did i not know this??

Thank you kindly for bringing that to my attention, i belive i just solved the debounce shite! :slight_smile:

Would a capacitor be connected directly to the button, or the arduino (button pin), or anywhere on the cable?
Im asking because sometimes the position is important when it comes to capacitors, but im too much newbie to understand why..

Also, in case i do not have that specific value, a larger value would still debounce the button, but the cap just takes some tiny amount of time longer to fill up?
In other words, any cap should suffice, but try to keep it around 0,1µF? Or MINIMUM 0,1µF?

Regarding the other questions:
The buttons are used to control horn, turn indicator and so on and are placed around the users thumbs on the handlebar, much like on a motorcycle.

So there are 4 "channels" for the buttons, turn right/left, horn and loud_horn.
I will probably be doubling up some of buttons, so i can use the horn with both hands for instance.

The minimum duration of a interesting keypress would be somewhere around 0.1-0.2 seconds, a quick "mouseclick" type of action.

I will allow multiple simultanious button presses, i want to be able to use the horn even when im activating the turn indicators and so on.

There are also 3 inputs dedicated to a 3way sliding switch, to set current mode, to turn on/off position lights and to toggle hazard light blinks.

The slide inputs are not to change that often, so a 0.5second delay would be fine, even tho i´dd rather have a delay to short to notice.

Would a capacitor be connected directly to the button, or the arduino (button pin), or anywhere on the cable?

That is a good question. I usually put the cap at the switch. I googled "hardware debounce cap location" to see if there is any info to validate how I do it and didn't really find anything, so am not sure that it matters.

Also, in case i do not have that specific value, a larger value would still debounce the button, but the cap just takes some tiny amount of time longer to fill up?

If you use too large a cap the RC time constant will be longer, but the bigger factor, I think, is with large caps (1uf or greater?), contact arcing could adversely effect contact life. Experimenting is allowed. Try a smaller value, try a larger value. See what happens.

If you are going to be in the hobby for a while, buy 0.1uf caps by the hundred. They are the most used cap value in my experience.

Long ago, before microcontrollers came with all of the peripherals built in, timer chips were an expensive (cost and board real estate) option. Hardware debounce with a cap, SR flip flop or Schmitt trigger were about the only ways.

I am no longer sure now why you want to debounce the buttons at all. If is a simple press-to-start-doing-something, release-to-stop operation, there is no need to debounce at all. You only need to debounce when you need to perform a once-per-click-only operation such as registering a keystroke on a keypad or counting the clicks to cycle through a set of options such as in a menu, setting a mode etc. These are the situations where double/triple-registering a press because of button bounce is unwanted.

groundFungus;
Hmm.. my buttons will be external, encased in hotglue plastic.. so im not sure if i can have the cap´s on the button itself..

And im getting a bit confused regarding the exact connection of the cap..
Do i put the cap´s each leg to each leg of the button, in essence parallell with the button?
Or am i supposed to connect ground to buttonPin1, buttonPin2 to cap1, cap2 to arduino digital pin? (using pull-ups in software.)

The parallel connection seems to me to be wrong, since the cap would charge from the pull-up resistors, making it impossible to detect the button behind the cap..
I assume im wrong, or just misunderstood something, but on the other hand, my hunches (or gut) are often not wrong..

I ordered a baggie of cap´s on ebay a few years ago, i believe it was 10 of each value, about 15 or 20 values in total.
So i should be good for the time being, but yes, i will be ordering bulk when the economy allows. :slight_smile:
The prices in sweden are insane, about 0,2€ per resistor (smd), while the chinese parcels often gets "misplaced" by the swedish postal "services"...

So its ether paying a high price for local parts, pay a lower price, but higher shipping on swedish e-commerce sites, or pay a good price(low as fsck), with a reasonable shipping cost, but at a roughly 20% risk loosing your package before you get it.

lol @ "if you're going to be in the hobby for a while"... :slight_smile:
I believe i found my calling in life, my only regret is that i didn't learn it when i was a young lad.. :stuck_out_tongue: :slight_smile:
..its VERY hard to learn electronics and programming by yourself, even if you have internet to help you..
..especially when you passed the half-way mark on your way to eternity...

Paul;
Well, when you put it like that, i cant really argue.. :slight_smile:
But i wont be "simply" using "press-for on, release for off" type of button trigger, i will be using multiple types of clicks, like shortclick/longclick/longpress.

With that said, i still don't know exactly why i would debounce them, i kind of though it was necessary, for some reason or another..

But on the other hand, i cant have the features popping on or off at random and many of the features are "latching" in software, so i click a button to invert the current state of that specific feature, turn ON the turn indicator if it was off and vice versa.

Some of the features are disturbing for others in traffic, a truck horn going off due to bad debouncing is not a welcome surprise at the red lights...
..and yes, im aiming at a electric truck horn as my loud horn, the polite horn will be a LOT quieter.. :slight_smile:

But still, i´ve just learned that i can use cap´s to eliminate bouncing, so this discussion is now purely academic, to further my development on the topic. :slight_smile:

Here is how a switch is wired. Each switch gets a cap.

Thanks Fungus! (what would i ever do without you?? :slight_smile: )

so, as i understand it, when the button gets pressed, both sides of the cap gets grounded, therefore: cap emptied, and the digital input reads 0V.

And when the button is not pressed, the pullup charges the cap to vcc, so a digital read returns HIGH.

So when the button is bouncing, the input still reads unpressed while the cap is emptying, until it suddenly reads pressed?

Is this correct?

..sorry for nagging about this, but im slowly grasping the finer details here, and just want to make sure im not wrong before i store the knowledge as fact. :slight_smile:

So when the button is bouncing, the input still reads unpressed while the cap is emptying, until it suddenly reads pressed?

That is kind of backward. When the button is pressed, the cap is shorted (0V across the cap) and the input is LOW. If the contacts open, due to bounce, the cap begins to charge at the rate determined by the pullup resistance (RC time constant) . So the cap starts at 0V and slowly (relatively), the voltage begins to rise. If the switch closes again quickly the voltage is brought back to 0V again. And as long as the voltage during the charging never reaches Vcc * 0.6 (the threshold for logic HIGH) the input will read LOW.

Using a capacitor is a great way to de-bounce switches.

As far as software is concerned, just read your switches every 50ms.
This will suffice for 99.999% of the time.

if (millis() - switchMillis >= 50ul)
  {
    switchMillis = millis(); //reset timing
 
    //it is time to go read the switches
    chechSwitches();
  }

.

I would put the cap as close as possible to the Arduino. That way it will also act as a filter to exclude interference picked up by the long cable. More filtering is possible if you put a resistor in the line coming in to the Arduino box.

If you're riding your pushbike on the road, you will get interference from the ignition systems of nearby cars.

Hmm... Now I have a question for the gathered experts. The Atmega's input pins are TTL-style or CMOS, yes? Doesn't that mean there will be a range of input voltages which are not guaranteed to predictably read LOW or HIGH? So when the debounce cap is charging or discharging, the voltage presented at the pin will be in that dangerous range of voltages for a time, and the input pin could read randomly HIGH or LOW, leading to false triggers and defeating the attempt to debounce the switch. I remember from my PICAXE days that PIC mcus have "Schmidt trigger" inputs selectable on some pins, which "snap" to HIGH or LOW, which would solve the problem. But AVR chips don't have Schmidt trigger inputs, do they? Someone please explain the flaw in my concerns, because I'm pretty sure debouncing caps work with AVR.

I have also seen some debounce circuits that use a Schmidt trigger chip for input debounce in hardware - sorry forgot where I saw the circuit - had some extra parts to make things work - the part that irritates me is that many times the logic level is reversed (low for button press) - I come from an industrial background and low for a button press was forbidden as a broken wire goes low and is seen as a button press - or maybe the logic was reversed in the chip giving low to the Arduino which makes the code a bit backwards - but the low for a button press was always not allowed for good safety reasons - broken wires needed to stop things not enable them

PaulRB:
Hmm... Now I have a question for the gathered experts. The Atmega's input pins are TTL-style or CMOS, yes? Doesn't that mean there will be a range of input voltages which are not guaranteed to predictably read LOW or HIGH? So when the debounce cap is charging or discharging, the voltage presented at the pin will be in that dangerous range of voltages for a time, and the input pin could read randomly HIGH or LOW, leading to false triggers and defeating the attempt to debounce the switch. I remember from my PICAXE days that PIC mcus have "Schmidt trigger" inputs selectable on some pins, which "snap" to HIGH or LOW, which would solve the problem. But AVR chips don't have Schmidt trigger inputs, do they? Someone please explain the flaw in my concerns, because I'm pretty sure debouncing caps work with AVR.

The 328 and probably other controllers have a Schmidt trigger on inputs.
See input drawing in the data sheet.

Best to have 100nF or smaller as the de-bounce capacitor so the charge time is fast.

I'm pretty sure debouncing caps work with AVR

Yes they do work.

As mentioned in an above post:
As far as software is concerned, just read your switches every 50ms.
This will suffice for 99.999% of the time.

For filtering, add a double read to the input read code.
ex: 25ms X 2 assures a valid input if over 50ms.

.

Great discussion on Mr. Gammon's web site.

.

Well, now that the buttons are debounced with cap´s, i was actually planning on using a library to enable software interrupts on pins other than the two enabled on the arduino (nano).

The plan is to use ISR´s to count the number of times it detects a button pressed, clearing the counter if button is released, and then use a number of if-statements, comparing each button press counter with predefined short/long-click durations.
If the counter is more than zero, the button is pressed.
I might eventually set the limit to 2 or something higher, in case i need a bit more signal filtering.

This is the current plan, ive never used ISR´s before and need a "tiny" bit of studying on that topic.. :stuck_out_tongue:

PaulRB; its a interesting point, but i think that such read failures would only delay the on and off state changes, not actually changing anything in practical terms for a human observer.
Im probably wrong, one way or another, this is just my late-night-logic applied to your post. :slight_smile:

MorganS;
Thanks for the placement advice on cap´s, ill make sure to place them as close to the input pin as possible.
,
I havent had any issues with external interference as button presses on my last build, simple pulldown type setup, over a cat5 ethernet cable, ending in a VGA connector fitted to the arduino box.
the cable lenght was about 2 metres (two good yankee-steps :wink: ) and was un-shielded (no foil, just plastic).
I did however use a double buttonread with a debounce interval in between, comparing current and last read.

I havent been intimate with any vehicle since i built the v1.0 system, so it might be a matter of distance..
However, if a car is that close to me in traffic, i believe my priorities are not anything related to the button signals, but more along the lines of getting the h€ll outta the way..

But now im getting off-topic, the initial question (and all of the related ones) are answered to my full satisfaction. :slight_smile:

Thank you all for donating your time and effort in answering my questions, i greatly appreciate it (and will be paying it forward)!

And a big thank you to groundFungus, for educating me on cap´s! This knowledge will come handy more than once! :slight_smile:

PS:
I´ll get back to you LarryD, i just have to interpret your scope pics first. (never used one)