4
\$\begingroup\$

I have a mechanical switch that I'd like to use as a signal source for a digital input of a microcontroller. The switch is normally closed, and I'd like to detect the switch being opened as quickly as I reasonably can, while also removing the effects of mechanical bouncing as the switch is opened. That is, I'd like the very first edge of the input signal to flip the state of the output signal towards the microcontroller and for that state to be held for a given duration even if the input signal bounces for a while after the initial edge.

Here's an illustration of what I'd like to see on a transition from closed to open. I chose an arbitrary polarity for the signals, but any polarity would do for my application.

desired behaviour when the switch is opened

I'm not really concerned with accurately detecting when the switch gets closed again, so it'd be fine if the output state changing in that direction had a fair bit of delay to the input signal first changing.

For the steady state it'd be ideal if the output was different depending whether or not the switch is open or closed, but for my application it'd also be OK if the output went back to its idle state after not detecting an edge for a while, just as long as it's easy to make the duration it's held in the activated state as long as I need it to be.

I feel like this should be achievable with at most a schmitt trigger, resistors and capacitors, and maybe a diode, but I haven't quite managed to work out how to achieve what I need with those, so I'd appreciate any thoughts pointing me in the right direction.

Thanks!

\$\endgroup\$
7
  • \$\begingroup\$ What is the supply voltage? What is the maximum amount of time delay between the signal going low and the output going low? \$\endgroup\$
    – Reinderien
    Dec 23, 2020 at 23:36
  • 10
    \$\begingroup\$ Why not de-bounce in software? Respond to the press immediately, then wait for multiple samples of the switch in the un-pressed state before looking for presses again. \$\endgroup\$
    – Mattman944
    Dec 23, 2020 at 23:37
  • 1
    \$\begingroup\$ schmitt trigger combined with a faster RC filter, such as here, if you want to be thorough. Software debounce can be very effective too. \$\endgroup\$
    – Pete W
    Dec 23, 2020 at 23:57
  • \$\begingroup\$ @Reinderien I have some flexibility with the voltages used. 5V would be most convenient. 3.3V and (less well-regulated) 24V are also an option. \$\endgroup\$ Dec 24, 2020 at 0:20
  • 1
    \$\begingroup\$ In a real system, switch bounce can be the least of the problems. Consider what is a valid operation of the switch (in real time terms) so you can distinguish between transients like ESD, lightning and other EMI. There's also other mechanical issues like vibrations etc that can cause false switch operation. If the switch is used for safety operations, then don't rely on the microcontroller. Feeding a mechanical switch into an external interrupt on a microcontroller is generally not a good idea - switches operate in terms of milliseconds, interrupts are in terms of microseconds. \$\endgroup\$
    – Kartman
    Dec 24, 2020 at 1:10

3 Answers 3

7
\$\begingroup\$

If you insist on a H/W solution, a diode will make the charging/discharging of the cap asymmetrical. The delay will be a few microseconds. The recovery time will be a few milliseconds.

schematic

simulate this circuit – Schematic created using CircuitLab

\$\endgroup\$
9
\$\begingroup\$

The best way to handle this is to debounce the signal in software with your microcontroller. This is cheap, simple, and gives you maximum versatility in terms of your debounce algorithm.

Here's an example algorithm (psudocode):

if(input != input_debounced && debounce_timer == 0){ 
    input_debounced = input;
    debounce_timer = 100; //don't flip signal again for at least 100 cycles
}
if(debounce_timer > 0) debounce_timer--;
delay_ms(1);

Notice how in the idle state the timer will reach zero, so when the switch flips, the debounced value will change imediately. The value will then be locked for 100ms.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ What you suggest is a great general solution that'll work in a majority of situations like the one I described. Calling it "best" for all situations seems like a bit of a stretch, though. You might not be in control of the firmware running on the microcontroller, you might not want to spend time in service routines for interrupts you know you're just gonna ignore anyway, you might not want to complicate your code and potentially introduce race conditions due to enabling and disabling interrupts at run-time, and so on. In my particular situation I'm mainly limited by time budget on my micro. \$\endgroup\$ Dec 24, 2020 at 0:15
  • 1
    \$\begingroup\$ This is a good answer, the OP didn't give any processing constraints. If you don't want to waste processing time, you can use an interrupt to capture the initial push. Then timers to poll for the inactive state. \$\endgroup\$
    – Mattman944
    Dec 24, 2020 at 0:56
  • \$\begingroup\$ This is the solution. The hardware ones introduce lag. This solution won't protect again noise spikes on the input, so use a smaller than usual pullup. I'm amazed how many algorithms I've seen for debounce that could just be solved by sampling the input every 50 or 100 ms. This solution is a variation on that - act instantly on state change and then don't look at the input for a while. \$\endgroup\$ Dec 24, 2020 at 15:36
3
\$\begingroup\$

Perhaps this is what you had in mind - it fulfills "a Schmitt trigger, resistors and a capacitor" and does not need a diode. When the switch is closed the capacitor is discharged instantly. Of course, "instant discharge" means theoretically infinite initial current limited only by the trace to the switch, so in practice you will want to limit this with another series resistor.

When the switch is opened, the capacitor charges through R1. Choose your component values to suit your taste.

schematic

simulate this circuit – Schematic created using CircuitLab

transient

\$\endgroup\$
5
  • \$\begingroup\$ Having a switch short out a charged capacitor is not good for the reliability of the switch. Death by a thousand cuts. \$\endgroup\$
    – Kartman
    Dec 24, 2020 at 8:53
  • 1
    \$\begingroup\$ @Kartman Do you think that would still be a problem for a 33nF cap? That's pretty small. \$\endgroup\$
    – Drew
    Dec 24, 2020 at 10:09
  • 2
    \$\begingroup\$ @Drew Small caps are actually better at delivering high peak current - that's why they're used for supply decoupling. Much better to put a resistor in series with the switch so that this is controlled. \$\endgroup\$
    – Graham
    Dec 24, 2020 at 10:20
  • \$\begingroup\$ @Kartman I wonder, are there caps specifically designed to withstand such abuse (preferably not via built-in series resistance)? I know of camera flash, but those are much bigger - and don't discharge too often. \$\endgroup\$ Dec 24, 2020 at 13:26
  • \$\begingroup\$ @Kartman Thanks - I had intended on adding a blurb about discharge safety but forgot. \$\endgroup\$
    – Reinderien
    Dec 24, 2020 at 13:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.