Go Down

Topic: Making it easier to debounce switches (Read 5560 times) previous topic - next topic


Sep 26, 2018, 10:51 pm Last Edit: Sep 26, 2018, 10:57 pm by pjrc
EdgeBounce has an interesting approach.  I do not wish to speak too harshly of this library, but in the context of possibly recommending this library for all Arduino users, I believe some thought and testing should go into how it will perform when run on faster chips and with more advanced compiler optimizations.

As I understand the code, it appears to repetitively call digitalRead() 16 times (configurable up to 32).  The timing of the repetitive reads appear to depend only on the CPU speed and the speed of digitalRead().

Code: [Select]
byte EdgeDebounce::debounce(byte pin) {
  unsigned long pinStatus;
  do {
    pinStatus = 0xffffffff;
    for (byte i = 1; i <= MYsensitivity; i++) pinStatus = (pinStatus << 1) | digitalRead(pin);
  } while ((pinStatus != debounceDontCare) && (pinStatus != 0xffffffff));
  return byte(pinStatus & 0x00000001); 

On slow 16 MHz AVR, with a fairly low performance digitalRead() requiring multiple PROGMEM reads, this timing probably works out fairly well.

But consider what will happen on a not-too-distant-future 1 GHz superscaler ARM microcontroller?  Imagine digitalRead() implemented more efficiently.  Or imagine what will happen if the C++ compiler is able to propagate all objects member variables (including the pin number) initialized with constants all the way to this function, and then optimize it and digitalRead() as a compile time const, effectively replacing the function call with just a direct register read from the hardware.  Imagine a future compiler smart enough to even unroll this loop.

In that sort of best case scenario, this code could possibly end up optimized into 16 successive direct hardware register reads running at the the incredible bus speed of a very fast chip.  All 16 reads might end up happening faster than an AVR could execute a single instruction!

I'm also a little concerned about what this code does in the case where the 16 reads aren't all logic high.  It looks as if the case where "pinStatus" isn't all 1s simply returns the most recent reading.  If "MYsensitivity" is 16 and the signal changes on the 14th or 15th reading and has random behavior for some time, wouldn't this return an unpredictable result?  Or maybe I've misunderstood the algorithm?

Go Up