Debouncing the Nordic FOB

I have a Nordic FOB talking to a Transceiver nRF24L01+ Module. I’m using an Atmel Tiny processor with a code fragment from the “Example receiver firmware” refrerence on the SparkFun web page for the FOB.

It is working well, except I frequently get multiple button push detections. So, I want to “debounce” the button push.

I’m wondering about the easiest way to do it, modifying the FOB or receiver firmware.

Currently, the receiver firmware is polling the transceiver in a ISR that fires at most every 256 cycles So, there should be some debouncing inherent in that receiver since the receiver won’t respond to a button detection until it’s polled. Should I just poll the transceiver less frequently? Or should I change the FOB firmware instead?

Thanks,

Dave Thomas

I get no button bounces with the fobs myself.

Simpliest way would probably be to modify your receiver and just change to interrupt instead of polling, then ignore any further reception after a press for 100ms or so.

I do see key bounce when polling the FOB every 33 ms.

I think processing an async interrupt in additon to the existing ISR could really complicate my existing event loop. I think its the same thing to reduce the frequency the transceiver is polled. Eg, Instead once every 256256 cycles, once every 256256*10 cycles. (i’m doing other things besides polling the transceiver in the ISR).

That change (polling at 81 ms, I thing) so far seems to eliminate the bounce, but there is a noticeable delay from button push to seeing the result. Probably doesn’t matter, but I’m going to play with figuring out the minimum “blanking time” required for sufficient debouncing.

I’m still thinking maybe this should be in the FOB. It shouldn’t send consecutive button presses that are any faster than are humanly possible to intentionally execute.

Dave Thomas

You shouldnt have any delay between button presses and response as you could process the results immediately and then just on entering detections check if the debouncing period has expired yet, so it would only effect future presses which should only be bounces anyway. Use a timer if you have one and just check its value on detection, if it is below the bouce time ignore this receive and carry on polling, if it isn’t, then reset the timer, process the data and then continue.

I actually had 327 msec worth of “skipped interrupts” when I noticed the delay.

I played around and it takes about 200 msec to eliminate (so far) the bounce.

I don’t have a spare timer. But instead of just polling more slowly, I could poll at the same rate, take action immediately on detecting the push, then “blank” for N cycles after that.

I’ll try that.

Thanks,

Dave Thomas

I too have this bounce problem with my fob/receiver. I’ve attempted to ‘debounce’ the receiver side several different ways including introducing an initial 250 ms delay but always seem to get an occasional extra signal for one button push. I’m tempted to mess with the fob code but then I have to attach a serial connection to the fob board I don’t want to have to do that just yet.

The using 250 msec “blanking” after detecting a button push solved the bounce problem for me.

No delay introduced, since action occurs on the first message received. I think you have to do the read on the bounces, but ignore the data until the blanking time expires. Otherwise, I think the FOB receiver has it stashed and ready for you, no matter how long you wait to read.

Yes, it should be debounced in the FOB. I want to change that code to get better battery life anyway. When I get a chance to do that, I’ll post the update.

Dave Thomas

Thanks, Dave. I’ll look forward to your post. In the meantime, I’ll try your suggestion.

Paul

I added 500 msec delay in the Nordic FOB and it eliminated the bounce.

There is a trap that I fell into, though. The delay_us function called by delay_ms function that’s in Nordic-FOB-v11.c don’t work when used in function main(). I added enough delay_ms(250) statements so I should have had several seconds minimum time between buttons being recognized. But, I was still getting bounce, and able to key several per second at will.

It probably has something to do with setting up the timer after awaking for sleep. I tried initing the timer like what’s done in the ioinit function before doing the delay. I also tried clearing the pin change interrupt explictly, in case a second pin change while executing code in main was causing the bounce.

I finally gave up trying to debug the delay() functions, and just used _delay_ms instead. This function is included in the AVR library and it doesn’t use a timer at all – it just executes enough cycles for the specified delay.

You need this statement : #include <util/delay.h> for it to compile.

I added two _delay(500) statements after the

sbi(PORTB, TX_CSN); //Deselect chip

No more bounce! And now, since my receiver ISR is simplified, I eliminated some flicker that occurred when the ISR didn’t complete fast enough.

Next, I’m going to eliminate the “key press count” bytes to save some battery life.

I know that this is somewhat of an old post, but I have a few ideas to contribute.

First, why does the de-bouncing delay have to be so long (2x500msec)? I don’t have the proper equipment to measure digital bouncing of buttons, but it should be on the order of less than 10msec of bounce (unless I am missing something about the button design, which I may be).

Second, I think that it would be rather easy to include a feature that transmits both when the button is pressed AND released. I would attempt this, but I don’t have the time or means to write code and test (I am writing this without even owning the Nordic FOB). You could probably just:

  • - check to see if a button was pressed
  • - wait a while (de-bounce delay)
  • - double check that the same button is still pressed //May or may not be necissary
  • - transmit the "button pressed" data
  • - wait until the button state indicates that it depressed
  • - wait a while (de-bounce delay)
  • - double check that the same button is still depressed //May or may not be necissary
  • - transmit the "button released" data
  • You could use this for applications such as remote control of displays, where prolonged holding of the button would result in rapidly scrolling through options, similar to holding down a button on a keyboard. The receiver software would have to be modified in order to recognize that the “button depressed” data had not been received, and you would have to do your own thing from there.

    I implemented the debounce on both the receive and transmit sides–it definitely takes at least 200 milliseconds, and close to 35 milliseconds of delay to reliabliy eliminate unwanted double button pushes. So, I ended up going with 350 millsicond delay in the transmitter.

    Anothter complication is power management. The battery life of the FOB is marginal for my application. The FOB is used 10 hours a day, for 2 or 3 days on a weekend. Probably 75 pushes per hour at most, 50 typical. Some FOBs don’t make it throught the weekend without requiring a battery change. I finally “wised up” and buy the CR2032 batteries in bulk for around $.25 each instead of the $2-5 you can pay at retail stores.

    The FOB code keeps the processor in sleep moe until a button is pushed. Power of the Nordic while transmitting dominates the total power consumption. So, I think transmitting data on both make and break of a button would cut battery life by at least a factor of 2.

    But, if battery life isn’t a consideration, I think transmitting data on both edges could be very useful. I think you’d also need to change tot using Auto-ack and Auto-retransmit to avoid getting into trouble with dropped packets. But, that’s something I want to do anyway.

    Dave Thomas

    I highly recommend danni’s [Efficient key debounce (bulletproof) project on AVRFreaks. (Login required, IIRC) I’ve used it with an ATTiny2313 to replace the keypad controller for my garage door opener and it just worked.](http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=1801&item_type=project)

    On the topic of power manegement ideas, one idea would be to get rid of the extra packets that the Nordic is sending. Looking at the code, it is sending:

  • - Button pressed
  • - High byte of the # of presses
  • - Low byte of the # of presses
  • - blank
  • One could possibly remove all but the first byte of data (the button that was pressed), which would cut down on the amount of time that the Nordic is transmitting, thus cutting down the amount of power that is used. “Technically”, the ATtiny24 would also have less processing to do, leading to less time spent in a “powered-up” state, but that amount of time would be almost undetectable. None the less, saving power is saving power!

    On track with what was said about power consumption and transmitting both the pressed/depressed states, I agree that the ATtiny24 would consume more power while waiting for the button to be depressed. However, I am almost sure that there would be a way around this. I’m not even close to being an expert on this subject, but I think that one could probably check to see if there was a change in pin state, do the debounce stuff and according to the new pin state, transmit data, and then go into sleep mode, and whenever the pin state changed again, an interrupt would be triggered, and you would repeat the process. This would require an interrupt to be triggered by a change in the pin state to any state, and I am pretty sure that you could do this. All of the lifting could be done by the receiver, and you would only need to make the transmitter robust in sending the packets correctly.

    Dave Thomas, do you suppose you could post example code running an ATTiny as the receiver? Having a little trouble getting it to work… My first foray into the world of Tiny :slight_smile:

    ~Mike

    (Sorry to necro a 2010 thread guys)