NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Microcontroller Programming » Debouncing on interrupt button press
March 28, 2013 by lnino |
Hey guys, it has been some time ago when I made my first attempts with Interrupts. So I decided to give it another try. I have a spinning 7 segment display and I want to interrupt it when I press a button (PC5) to do another operation. I trasposed a interrupt code of another thread and it works great. The only thing is I think a made somehting wrong with the debouncing. Something when I press the button the operation executes twice instead of once. This is normally an inidication of a debouce failure. But in my other project the debouncing works like I used it. Does someone has an idea how it should work?
|
---|---|
March 28, 2013 by esoderberg |
Inino, This blurb from AVR Freaks might explain your results: Each vector has an associated ??IF?? bit. When the event occurs the ??IF?? bit is set. After completing an opcode the AVR core then checks the ??IF?? bits in vector table order and for the first one it finds to be set it then calls to that interrupts vector handler. If the same even occurs once while that interrupt is being handled the ??IF?? bit for the interrupt is set again. When the ISR performs RETI the interrupt system is re-enabled and a return to the interrupted code is made where ONE opcode will be executed. When that opcode completes the whole process starts again. So you will get one main line opcode executed for each handling of interrupt. If the interrupt event occurs TWICE while the ISR is being handled then ??IF?? does not count interrupts but only says that "one or more occured" so one occurrence will be handled and any other will be lost. This is why an ISR should always complete in 2us..3us and NEVER take as long a 1ms and definitely not longer than the expected period between interrupting events. |
March 29, 2013 by lnino |
Hi esoderberg, thanks for your reply. And how can I change the code that the ISR takes a shorter time? Reduce the milliseconds in the delay function for the debouncing? What do I have to change in my code? |
March 29, 2013 by esoderberg |
Inino, I think the simplest way would be to poll vice using an interrupt.
The down side to this is your code sits around doing nothing for 400 ms every button press. If you wanted something that would run faster and use interrupts, you could have a clock running in the background and use the interrupt to mark the time (at tm) for a start of button hit(not much time executing interrupt code at all), then outside interrupt check:
NOT tested code, just my quick swag. Eric |
March 29, 2013 by lnino |
Hi esoderberg, thanks for your reply. I will test your code example. Meanwhile I found an awesome code for debouncing a button. I tried it and it works great. Here it is:
|
March 29, 2013 by esoderberg |
Inino, Posted code below works. The polling code is simpler (with no extra overhead of running a clock if not already doing so) so if it works for you that's great. However, the interrupt code below won't cause your code to hang up on each button push so it may be of value for time sensitive programs where waiting for 200 ms or more on each press isn't advisable.
|
April 07, 2013 by JimFrederickson |
One of the things that you really want to think about is before you use them are the "_delay_ms()" functions. I, personally, ONLY use them for delays of < 5ms. (Even then I don't use them often.) With the delay of 200ms that you used in one of your examples that is, essentially, stopping your program for nearly 3,000,000 cycles. For "simple"/"test" programs this is not a problem, but for future more complex programs this will become a problem. So staying out of that mindset sooner, is often better. For most, more complex programs, you will want to be able to juggle multiple events/actions in a manner that appears simultaneously for that you need to have "even program flow". "Doubletap" is in the library that would shed some light on this. We had a discussion of this in the Forums here in September of last year. Ultimately, you want interrupts to really do "as little as possible". Interrupts "CAN NEVER" do more processing than the frequency of the interrupt occurrence. (As a simple example of this, if you have an interrupt that occurs 1,000 times a second then the code for the interrupt CANNOT use more than 14,745 cycles in length.) The code for the interrupt must ALWAYS finish before the next interrupt occurs. For using "keys" of any sort there are really 2 things that are important. 1 - "debouncing" of the actual key press/key release. This is effectively removing multiple quick contact/no contact situations from the actual key action. So that in the end you have a solid "key press" or "key release". 2 - Does your program care if the "key is being pressed" or that the "key was pressed". (The same applies for releases as well, but it is also basically the difference between a "switch" and a "key"/"button".) These are 2 different situations. Mostly your program will care the that "key was pressed" and then there will need to be code in your program to wait for a "key release event" before processing the next "key press event". A common error is continuously checking if the "key press event" without ever looking for a "key release event". Even if you press and release the key as quickly as you can, the Microcontroller will see dozens of "key press events" before you can release the key. For me almost everything I do involves some sort of "switch" or "key", and I debounce both of them and store their results separate. (I am traveling and will write more later... The "library double tap" example is simplified the discussion I think is better...) |
Please log in to post a reply.
Did you know that you can connect digital calipers to a microcontroller? Learn more...
|