Options for using peripherals (PCNT?) for switch debouncing
Posted: Wed Jan 10, 2018 1:11 am
The two "classical" ways to debounce a switch in software involve either regular polling followed by a counter, delay or shift register, or use of an interrupt with a timestamp comparison to disregard spurious transitions.
I had an idea to use the counter peripheral (PCNT) to debounce a switch - the idea being that the switch could be used as the control input to a counter such that it would count up when it's asserted, and count down when it isn't. The idea is that the counter might start at, say, 0, and if it counts up to 10 then the switch is considered "pressed", and if it counts down to -10 then it's considered "released". Anywhere in-between is "undecided". Once one of these threshold values is reached, the counter is limited to that value and can only keep the same value, or move back towards the other threshold.
The counter needs a regular and persistent clock to count from. Perhaps a GPIO could be shared with, say, an PWM output channel that is generating the clock pulses at a known rate (say, 1 kHz). Then if the switch is asserted, so is the control signal and the counter will count up. I think the PCNT can be configured to count down when the control signal is de-asserted. If a threshold is reached, a watchpoint interrupt can be used to signal to a task that the switch state has changed.
The main problem seems to be that the maximum/minimum threshold "watchpoints" reset the counter to zero when reached, so I can't see a way for the threshold value to be "held" while the switch state is maintained. However even if the counter is being reset every, say, 10ms, then it acts as an interrupt filter, only generating one switch state interrupt for every 10 or so GPIO transitions. So maybe this is a viable option.
I've noticed that the counter also has a filter, so I wondered if it can be used to debounce the switch signal directly. However the filter length seems to be tied directly to the APB clock, so with a maximum value of 1023 cycles (12.79 us) it isn't long enough for many switches that have bounces in the order of a few milliseconds.
I'm left considering what other ideas are viable on this platform. Although I could just have a dedicated task that sleeps for 1/100th of a second and regularly samples the GPIO to debounce "in software", it would be interesting to see if there's a way to offload this to the hardware.
Any ideas?
I had an idea to use the counter peripheral (PCNT) to debounce a switch - the idea being that the switch could be used as the control input to a counter such that it would count up when it's asserted, and count down when it isn't. The idea is that the counter might start at, say, 0, and if it counts up to 10 then the switch is considered "pressed", and if it counts down to -10 then it's considered "released". Anywhere in-between is "undecided". Once one of these threshold values is reached, the counter is limited to that value and can only keep the same value, or move back towards the other threshold.
The counter needs a regular and persistent clock to count from. Perhaps a GPIO could be shared with, say, an PWM output channel that is generating the clock pulses at a known rate (say, 1 kHz). Then if the switch is asserted, so is the control signal and the counter will count up. I think the PCNT can be configured to count down when the control signal is de-asserted. If a threshold is reached, a watchpoint interrupt can be used to signal to a task that the switch state has changed.
The main problem seems to be that the maximum/minimum threshold "watchpoints" reset the counter to zero when reached, so I can't see a way for the threshold value to be "held" while the switch state is maintained. However even if the counter is being reset every, say, 10ms, then it acts as an interrupt filter, only generating one switch state interrupt for every 10 or so GPIO transitions. So maybe this is a viable option.
I've noticed that the counter also has a filter, so I wondered if it can be used to debounce the switch signal directly. However the filter length seems to be tied directly to the APB clock, so with a maximum value of 1023 cycles (12.79 us) it isn't long enough for many switches that have bounces in the order of a few milliseconds.
I'm left considering what other ideas are viable on this platform. Although I could just have a dedicated task that sleeps for 1/100th of a second and regularly samples the GPIO to debounce "in software", it would be interesting to see if there's a way to offload this to the hardware.
Any ideas?