INPUT_PULLUP, button, debounce and custom counters

Hi again! I’m trying to increment a counter with a button (not the onboard BTN), and it seems all of the debounce code you see with Arduino relies on millis(), which I believe counts forever… but as PB’s time() operator counts between 0 and 1 I am unable to mark the point when the button is initially pressed. BTW, I’m doing this to create a master pattern list that’s separate from the on-board UI, mainly to prevent the user from accidentally resetting the wifi and to have a single master brightness variable, so if there’s a different method I’d love to hear it. Thanks again for this awesome product!

you can ‘fake’ it by making a delta powered counter in beforerender. Make it global, and it’ll count millis for you like millis(). It’ll wrap at 32768, of course, but you can always reset it to zero when the button is pressed, so I suspect that’ll work for you.

1 Like

Check out “Example - Button with debounce” - available on the pattern site around page 6.

Example - Button w_ debounce.epe (3.5 KB)

/*
* Example to use one of the IO pins as a button with debounce logic.
* This example will increment a mode variable.
*/
buttonPin = 4
debounceTimer = 0
lastButtonState = HIGH
mode = 0
numModes = 3

//initialize the pin we're using as a button with a pull-up resistor
pinMode(buttonPin, INPUT_PULLUP)

export function beforeRender(delta) {
  //read the new button state
  var newState = digitalRead(buttonPin)
  //if its the same as the old state, reset the timer
  if (newState == lastButtonState) {
    debounceTimer = 0;
  } else {
    //otherwise add time to the timer
    debounceTimer += delta;
  }
  //if the timer crosses a threshold, then we're sure the state changed
  if (debounceTimer > 50) {
    lastButtonState = newState
    //do something when the new state is low (button pressed)
    if (newState == 0)
      mode = (mode + 1) % numModes
  }
}

export function render(index) {
  h = mode/numModes
  s = 1
  v = 1
  hsv(h, s, v)
}

BTW - millis() in Arduino rolls over about every 49 days (thats 4,294,967,296 milliseconds for anyone counting). It is a source of bugs that can be hard to track down. It can be used to measure periods of time, but requires a certain style and the use of unintuitive features of unsigned integer math. I’d avoid trying to recreate it in pixelblaze. Instead I’d recommend measuring time relatively with some bounds/limits so that it won’t accumulate past the value limits of variables.

2 Likes

I’ve been using the delta accumulation method as a crude timer, the problem is that the interval is variable, and depends on the frame rate.

So you can use it for long time intervals, or periods where you don’t care (like debounce), but you can’t use it for accurate timing.

You probably can’t implement an accurate millis() equivalent anyway, due to the underlying OS timing considerations, but it seems to me that a millis() equivalent is something that should be added to the functions wishlist.

Even if it reports seconds, and wraps every 9 hours or so, there are plenty of known workarounds to deal with this behavior.

1 Like

I’d happily take the low order 32 bits of xTaskGetTickCount()!

I’m with @Nick_W here - even relatively frequent wrapping is reasonably easy to deal with, and the ability to consistently measure smallish intervals would enable the use of some interesting timing dependent hardware. In addition to debouncing, those cheap ultrasonic distance sensors come to mind. We could build a working Pixelblaze “radar”!

For me this feature’s in the “not critical, but sure would be nice to have”, category.

This is perfect, thank you. I thought I had searched thoroughly in the patterns but apparently not hard enough. Much appreciated!