Button press duration after a PIC interrupt

Thread Starter

dayv3

Joined May 22, 2014
38
Hi all, It has been awhile.

Awhile back I wrote a ISR program that tests whether a button press is debounced. but now, I want to
modify the program to test how long the button is pressed, after the interrupt is generated, so that the
program can make decisions about what action to make. My problem is that I do not know how to
approach the problem. If there is anyone that can help me by directing me in the correct direction I
would greatly appreciate it. My previous program was written for a 12F683 but If I need to change the
processor so be it. Once again, Thanks in advance for any help.

Dave
 

MaxHeadRoom

Joined Jul 18, 2013
30,654
Use the IOC and detect the first (say rising) edge and start a timer, the second (falling) edge will stop the timer and capture the duration.
Max.
 

danadak

Joined Mar 10, 2018
4,057
Detect first + edge would start a timer or a SW counter. Now you
have to loop until it meets some consistent on time, the bounce
out period.

Now when first negative edge occurs stop the timer, bounce out the
key, and using test statements on the timer value execute the code
you want that is a f(timer value).


Regards, Dana.
 
Last edited:

JWHassler

Joined Sep 25, 2013
308
You probably already have a timer running, so put something like this in it:
Code:
void One_Msec_ISR(){
if (Button_Down) Button_Counter++;
            else Button_Counter = 0;
if (Button_Counter == DEBOUNCE_MSEC)
    DO_SOMETHING;

  };
 

Thread Starter

dayv3

Joined May 22, 2014
38
Hi all,

Spent some thinking and researching this and this is what I have.
Currently, I am using an ISR that is using timer 0 and it checks that state of the button.
When the state is stable for, say, 20 ms I throw a flag in the ISR that main() picks up.

Now, I want to modify the program so that if the button is pressed and released the circuit will
do what it normally will does. However, if the switch is pressed and held for, say, 2 seconds it will
cause a different behavior when thr button is released. Maybe this is a bit of a rehash but I wanted to make sure
that I stated the problem correctly.

Like I said above, I looked at the problem since I posted my first post, as well as, some of the suggestions
in addition to spending some time looking a various PIC's data sheets. Would using the compare portion of the
Capture/Compare/PWM (CCP) module work? I have never used this but it looks fairly straight forward.
Is this good idea for a path forward? If so, or not, if anyone has some tips or knows of some gotcha's that
I need to be aware of I would appreciate the advice. OR is there a better way? I am open to suggestions.

Dave
 

jpanhalt

Joined Jan 18, 2008
11,087
Hi all,


Now, I want to modify the program so that if the button is pressed and released the circuit will
do what it normally will does. However, if the switch is pressed and held for, say, 2 seconds it will
cause a different behavior when thr button is released.

Dave
Press and release can be detected a few ways (polling, IOC, timer overflow for example). I agree with Max (post#2) that using interrupt on change (IOC) will not tie up the processor as much as polling has the potential to do. Two seconds is a very long time. Some of that "wasted" time can be eliminated by using a timer and interrupt (say Timer 2) to clock the polling. For example, check state on interrupt, then do something else until the next interrupt. An interrupt-driven poll every 100 ms would allow the MCU to do a lot of work during the 2 seconds.

Here's one approach. Assuming you have a timer that will count for 2 seconds and a press-and-release detected by IOC with alternating sign detection (e.g., H>L detects press, then only L>H will be detected or any change) before overflow does Action 1. Upon such release, the timer overflow interrupt is masked (i.e., set timer overflow interrupt enable bit to 0). If no release before overflow, then Action 2. The case of multiple presses would simply restart the timer with each press.
 

MaxHeadRoom

Joined Jul 18, 2013
30,654
If extended time interval measurements are needed you could also look at a 32Khz Xtal on the Timer1 input for a precise 1 sec based clock.
Max.
 

jpanhalt

Joined Jan 18, 2008
11,087
If extended time interval measurements are needed you could also look at a 32Khz Xtal on the Timer1 input for a precise 1 sec based clock.
Max.
My 16-bit TMR1 gives exactly 2 seconds per tick with 32.768 kHz. Easy to preload or capture if you need 1 second. However, since the TS wants a 2-second delay, it would be super simple.
 

Thread Starter

dayv3

Joined May 22, 2014
38
Okay, I looked at the IOC option but I have questions.
The examples that I found used an external trigger (ie: the switch) connected to a port that is configured by the IOC register.
The code that I wrote, from before, debounces the switch with software using a timer0 ISR routine. Is there are way to keep
my software based ISR because I THINK that I already have the state change flags or would I need throw all that away?
What is the best thing to do?

Just my thoughts for now, but I need to think a little more about what jpanhalt (Here's one approach...) and what JWHassler
had to say.

Dave
 
Last edited:

jpanhalt

Joined Jan 18, 2008
11,087
Okay, I looked at the IOC option but I have questions.
The examples that I found used an external trigger (ie: the switch) connected to a port that is configured by the IOC register.
The code that I wrote, from before, debounces the switch with software using a timer0 ISR routine. Is there are way to keep
my software based ISR because I THINK that I already have the state change flags or would I need throw all that away?
What is the best thing to do?
Just my thoughts for now, but I need to think a little more about what jpanhalt (Here's one approach...) and what JWHassler
had to say.

Dave
Hi Dave,

Depend on the datasheet, then refer to examples for additional help if needed.

You can keep TMR0 for debounce as that can run independently from TMR1. No need to throw any code away. There is also TMR2 that can produce an interrupt and with both prescale and postscale set to 1:16 gives you up to 16 bits (Tcy) of time.

For TMR1, from the datasheet:

upload_2018-12-15_3-46-12.png

There are 2 oscillator choices for the 12F683, an external LP crystal (often 32.768 kHz) and the system oscillator (Fosc/4). Assuming your system clock is a few MHz, you can get longer periods using a watch crystal (32 Khz) source. The external crystal is quite easy to add, but does take up 2 pins.
 

jpanhalt

Joined Jan 18, 2008
11,087
I have also ran the small 8 pins such as the 12F683 using the 31Khz internal clock, where processing time is not an issue.
Max.
That (underlined) might vary with the language used. The LP clock in those chips is quite inaccurate. I have seen errors of 20% reported, but have no first hand experience with it.
 

ebp

Joined Feb 8, 2018
2,332
You can do it all with one timer.
Assume the switch input goes HIGH when the switch is pressed.

Configure the timer to generate an interrupt on overflow but to continue to count.
When the very first switch closure rising edge is detected, preload the counter to produce the required debounce period and start it running.
When the timer generates the overflow interrupt, enable the switch input to generate an interrupt on falling edge.
When the switch interrupt is detected, read the counter.
Add the value read from the counter to the original debounce period.

Note that if you used an interrupt to detect the first rising edge from the switch you must disable that interrupt immediately (probably done anyway in the hardware) and not re-enable it until after the debounce period, otherwise you will get spurious interrupts until the bouncing stops.
 

Thread Starter

dayv3

Joined May 22, 2014
38
Ok,

I think the 32.768 kHz crystal is the way to go. Being that I have always used the internal clock are 22pF capacitors okay? But, I will
need to go to a different chip, maybe a 16G628, because I will need the pins back. Which is okay.

But I have other questions, I looked at my code and my TM0 code just cycles (overflows) at 1ms intervals and if the counter, inside the ISR, sees that the switch is in a given state (on or off) a counter in incremented. Once the magic number is reached the counter is reset and a flag for the switch state (1 or 0) and that the switch state changes are set that is then picked up by main(). My question is that, I am now adding a second counter to count how long the button is pressed. I write in C.

I haven't looked at the data sheet* yet, but I can set up another interrupt function to count the switch duration but I do not know where to add the code to do that. Do I add it to main() or do I add it as part of the existing ISR function? I'm just confused.

*(I read someplace that the 18F series supports 2 interrupt vectors and the mid range series only supports one.)

Dave
 

jpanhalt

Joined Jan 18, 2008
11,087
That should be OK. The load on the crystal would be 22/2 = 11 pF plus stray capacitance. Stray capacitance can be significant; some references suggest 2 pF as an approximate amount to add. Your crystal should have a specification for load, if not, two, 22 pF caps is common.
 

Thread Starter

dayv3

Joined May 22, 2014
38
@ebp
Configure the timer to generate an interrupt on overflow but to continue to count...

I thought about what you said and it makes sense. I will be playing with you idea over the next few days. Thanks.

Dave
 
Top