fmas
Posts: 2
Joined: Tue Jun 19, 2018 11:42 pm

wiringPiISR switch bounce

Mon Jul 30, 2018 4:29 am

Hello,

I am trying to include an interrupt with a switch in my code with wiringpi. When i press the swtich it is triggered several times due to bounce and wiringPiISR continues to be called. Is there any way to implement a glitch filter or include a delay in wiringPiISR?

This is the code I've written with C++

Code: Select all

#include <wiringPi.h>
#include <stdio.h>
#include <unistd.h>

int ncount = 1;
int interrupt = 7; //wiringpi gpio 

void myInterrupt(void)
{ 
if (wiringPiISR(interrupt, INT_EDGE_RISING, &myInterrupt) > 0)
{  
printf("Interupt signal %d\n", ncount);
ncount++;
}
}

int main (void)
{ 
wiringPiSetup();
pinMode(interrupt, INPUT);

for (;;)
{
pullUpDnControl(interrupt, PUD_DOWN);
 
wiringPiISR(interrupt, INT_EDGE_RISING, &myInterrupt);
  }
}

Thanks in advance.

fbe
Posts: 371
Joined: Thu Aug 17, 2017 9:08 pm

Re: wiringPiISR switch bounce

Mon Jul 30, 2018 6:21 pm

Code: Select all

#include <wiringPi.h>
#include <stdio.h>

#define PIN_KEY 7

void onKey()
{
    static int previous_key_state = -1;
    static int ncount = 0;
    int key_state = digitalRead(PIN_KEY);
    if (previous_key_state != key_state) {
        previous_key_state = key_state;
        ncount++;
        if (key_state == HIGH) {
            /* Key released */
            printf("Key released %d\n", ncount);
        }
        else {
            /* Key pressed */
            printf("Key pressed %d\n", ncount);
        }
    }
}

int main()
{
    if (wiringPiSetup() < 0) return 1;
    pinMode(PIN_KEY, INPUT);
    pullUpDnControl(PIN_KEY, PUD_UP);
    if (wiringPiISR(PIN_KEY, INT_EDGE_BOTH, &onKey) < 0) return 1;

    while (1) {
        delay(1000 - (millis() % 1000));
    }
}
This helped to solve a similar problem with keys on my 3.2" TFT display. You may add a short delay to the handler function. Only one more handler function call is "cached" while a handler is running. So the second call should happen when the switch state is stable. http://wiringpi.com/reference/priority- ... d-threads/

photomankc
Posts: 80
Joined: Fri Aug 24, 2012 12:58 pm

Re: wiringPiISR switch bounce

Wed Sep 12, 2018 9:23 pm

So one of my favorite debounce methods goes like this.

In the ISR (which is just a thread as I understand it so no need to worry about being as fast as possible) you use say an 8bit integer as a kind of stream input and define a bit pattern that represents the edge you want. So for a clean/sustained rising edge we need to see 01111111b. So when the ISR trips, we do this:

Code: Select all

uint8_t edge = 0x7F    // 01111111
unit8_t stream = 0;
for(int i=0, i<16, i++)
{
    stream <<= 1;
    stream |= digitalRead(pinnum);

    if (stream == edge)
    {
        g_external_flag = true;
        break;
    }

   delay(3);
}
So when the ISR fires we will collect samples of the input and if a nice steady stream of 1's comes in following a 0 over seven samples (21ms) we probably have a good solid button press. If not and we wind up with something like 01101111, then we will collect 3 more samples before it ends up matching the edge pattern. Now, if after 16 samples we don't have a match we give up. If that's happening a lot maybe slow down the loop or get a better switch.

You could handle the second spurious queued interrupt by looking at g_external_flag, if it's still true then return from the ISR without bothering to sample since we have not yet processed the original button press yet. When you're ready to handle another press, clear your flag in the main program.

Just make sure that your edge is always at the far left. Don't use 00001111 as the pattern since it's possible that bounce in the left side will prevent you from making a match on the pattern like this 01001111. In that case you got the four 1's you wanted but can't pick up the edge because the spurious 1 in bit 6 stops it and it will now never match.

rising:
edge = 01111111
stream = 0000000 <-Starting value;

falling:
edge = 10000000
stream = 11111111 <-Starting value

I'm free typing this so hopefully it's not to error-filled but I think you can get the picture.
Last edited by photomankc on Fri Sep 14, 2018 5:13 am, edited 1 time in total.

User avatar
mooblie
Posts: 107
Joined: Fri Oct 14, 2016 2:07 pm
Location: The Scottish Highlands

Re: wiringPiISR switch bounce

Wed Sep 12, 2018 10:57 pm

IMHO, debouncing is best done in hardware, if you're up for that. Two NAND gates, two pull-ups and a SPDT switch are all that is required. Then no software shenanigans are necessary.

photomankc
Posts: 80
Joined: Fri Aug 24, 2012 12:58 pm

Re: wiringPiISR switch bounce

Thu Sep 13, 2018 2:13 am

I can't say that's wrong and if I were going to make a product to go out the door and the part count and cost allowed it I'd say that's better and cleaner software-wise.

In my experience in a hobby environment where you have a range of hardware being attached it's not always so easy to debounce there. So many switches have very different bounce characteristics that a solution that worked well for this switch doesn't work well for that one. Software debounce can be easily implemented as a parameterized function or class that can adapt to whatever.

I'll have to look into what you are describing. I'm always interested in how to get things done in hardware.

User avatar
mooblie
Posts: 107
Joined: Fri Oct 14, 2016 2:07 pm
Location: The Scottish Highlands

Re: wiringPiISR switch bounce

Fri Sep 14, 2018 5:55 pm

As long as you use a SPDT switch that breaks one pole before making the other (like "all" SPDT switches do) then ANY such switch will do, and the two NAND gates are guaranteed to de-bounce it absolutely into a clean single edge.

Image

User avatar
stefanv
Posts: 36
Joined: Wed Oct 19, 2016 12:08 pm
Location: Ontario, Canada
Contact: Website

Re: wiringPiISR switch bounce

Wed Sep 19, 2018 4:28 pm

It's not always possible to arrange for the input to be an SPDT switch. In my Pi-based synthesizer project, the switches were all SPST keyboard switches. There's nothing wrong with debouncing in software.

The technique given by photomankc above is a good one, except there's no need for the loop. Just shift one sample into the 8-bit buffer at each interrupt in the ISR (or at each pass through a polling loop). If, after the most recent shift, the desired pattern has appeared, you have your edge. That way you're not wasting cycles waiting for the edge to appear.
Stefan Vorkoetter: Programmer, hobbyist, amateur watchmaker, pilot, and collector of fountain pens, slide rules, calculators, and watches.

photomankc
Posts: 80
Joined: Fri Aug 24, 2012 12:58 pm

Re: wiringPiISR switch bounce

Thu Sep 20, 2018 2:49 pm

I agree, hardware is good if there is room but I know most developers are going to go with software, it's more flexible and it's not terribly taxing. I know a number of proponents of hardware that have conceded that software debounce is fine.

On the loop, I was under the impression that the ISR would only fire on rising or falling edges, not steady state. In that case I don't see how the ISR can collect the stream of input without a polling loop somehow. It would only execute when a transition had occurred, in OP's case a rise from 0 to 1. This seems to be the case in my implementations so far anyway.

Return to “C/C++”