that line has an error but i cant find it ![]()
I think the problem is in a bad contact in the button and in the debounce variable "banda" that is late or something
200ms is an extremely long debounce interval. You would only be able to register 5 pulses per second at that rate.
No, the message says:
In function 'void loop()':
sketch_oct09a:40:3: error: expected ';' before 'if'
if (print)
^~
If you look for a missing ';' before the 'if' you will find one at the end of the line ABOVE the 'if':
preCounter = localCounter
if (print)
Adding the reported missing ';' fixes the problem.
Yes, but anything too short will start catching an extra count when the button is released.
The timed lock-out debounce method does not work if you are only watching for one edge.
Interrupt or no.
a7
It does if you are keeping track of the switch state. Then you can debounce both rising and falling edges, but check and report only one, if you are only interested in one.
Unless, I missed your point...
I guess I'm saying, the correct way is to debounce all transitions, then sort out their meaning. You certainly don't want to debounce only on one edge. Unless I just got lucky in my code - but I debounce both edges. I wanted to post it but I couldn't find the demo version.
I see, the interrupt is only called on one edge, so that choice doesn't exist. I can't think about it right now, but tomorrow morning with coffee in hand will work...
The other nasty thing about the lockout with an ISR, is that you are not locking out the ISR calls. The ISR is called every time the switch contacts bounce, creating a flurry of interrupts. The code does nothing, but still incurs the ISR call overhead each time.
With a polled port, the polling doesn't take place at all while the switch contacts are bouncing. The processor is doing useful work instead.
Yes, but not with the simple timed lockout.
Yes, I observed a problem (in the running program behaviour) and several ideas I had to solve it did not work, and I would not have even tried them had I been thinking instead of wildly hackingโฆ basically, processor fast, bouncing slow, and there are RISING interrupts taken on all the LOW to HIGH transitions on both sides of the slow switch on and off.
Anything to fix that starts to look like why use interrupts at all, if I have to do all this other stuff to make it work?
a7
I didn't see any problem other than the impact on CPU time that I mentioned. But after a walk through, I found a problem. Debouncing a static switch would be different, but for a simple push button switch, the transition from open to closed is the only event that matters, to the application. Some code might utilize the closed to open transition for some internal reason, but it's not needed "upstream".
For anyone that's uncomfortable with seeing millis() in an ISR, just be aware that calling it in that circumstance, provides the correct time, but does not increment during the time of the ISR.
Keeping in mind this limited context, have a walkthrough of an ISR. I use global constants and variables to simplify the ISR contents. Assume the wiring and edge selection is configured for a RISING edge. But that doesn't really influence the basic logic.
const int lockoutInterval = 20;
unsigned long timeStamp = millis();
...
void pushbuttonISR(){
if (millis() - timeStamp > lockoutInterval){
counter++; // just keep track of button presses for now
timeStamp = millis();
}
}
Here is a time line:
- the system boots
- the physical button is inactive = LOW, millis counter soon exceeds the lockout interval
- sometime, the button is pressed
- the first LOW to HIGH transition triggers the ISR and it is called
- the timeStamp check passes, so it increments and resets the lockout timer
(now we have entered the lockout interval) - soon the first of several false switch activations arrive (switch noise)
- it's a HIGH to LOW transition but it's ignored by the interrupt hardware because that is how the pin is configured
- soon after, another false transition, LOW to HIGH triggers the pin and the ISR is called
- this time, the lockout test fails
- the ISR immediately returns to the main program with no increment performed
(the last two steps repeat as many times as there are false triggers within the lockout interval)
When the lockout interval expires, there are two possible conditions:
- The button is still pressed
- The button has been released
Digression: Generally, this offers a choice which has trade offs. You can choose between two options, you can either
- Ignore the button state and just continue to look for LOW to HIGH transitions
- Check the button state and do not respond to the switch if it has been released during the lockout interval.
The trade off is, if you ignore, you can respond at the beginning of the lockout interval. If you want to check it, you have to wait until the end of the lockout interval. So, with one approach you get key latency, but resistance to electrical noise, and with the other you get instant response but no protection from electrical noise.
Back to the walk through, in this case we are not checking the button state at the end because the simple code here only responds to edges. It's reasonable to assume that the button is now held down, but the lockout interval has expired.
- no more LOW to HIGH transitions occur, the ISR is dormant
- millis counter becomes much greater than the last saved time stamp
- now, the button is released
- first there is a HIGH to LOW transition, it's ignored by the input hardware edge detection, the ISR is not called
- soon the first bounce pulse comes along, it is a LOW to HIGH
- that triggers the ISR
- the time stamp check passes
- there is an increment
Stop right there - this was not supposed to happen! We are registering a count on the release of the button. So you are right! Something has to be done to fix that.
I'm off to the beach, so I skipped to the tl;dr portion of your post. I will read it all carefully L8R.
But every way I tried landed me up realizing why ppl who insist on using interrupts in this scenario typically use an interrupt on a timer rather than hung on the button itself.
This then makes it an elaborate mistaken approach to polling. In a well-designed loop() polling should not present any problems, certainly none that an interrupt would fix.
And anything you come up with shall be tested! My code often surprises me, and my code operated by other ppl even more often...
a7
I did extensive testing of my own polled switch code. I don't really like the ramifications of debouncing interrupts in software so I have never looked into it very much. I agree with the people that say, if you must put a button on an interrupt input, debounce it with hardware first.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.