Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Non-inverted RC Debouncer

Status
Not open for further replies.

z9u2k

Member level 1
Joined
Jul 10, 2009
Messages
32
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,602
Hey all,

been doing some reading on single-throw switch debouncing methods, mainly here: Debouncing

I am interested in the RC debouncer presented, but I was wondering if it was possible to lose the inverter.

The inverted debouncer looks like this:
debouncerrc.jpg


I was thinking that by swapping the switch and R1, and changing component's values, I could get a non-inverting debouncer.

At first, the switch is open, and the capacitor is discharged. The gate sees a logical zero. When the switch closes, the capacitor will be charged through R2 alone. Using a 100nF capacitor and a 390k resistor as R2 I could get 20ms before the capacitor's voltage reaches 2V (assuming a 5V supply), which is the logical high threshold of the uC I'm working with.

When the switch opens again, the capacitor will slowly discharge through both R1 and R2. Using a 10k resistor as R1, I would get about 73ms before hitting the 0.8V logical low threshold of my uC. (if C was fully charged)

Having the logic inverted isn't a problem as having my CMOS input pin leaking about a microamp when held high (would it leak out when held low?) which biases the capacitor to that current times R2.

This would also prevent false triggering when the circuit is first powered up and C slowly charges past the threshold voltage on its way to the idle state, long after the uC has booted (which makes me use a similar circuit on my nRESET pin to prevent the uC from powering up before all peripheral capacitors have charged)

If this works (and please point me where I'm wrong), why is the inverted circuit so popular while I couldn't find references to any non-inverting?

Thanks in advance!
 

Inverting or non-inverting will work just the same. The critical factor is the type of gate you use, it must be a Schmitt triggered input, one where the upper logic threshold and lower logic threshold have a gap between them. A normal gate will switch at one threshold, below it is one logic level, above it is the other but there is a gray area at exactly the point where the level is reached. As the input voltage will rise or fall fairly slowly as the capacitor charges and discharges, a normal gate might show random output levels as it crosses the switching point. In other words it would look just like switch bounce! The two switching points of a Schmitt input gate prevent this happening.

As an alternative, you can always use the inverting gate and re-invert it afterward in a second gate.

Brian.
 
  • Like
Reactions: z9u2k

    z9u2k

    Points: 2
    Helpful Answer Positive Rating
Thanks.

For some reason I was certain that PICs has a Schmitt trigger at their GPIOs. They don't...

I still think that going with the non-inverting method is better, as it saves the trigger's input leakage current(?), and avoiding the initial false-release on powerup...
 

I suppose it really depends on which polarity you need to detect at the output. You are partially correct in saying some PIC pins are not Schmitt triggered although in some cases they are. If you use this circuit to drive a PIC, why not simply look for the other logic level as an indication of the switch being closed? It should be a very simple software modification, either change 'btfss' to 'btfsc' on the port bits or if you are using all 8 bits of a port, invert the whole lot in one go.

There is another option, to use a non-inverting CMOS gate and connect a high value resistor (1M perhaps) between it's output and input so it tries to pull itself high or low, then provide enough current sink or source to override the input condition through your switch. This method one less component at the expense of using a changeover switch.

Brian.
 

If you are using a PIC, then it is easy to do the debouncing in software.
 

If you are using a PIC, then it is easy to do the debouncing in software.

Indeed I could add a delay to my ISR, the problem is that my buttons are connected to PORTB, with interrupt-on-change, and aside from my buttons, a few SPI peripherals has their IRQ lines connected to this port, so adding a delay to the ISR is less of an option in this case...
 

But you don't need to have an interrupt on all bits of the port - leave it off the bit you are using for the button.
BTW, what is your 'ISR'?
 

But you don't need to have an interrupt on all bits of the port - leave it off the bit you are using for the button.
BTW, what is your 'ISR'?

ISR = Interrupt Service Routine

I don't have Interrupt-on-change on all bits, only on those I use. But I have more than buttons on these bits, I have also interrupt notifications from external peripherals, which cannot wait a few milliseconds before served.
 

I am not sure I unterstand what you mean. Are you saying that a specific bit being used for a button input that must have a debounce delay, is also being used for input from a peripheral that needs immediate servicing?
 

I am not sure I unterstand what you mean. Are you saying that a specific bit being used for a button input that must have a debounce delay, is also being used for input from a peripheral that needs immediate servicing?

No. Different pins on the same port.

The interrupt-on-change is given at the port level.
 

I am currently using the 12F629 which has a register, IOC, to individually enable/disable the interrupt on each pin. I assumed that PICs used a standard interrupt-on-change method, but obviously they don't.

Nevertheless, why not check the button bit after you go into the interrupt routine. Then, if activated, set a flag that you can look for when you exit the routine. If the flag is set, then do a debounce routine.
 

I am currently using the 12F629 which has a register, IOC, to individually enable/disable the interrupt on each pin. I assumed that PICs used a standard interrupt-on-change method, but obviously they don't.

Nevertheless, why not check the button bit after you go into the interrupt routine. Then, if activated, set a flag that you can look for when you exit the routine. If the flag is set, then do a debounce routine.

Hmmm.. This is interesting, but might be unpredictable.

You assume the value of the port won't change between the time the interrupt was triggered and the port is read inside the ISR.

There is at least (2 x Fosc/4) time between the port changing its value and the ISR entering. Then, there are a few context-save instructions.

Assuming 4MHz, it could take a few microseconds for my ISR to read the port...

Some switches might produce waveforms in the MHz region, fast enough to change between entering the ISR, and reading the port.

So... which pin triggered the interrupt?

OTOH, I guess I could check the urgent pins (that doesn't bounce) first, and if none has changed, wait the debounce period and recheck.

Thanks :)
 

Yes, your last sentence would seem to be the best way of doing it. And it would probably help to fit a 1nF cap from pin to ground to slow the pulse for a few µsecs.
 

Yes, your last sentence would seem to be the best way of doing it. And it would probably help to fit a 1nF cap from pin to ground to slow the pulse for a few µsecs.

Though this may cause me to lose "other" interrupts (whether I'm delaying in the ISR, or turning them off and starting a timer).

A hardware solution is still required... :\
 

I'm amazed at how much time is wasted on switch debounce. Most people optimize their moronic software for new switches and have no clue how their hardware and software will react as their switch ages. Tieing buttons directly to interrupts is a waste of time and a waste of your time.

Around 30 years ago, the Commdore PET / VIC20 / C64 all scanned the keyboard at 60Hz rate, didn't use crazy debounce hardware, and they shipped millions of those computers. All you need to do is read buttons every tick and look for changes, and it doesn't matter what happens to your switch signals between scanning.
 

Around 30 years ago, the Commdore PET / VIC20 / C64 all scanned the keyboard at 60Hz rate, didn't use crazy debounce hardware, and they shipped millions of those computers. All you need to do is read buttons every tick and look for changes, and it doesn't matter what happens to your switch signals between scanning.
Well, I too thought it somewhat a waste of time, and for many cases a simple delay routine, or pulling instead of pushing the button will be a lot simpler and quicker. But then there are these cases you want it 'just right'.

What about battery operated devices (such as my application), that most of the time does nothing? I like to send my uCs to sleep for as long as possible if I'm idle, to save power.

Connecting buttons directly to an interrupt allows me to go to sleep for long periods of time, without worrying that I'll miss a button press.

Seems like a waste of power if I have to wake up every 16ms instead of a few seconds just to pull on a pin instead of sleeping waking up only when something actually happened.
 

There are another potential problems with polling instead of interrupting, especially when bounce is anticipated, the poll might catch the 'bounce' in the wrong state and see the wrong logic state and it could also miss the input altogether if the polling was too slow or delayed by some other event. Electrical debounce, preferably followed by IOC is by far the safest method.

I don't know z9u2k's design but if any of the switch inputs have 'auto repeat' it also gets messy in software to debounce and count repeat delays at the same time. They are also quite right about the 'sleep' issue, if the clock is shut down it is impossible to run a software switch scan. From a power saving point of view, the original post is correct, using a non-inverting gate is perfectly acceptable but I'm not sure reversing the switch and R1 would actually reduce consumption, even if the switch was held closed.

Brian.

Brian.
 

z9u2k: If you use a hardware debounce, you still have the problem of having to wait in the interrupt routine for the switch pulse to end. During that period you could miss an input from one of the other sources unless you are watching out for them. If you watch for them you might just as well do the debounce while you are there.

If you still want to use hardware, then what you really need is a short, sharp pulse from a monostable. But you could probably get by with this simple arrangement. Put a 10nF cap across the switch and feed it from +5V through a 10K resistor. When the switch is operated you will get a very short fall time with good immunity from bounce. Couple the switch into the port bit with a small cap and use a pull-up on the pin. The cap should be just large enough for the differentiated pulse to be long enough to be detected and identified within the interrupt routine.
 

z9u2k: If you use a hardware debounce, you still have the problem of having to wait in the interrupt routine for the switch pulse to end.
Why do I have to wait inside the ISR?

I'll get the first interrupt on the 0 -> 1 change, go about my business, and another interrupt (which I can ignore) on the 1 -> 0 change.

If you still want to use hardware, then what you really need is a short, sharp pulse from a monostable. But you could probably get by with this simple arrangement. Put a 10nF cap across the switch and feed it from +5V through a 10K resistor. When the switch is operated you will get a very short fall time with good immunity from bounce. Couple the switch into the port bit with a small cap and use a pull-up on the pin. The cap should be just large enough for the differentiated pulse to be long enough to be detected and identified within the interrupt routine.
Not sure I understand. The switch is grounded on one side, and tied high through a 10k resistor on the other, with a 10nF across the switch?

This resembles the schematics in the original post only without R2, correct?
 

Why do I have to wait inside the ISR?

I'll get the first interrupt on the 0 -> 1 change, go about my business, and another interrupt (which I can ignore) on the 1 -> 0 change.
You're quite right. I was forgetting. This is an interrupt on change, not on level.


Not sure I understand. The switch is grounded on one side, and tied high through a 10k resistor on the other, with a 10nF across the switch?

This resembles the schematics in the original post only without R2, correct?
Not quite. Here is the circuit. Differentiated pulse gives input only while level is below the input's threshold level.
59_1284993598.gif
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top