How do Pic users here handle input debounce for P.B./Switches?
Hardware or software wise?
Or ?
Max.
Hardware or software wise?
Or ?
Max.
+1. I also debounce it when going open to mitigate the possibility of mechanical jolts banging the closed contacts causing false opens - think forklift running over a bump.In software.
Usually I've sampled switch states in a periodic timer interrupt (which occurs at a rate between 10 kHz and 100 kHz) and require some number of consecutive samples, totaling 10-30 ms, to agree before I'll register a change of switch state and report it.
My recollection from past projects is that I've often used four flags: STATE reports the debounced state of the switch; CHANGE reports that a change of state has occurred; and SW_ON and SW_OFF report switch closure events and switch opening events, respectively. As with your system, the latter three flags operate as semaphores that can be cleared by main code after the switch event is processed.I usually have two flags. One shows the condition of the switch in real time. The other is set once per denounced closure and indicates a new closure.
unsigned char Switches_isSetupPressed()
{
unsigned char pressed;
if (SEL_SWITCH_SETUP_PIN == 1)
return 0;
else
{
__delay_ms(2);
pressed = (SEL_SWITCH_SETUP_PIN == 0);
while (SEL_SWITCH_SETUP_PIN == 0);
return pressed;
}
}
Usually in software. That's the cheapest, most flexible approach. It's conceivable that you could be so resource starved in your PIC that you have to move some of the task externally, but I would imagine in most such situations the added costs would justify a more capable PIC first.How do Pic users here handle input debounce for P.B./Switches?
Hardware or software wise?
Or ?
Max.
I've done it this way (without interrupt timer):Anyone want to share their code? I simply test then wait and test again. Seems to work OK for me on a number of projects. But always looking for something better.
if (GP0 == LL) // if alarm signal is low
{
__delay_ms(DB); // debounce
if (GP0 == LL) // if alarm signal is still low
{
ALM = LH; // ALM status high
}
}
if (GP1 == LL) // if ack is pressed then
{
__delay_ms(DB); // debounce
if (GP1 == LL) // if ack is still pressed then
{
ACK = LH; // ACK status high
}
}
Here's some code for a dsPIC30F3013 showing what I talked about in post #6:I don't use C, Assembly only!
;====================================================================
;
; Demo of IIR-based pushbutton switch debouncing
; Written in ASM30 under MPLAB 8.92 for dsPIC30F3013
;
; Execution time is about 700 nanoseconds w/ 120 MHz clock (30 MIPS)
;
; NOTES:
;
; The pushbutton switch is a normally open switch connected between
; bit PBSWBIT of port PBSWPORT and ground, with an external pullup
; resistor to Vdd.
;
; The constant PBFILT is a 16-bit unsigned fraction in 0.16 format,
; and determines the time constant of the IIR filter. Pushbutton
; is the IIR filter variable.
;
; IIR filter is a first-order filter of the form:
; NewFilterValue = [(1 - K) * PresentFilterValue] + (K * Input)
; where K = PBFILT and Input = pushbutton state (0 or 1).
;
;====================================================================
ProcPB:
; [17] Process pushbutton
;
; debounce pushbutton using IIR filter
;
mov #65536-PBFILT, w0 ; (1-PBFILT) is 16-bit unsigned fraction in 0.16 format
mov Pushbutton, w1 ; Pushbutton is current value of IIR filter in 0.16
mul.uu w0, w1, w2 ; multiply them (16x16-bit unsigned multiply)
clr w0 ; before testing the button, clear w0
btss PBSWPORT, #PBSWBIT ; is button pressed?
mov #PBFILT, w0 ; yes, load w0 with FBFILT; keep zero in w0 if not
add w0, w3, w1 ; add w0 to current state of Pushbutton variable
mov w1, Pushbutton ; and save it.
;
; apply hysteresis to current filter value
;
lsr w1, #14, w1 ; extract upper 2 bits by shifting right 14 places
cp w1, #0 ; are they zero (Pushbutton variable <= 0.25)?
bra Z, ProcPBOff ; yes, process pushbutton OFF condition
cp w1, #3 ; no, are they both set (Pushbutton variable >= 0.75)?
bra Z, ProcPBOn ; yes, process pushbutton ON condition
bra PBProcEnd ; no, pushbutton is in between hysteresis thresholds; do nothing.
ProcPBOff:
;
; Button is in OFF condition. If it was already OFF, do nothing. If it was previously ON,
; set ButtonState to OFF and clear the PBEvents flag.
;
cp0 ButtonState ; button is OFF; was it OFF before?
bra Z, PBProcEnd ; yes, don't do anything
clr ButtonState ; no, set ButtonState to OFF,
bset PBEvents, #BUTTONEVENT ; set BUTTONEVENT flag,
bra PBProcEnd ; and exit.
ProcPBOn:
;
; Button is in ON condition. If it was already ON, do nothing. If it was previously OFF,
; set ButtonState to ON and set the PBEvents flag.
;
cp0 ButtonState ; button is ON; was it ON before?
bra NZ, PBProcEnd ; yes, don't do anything
setm ButtonState ; no, set ButtonState to ON,
bset PBEvents, #BUTTONEVENT ; set BUTTONEVENT flag
bra PBProcEnd ; and exit.
PBProcEnd:
;
; Non-button-related stuff goes here
;
Hi MaxHeadRoom,I don't use C, Assembly only!.
Max.