CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Best way to debouce?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kd5uzz



Joined: 28 May 2006
Posts: 56

View user's profile Send private message

Best way to debouce?
PostPosted: Fri Mar 09, 2007 3:30 am     Reply with quote

I'm using a matrix encoded keypad, connected to a MM74C923 keypad decoder. This chip had a built-in debouce function, but I don't have the correct value caps to make use of it.
I figured I could create a debouce function in software tonight and worry about getting the caps another day, but so far I haven't been able to create a working debouce routine. I've tried disabling int_ext inside the ISR, printing the value and enabling int_ext. I'd like to avoid delay_ms(), so I tried using TIMER2 to reenable int_ext after upto 80ms, but that didn't work quite right either.
Ideas?

Code:

 #include <16F877a.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000)             //clock speed
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,ERRORS)

int CheckButton = FALSE;

void Main(){
   int PortVal;
         
   enable_interrupts(INT_EXT);  //INT for B0 (IR or Keypad)
   enable_interrupts(GLOBAL);   //Actually enable them
   
   printf("Keypad Test\n\n\r");
   
   while(TRUE){
      if ((CheckButton == TRUE)) {
         CheckButton = FALSE;         
         PortVal = input_d();         
         printf("Scan Code:%d\n\r",PortVal);
      }
   }
}

#int_ext
   void ButtonPress() {
      CheckButton = TRUE;
   }

kender



Joined: 09 Aug 2004
Posts: 768
Location: Silicon Valley

View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger

PostPosted: Fri Mar 09, 2007 4:03 am     Reply with quote

Push buttons connected to the ISRs would normally require hardware debouncing. But in your case the software debouncing algorithm can be as simple as this:

- Declare a global counter variable
- Set up a timer interrupt, which increments the counter.
- The counter is zeroed in the ISR every time th ISR is called. By the way, the majority of the ISR calls will be caused by the bounce transitions. ISR also sets up a flag like your present code.
- The main loop polls for a flag (just like it does already). When it sees the flag, it waits for 50uS. (Don't remember the exact number. It's somewhere in the tens of uS.) Make sure that the button interrupt remains enabled during this delay.
- After this delay the main loop looks at the counter, if it's below some threshold number - the line is still bouncing. You could wait again or proceed with other things.
- If the counter is above the threshold value, then the line has stopped bouncing. Check the state of the button pin: if it's the same as the flag - you have a legitimate button press. If it's not the same as a flag - the interrupt that have set the flag was caused by some kind of glitch.
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Fri Mar 09, 2007 8:28 am     Reply with quote

Kender has all good points.

I'm not sure if you still have the MM74C923 in the circuit.

If you do, you should follow that circuit. Software debounce
may simply NOT be able to work. That chip has timming that
you must adhear to.
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Re: Best way to debouce?
PostPosted: Fri Mar 09, 2007 10:02 am     Reply with quote

kd5uzz wrote:
I'm using a matrix encoded keypad, connected to a MM74C923 keypad decoder. This chip had a built-in debouce function, but I don't have the correct value caps to make use of it.
I figured I could create a debouce function in software tonight and worry about getting the caps another day, but so far I haven't been able to create a working debouce routine. I've tried disabling int_ext inside the ISR, printing the value and enabling int_ext. I'd like to avoid delay_ms(), so I tried using TIMER2 to reenable int_ext after upto 80ms, but that didn't work quite right either.
Ideas?

Code:

 #include <16F877a.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000)             //clock speed
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,ERRORS)

int CheckButton = FALSE;

void Main(){
   int PortVal;
         
   enable_interrupts(INT_EXT);  //INT for B0 (IR or Keypad)
   enable_interrupts(GLOBAL);   //Actually enable them
   
   printf("Keypad Test\n\n\r");
   
   while(TRUE){
      if ((CheckButton == TRUE)) {
         CheckButton = FALSE;         
         PortVal = input_d();         
         printf("Scan Code:%d\n\r",PortVal);
      }
   }
}

#int_ext
   void ButtonPress() {
      CheckButton = TRUE;
   }



I think a simple solution would be to do this from the interrupt pin; enable a timer interrupt and set the timer to a value that will cause a timer interrupt in xmS. When the timer interrupts the value has been stable for xmS so it is debounced, read the input from the timer interrupt set flag that input has changed.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri Mar 09, 2007 10:07 am     Reply with quote

I posted a little piece of code that works to debounce a switch. Check here: http://www.ccsinfo.com/forum/viewtopic.php?t=24103

Ronald
mat72



Joined: 19 Jan 2006
Posts: 11

View user's profile Send private message

PostPosted: Sun Mar 11, 2007 9:55 am     Reply with quote

I have a bunch of switches that I debounce without using an ISR and it works great. it even picks up on press and release.

Each button has the following structure
Code:

typedef struct {
   BYTE isDirty;
   BYTE value;
   BYTE holdTime;
   unsigned int16 pin;
} DebouncedInput;


My code uses a multi tasking design. I have a task which checks the input every 5ms via the following function:

Code:

void DebounceInput(DebouncedInput *in, BYTE newValue){
   if(in->holdTime <0>value != newValue){ // change has occured
         in->holdTime = DEBOUNCE_DELAY;
         in->value = newValue;
         in->isDirty = 1;   
      }
   }
   else{
      if(in->holdTime)in->holdTime--;
   }
}

each time there is a change in the input value, a hold time for that input is set (DEBOUNCE_DELAY). I have a DEBOUNCE_DELAY of 4 and because the calling task is scheduled to run every 5ms, thats a hold time of 20ms.


note that onInputChange is called every time the debounced input goes from 1 -> 0 or 0->1.
You can also just read from the debouncedInputDevices[i].value.

I find this code works great, as I have a lot of other tasks running and I don't like spending anytime in ISRs or delaying/blocking the processor with delays.
Code:
void taskPollDebounceInput(){
   static BYTE i;
   if(timerPollDebounceInput) return;
   timerPollDebounceInput = TIMER_DEBOUNCE_INPUTS;
   
   for(i = 0; i < numDebouncedInputDevices; i++){
      DebounceInput(&debouncedInputDevices[i], input( (debouncedInputDevices[i].pin) ) );
      
      // there has been a change
      if ( debouncedInputDevices[i].isDirty == 1 ){
         debouncedInputDevices[i].isDirty = 0;
         
         onInputChange(i);
         
      }

   }


}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2005 phpBB Group