View previous topic :: View next topic |
Author |
Message |
Edgar
Joined: 04 Oct 2004 Posts: 11
|
Posted: Wed Oct 20, 2004 4:17 pm Post subject: Debouncing reed_input |
|
|
Hi,
I'm having trouble with debouncing a reed switch in software, using BASCOM and a AT90S2313 controller. In the testbench (using pulse generators) it works fine, but in reality it doesn't. The input is set "weak" (internal pull-up resistor).
Here a sample of the ISR doing the job:
Reed_isr:
Disable Int1 'debounce input !
If Wheelspincntr = 4 Then 'time-averaging in 4 wheelrevolutions
Wheelspincntr = 0
Value = Rpm_counter
Rpm_counter = 0
Else
Incr Wheelspincntr
End If
Waitms 10 'debounce time
Enable Int1 'debounce REED-input with 10ms
Return
So I disable the interrupt, do the job, wait for 10ms or so and enable the interrupt again.
Do I do something wrong ? Is there a better way to debounce an interrupt-input ?
Regards,
*edgar* |
|
Back to top |
|
|
Frankeman
Joined: 11 Aug 2004 Posts: 948 Location: the Netherlands
|
Posted: Wed Oct 20, 2004 5:20 pm Post subject: |
|
|
Hi,
Can't you use the DEBOUNCE statement.
Frank. |
|
Back to top |
|
|
DToolan
Joined: 14 Aug 2004 Posts: 1384 Location: Dallas / Fort Worth, Texas (USA)
|
Posted: Wed Oct 20, 2004 7:11 pm Post subject: |
|
|
Edgar,
When you "Disable Int1", you aren't actually disabling the interrupt. What that does is disable a flag in an internal AVR register that means "allow servicing this particular interrupt when it occurs". You can remove those "disable int1 / enable int1" lines from your INT1 service routine.
There is another register that holds the actual INT0 and INT1 flags themselves. When configured, these flags will get set any time an INT0 or INT1 condition occurs (regardless of whether INT0 or INT1 is enabled / disabled).
The INT0/INT1 interrupt process goes something like this.
1. A high or low transition occurs on the INT0/INT1 pin and this, in turn, sets the INT1 flag in a register called GIFR.
2. The processor looks to see if the servicing of interrupts is globally enabled/disabled. This is a flag in a register called SREG.
3. If so, the processor then looks to see if servicing INT1 is enabled or disabled. This is a flag in a register called GMISK.
4. If so, the processor vectors to the INT1 service routine and automatically clears the INT1 flag in GIFR that began this whole process (step 1).
So you see, enabling/disabling INT1 doesn't stop step 1, it only changes (halts the progress of) step 3.
So now let's narrow down your particular problem / condition. When your reed relay first produces a high or low (I don't know what level you have INT1 config'd for), this generates the step 1 condition. With interrupts globally enabled and your INT1 enabled, we progress to step 4 and you are now inside your INT1 service routine. Well, because your reed relay bounces, while you are inside your INT1 service routine, the step 1 condition (flag) gets set again. This won't get handled until you leave your INT1 isr. This is also true for all other interrupts. While the processor is busy inside one interrupt service routine, all other interrupts that occur get placed in a waiting line.
Ok, so you are inside your INT1 service routine to do whatever it is you need to do. The bouncing relay has set the stage for an unexpected and unwanted re-entry into this service routine. To get rid of the step 1 condition that the bouncing relay has just caused, place the following line as a last statement before you exit the ISR (after your Waitms 10),
GIFR.7 = 1
This bit in GIFR is the flag that gets set by the bouncing relay in step 1. Writing a 1 to this bit will clear the condition and halt the re-entry problem you are experiencing. Also, it "might" be necessarry to increase your 10ms wait. This depends on how long it actually takes for your reed relay to settle. 10ms certainly seems long enough to me but i'm no expert on reed relay bounce time.
I hope this made a little sense? |
|
Back to top |
|
|
Edgar
Joined: 04 Oct 2004 Posts: 11
|
Posted: Fri Oct 22, 2004 3:47 pm Post subject: |
|
|
DToolan wrote: | Edgar,
When you "Disable Int1", you aren't actually disabling the interrupt. What that does is disable a flag in an internal AVR register that means "allow servicing this particular interrupt when it occurs". You can remove those "disable int1 / enable int1" lines from your INT1 service routine.
There is another register that holds the actual INT0 and INT1 flags themselves. When configured, these flags will get set any time an INT0 or INT1 condition occurs (regardless of whether INT0 or INT1 is enabled / disabled).
The INT0/INT1 interrupt process goes something like this.
1. A high or low transition occurs on the INT0/INT1 pin and this, in turn, sets the INT1 flag in a register called GIFR.
2. The processor looks to see if the servicing of interrupts is globally enabled/disabled. This is a flag in a register called SREG.
3. If so, the processor then looks to see if servicing INT1 is enabled or disabled. This is a flag in a register called GMISK.
4. If so, the processor vectors to the INT1 service routine and automatically clears the INT1 flag in GIFR that began this whole process (step 1).
So you see, enabling/disabling INT1 doesn't stop step 1, it only changes (halts the progress of) step 3.
So now let's narrow down your particular problem / condition. When your reed relay first produces a high or low (I don't know what level you have INT1 config'd for), this generates the step 1 condition. With interrupts globally enabled and your INT1 enabled, we progress to step 4 and you are now inside your INT1 service routine. Well, because your reed relay bounces, while you are inside your INT1 service routine, the step 1 condition (flag) gets set again. This won't get handled until you leave your INT1 isr. This is also true for all other interrupts. While the processor is busy inside one interrupt service routine, all other interrupts that occur get placed in a waiting line.
Ok, so you are inside your INT1 service routine to do whatever it is you need to do. The bouncing relay has set the stage for an unexpected and unwanted re-entry into this service routine. To get rid of the step 1 condition that the bouncing relay has just caused, place the following line as a last statement before you exit the ISR (after your Waitms 10),
GIFR.7 = 1
This bit in GIFR is the flag that gets set by the bouncing relay in step 1. Writing a 1 to this bit will clear the condition and halt the re-entry problem you are experiencing. Also, it "might" be necessarry to increase your 10ms wait. This depends on how long it actually takes for your reed relay to settle. 10ms certainly seems long enough to me but i'm no expert on reed relay bounce time.
I hope this made a little sense? |
Thanks a lot for your very extensive answer. I also read more or less the same answer on AVR-freaks. So the bottomline is that interrupts are placed in a que, instead of interrupting the current interrupt service routine. That in fact was my concern. Now knowing this is not the case I can remove the enable and disable statements in the REED_ISR.
I already implemented the GIFR=128 command which indeed works great.
By the way: the 10ms debounce time is way larger than the real debounce time of a reed switch, which is something like a 1 ms or less, depending on the size, of course
Regards,
*edgar* |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You cannot download files in this forum
|
|