Hi,
I'm looking for some design help with the logic for a fairly straightforward circuit I've built. Basically, I have a stepper motor that raises or lowers a gate and at each extreme there is a microswitch that is set when the gate slides by. In my PIC I have logic for controlling the movement of the stepper motor (clockwise or anticlockwise) and have also enabled RB7-RB4 change interrupt - the 2 switches are wired to RB4 and RB5. In my ISR I detect which pin has changed state and set a corresponding bit in a status register. The latter are checked during the routine that raises or lowers the gate so that the routine knows when to exit its stepper loop.
It all kinda works, except for the odd occasion when it looks like a switch change might be getting missed. I've come to the conclusion that I need to implement switch debounce and that's where I could use some advice.
I understand how debounce logic works, in fact I've implemented it several times in inline code, but in this case, I'm wondering what might be the best way to design my PIC code so that the switch changes are still detected by the PIC interrupts but somehow a 20ms time delay can be introduced to eliminate switch bounce.
I think that what might be causing my problem is that a state change interrupt (due to bounce) might be happening before I have processed the first one in my ISR and then I really don't know what the behaviour of the PIC will be. Anyhow, here's my current ISR routine to help you understand what I've done so far. Also, note I'm also using RB6 as an activation switch, i.e. it causes the gate to lower.
Thanks for your feedback.
I'm looking for some design help with the logic for a fairly straightforward circuit I've built. Basically, I have a stepper motor that raises or lowers a gate and at each extreme there is a microswitch that is set when the gate slides by. In my PIC I have logic for controlling the movement of the stepper motor (clockwise or anticlockwise) and have also enabled RB7-RB4 change interrupt - the 2 switches are wired to RB4 and RB5. In my ISR I detect which pin has changed state and set a corresponding bit in a status register. The latter are checked during the routine that raises or lowers the gate so that the routine knows when to exit its stepper loop.
It all kinda works, except for the odd occasion when it looks like a switch change might be getting missed. I've come to the conclusion that I need to implement switch debounce and that's where I could use some advice.
I understand how debounce logic works, in fact I've implemented it several times in inline code, but in this case, I'm wondering what might be the best way to design my PIC code so that the switch changes are still detected by the PIC interrupts but somehow a 20ms time delay can be introduced to eliminate switch bounce.
I think that what might be causing my problem is that a state change interrupt (due to bounce) might be happening before I have processed the first one in my ISR and then I really don't know what the behaviour of the PIC will be. Anyhow, here's my current ISR routine to help you understand what I've done so far. Also, note I'm also using RB6 as an activation switch, i.e. it causes the gate to lower.
Rich (BB code):
; start of ISR
ISR CODE 0x0004
; save context
movwf cs_W ; 1 instr
movf STATUS,w ; 1 instr
movwf cs_STATUS ; 1 instr
; Test why ISR has been driven
processInterrupt
btfsc INTCON, RBIF ; RB pin change
call processRBPinChange
goto ISR_END ; 2 instr
processRBPinChange
bcf INTCON, RBIF ; clear interrupt flag ; 1 instr
; compare PORTB with previous state
movf PORTB, w
xorwf stateWord, w
btfsc STATUS,Z
return
; something has changed, store the bitstrip and figure out what
movwf bitStrip
; refresh last state
movf PORTB, w
movwf stateWord
btfsc bitStrip, UPPER_SWITCH
call processUpperSwitchChange
btfsc bitStrip, LOWER_SWITCH
call processLowerSwitchChange
btfsc bitStrip, BUTTON
call processButtonChange
return ; not interested in other changes
;-----------------------------------------
processUpperSwitchChange ; get state of upper switch
btfsc PORTB, UPPER_SWITCH
goto upperSwitchSet
upperSwitchReset
bcf FLAGWORD, UPPER_SWITCH_SET
bcf PORTA, LED_PIN
return
upperSwitchSet
bsf FLAGWORD, UPPER_SWITCH_SET
bsf PORTA, LED_PIN
return
;-----------------------------------------
processLowerSwitchChange ; get state of lower switch
btfsc PORTB, LOWER_SWITCH
goto lowerSwitchSet
lowerSwitchReset
bcf FLAGWORD, LOWER_SWITCH_SET
bcf PORTA, LED_PIN
return
lowerSwitchSet
bsf FLAGWORD, LOWER_SWITCH_SET
bsf PORTA, LED_PIN
return
;-----------------------------------------
processButtonChange ; get state of button
btfsc PORTB, BUTTON
goto buttonSet
buttonReset
bcf FLAGWORD, BUTTON_PRESSED
return
buttonSet
bsf FLAGWORD, BUTTON_PRESSED
return
ISR_END ; restore context then return
movf cs_STATUS,w ; 1 instr
movwf STATUS ; 1 instr
swapf cs_W,f ; 1 instr
swapf cs_W,w ; 1 instr
retfie ; 2 instr
; end ISR