Need to debounce the counter input - New user programming in C needing help
Sparko
Posts: 8
I now have a counter that works. I monitor PIN0 , that I have held high using a 100K resistor between Vin and Pin0. When I ground Pin0 it realizes a negative going edge and counts. The only trouble is that multiple counts always occur.
The normal pulse to be counted is low for 100ms.
I have put in a loop that checks for a change in the pulse condition after 50ms and this accomplishes the debounce fine but ties up the main program for the 50ms.
Please give me advice on the best way to debounce input for an event counter like in this kind of application.
Thanks in advance.
Sparko
The normal pulse to be counted is low for 100ms.
I have put in a loop that checks for a change in the pulse condition after 50ms and this accomplishes the debounce fine but ties up the main program for the 50ms.
Please give me advice on the best way to debounce input for an event counter like in this kind of application.
Thanks in advance.
Sparko
Comments
The best way is with an External logic gate Schmitt + RC filter ( 1G17 etc) - HW sets the filter time constants, and no SW fixups are needed.
A SW patch approach would be to limit the count rate to (eg) +1 every 100ms, and for that you just check the Counter at some convenient polling rate, and ensure over 100ms it is forced to either +0 or +1
Effectively the Counter HW is used as an edge(s) detector, and you advance in SW at some slower rate.
This device is being developed to count coin pulses from various already installed coin drops. Bounce is anticipated but due to the variety the exact duration is unknown. However not more than about 10ms.
Leon - Thanks I will consider RC circuit in the article first.
jmg - Thanks - Am I correct in thinking that running the counter and SW debounce in a separate cog allows the main program to proceed at will (asynchronous from the counter) and read the count and zero the count any time it is convenient? If this is the case is there any advantage to using a counter in the edge detecting mode at all?
professor - Thanks Here are the sections of code involved below. Am I correct that if I put this in a cog independent of the main the main can proceed and check and zero the count at any time that is convenient? Am I correct in thinking there is no advantage to using a counter at all? If there is an advantage I could I use the debounce part of this code to feed the neg edge detecting counter?
...................................
#include "simpletools.h" // Include simpletools
int main() // main function
{
int buttonchange = 0;
int pulses = 0; // initialize pulse counter
while(1) // Endless loop
{
while(buttonchange == 0) // Loops until a valid pulse is realized. Pulse detection
{
buttonchange = 0; // a change is the switch position from zero to one will record a change
int button1 = input(0); // initial button position
pause(50); // wait 10ms to get beyond any bounces
int button2 = input(0); // button position after pause
if (button1 != button2 && button1 == 1) // button has made a complete transition without bounces
{ buttonchange=1;}
}
++pulses;
pause(100); // Wait 0.1 second before repeat - a subsequent pulse is not possible for the next 0.1 second
print("pulses = %d\n", pulses); // Just for testing the program
buttonchange = 0; // Return to pulse detection loop
}
}
Of course you synchronize the reading in main with global flag or semiphore.
So you need less power than with polling.
Once the bouncing stops the switch is probably stable and the reading can be used. I would start the 10ms wait timer after the detected bouncing stops for a typical single bounce cycle. So it might be that using the propeller to look for a lack of bounces / transitions for a short period of time, then waiting a little longer, would be a way optimize the overall wait time to take a reading.
This is a real tricky problem that appears to be solved until the one in a hundred (or thousand) unpredictable-unrepeatable hiccup occurs. Temperature will change the relative position of opposing contacts and change the nature of the beast too.
Yes, a separate COG can move the result to a simple async, anytime, HIUB read.
However, you may not need to go that far - the Counter may seem almost 'not needed' but it does give HW edge detection, so you know you do not miss any edges, the problem shifts to what to do about the 'bonus edges'
With a counter, you can check that quite infrequently in the main SW, and then apply your simpler rate filter.
You do not have to worry about the duty cycle of the trigger signal, and it will work on opto-interruptor style signals too.
Psuedo code is along the lines of this, called slower than longest bounce time, and faster than your known shortest pulse-pulse time.
I agree with jmg's concept. Wait for the first transition with a waitpeq/waitpne as this lowers power consumption. You could then fire off your counter to count the transitions, and monitor the transitions until they stop counting for a period of time (use the CNT to time the steady state time). Each time you get a toggle, reset the time.
It is quite simple and lends itself to be done in pasm (or spin) as its own object running in its own cog. Then its only a matter of that object updating a hub variable each time a valid count is seen (its going to be quite slow - how fast can you put a coin in a slot - not that fast in reality).
As others have said, you can throw this in another cog if you like.
It works by having a timer keep track of the system counter. It only checks pin states if the counter has elapsed past the debounce time. Then it uses a flag to track the previous state of the pin.
As written it looks for pin high on a pull-down resistor. To use a pull-up like you said you need, just move the action (incrementing the counter) to the "if pin == 0" block.
Brian