Make one-shot from debounce code?[FOUND BETTER CODE]

For Adafruit customers who seek help with microcontrollers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
DanPolka
 
Posts: 108
Joined: Tue Feb 18, 2014 5:31 am

Make one-shot from debounce code?[FOUND BETTER CODE]

Post by DanPolka »

I've tried to make a one-shot from the following debounce code (not mine), and cannot.

I want that when a set of keys is polled, if a key is pressed, it's number will be returned (the debounce code does that), but if it's held down, it will only be returned the first time it's pressed. Then, if it's released, it can again be seen if re-pressed.

Code: Select all

byte check_switches()                                   
{
  static byte previous[4];
  static long time[4];
  byte reading;
  byte pressed;
  byte index;
  pressed = 0;

  for (byte index = 0; index < 4; ++index) {
    reading = digitalRead(14 + index);  // this is where it looks at each switch
    if (reading == LOW && previous[index] == HIGH && millis() - time[index] > DEBOUNCE)
    {
      // switch pressed
      time[index] = millis();
      pressed = index + 1;
      break;
    }
    previous[index] = reading;
  }

  return (pressed);
}
Last edited by DanPolka on Sun Mar 09, 2014 12:19 pm, edited 3 times in total.

User avatar
marshaj847
 
Posts: 43
Joined: Wed Jul 31, 2013 6:12 pm

Re: Make one-shot from debounce code?

Post by marshaj847 »

it may be an order of operations problem... try throwing in some parens

Code: Select all

    if ( (reading == LOW) && (previous[index] == HIGH) && ((millis() - time[index]) > DEBOUNCE) )

DanPolka
 
Posts: 108
Joined: Tue Feb 18, 2014 5:31 am

Re: Make one-shot from debounce code?

Post by DanPolka »

The code as presented is ok for its original purpose, a debounce function; it's copied from a WaveShield library, and functions as written correctly as a debounce.

What I'm looking for is a way to alter the given code so that it will also function as a one-shot; that is, after returning the fact that a particular key has been pressed, if on the next pass through the function that key is still pressed, it should not return again that that key is pressed, until after that key has been released and is again pressed.

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Make one-shot from debounce code?

Post by adafruit_support_mike »

What does the existing code do that you don't want?

DanPolka
 
Posts: 108
Joined: Tue Feb 18, 2014 5:31 am

Re: Make one-shot from debounce code?

Post by DanPolka »

It repeatedly reports that the key is pressed (if it's still held down), instead of just reporting it once.

When the debounce code is called from within a loop, and a key is pressed and held down, the code continues to say that a key is pressed; I want that it NOT continue to say that a key is pressed if it is STILL being pressed, that is, if it has not yet been RELEASED.

I want (or at least wanted) that when a key is pressed, that key is at first reported as having been pressed, but will NOT be subsequently reported as being in a 'down' (pressed) position (when the debounce is again called) until AFTER it is RELEASED and pressed AGAIN.

I was hoping that even though the key scan routine was inside a loop, and therefore continuously repeated, that there could be some way that I could let it know that the key had not been released, and consequently NOT report that it was in a 'down' position.

However, I may have a larger problem in terms of correctly designing the overall intentions regarding causing different actions from pressing different switches and from different actions upon the switches (press&release, press&hold, double-tap); so I'll look into the "Bounce" library.

But I'm confused by the documentation for that library, so I'll ask a more basic question about that library as a new question.

mwilson
 
Posts: 46
Joined: Sun Oct 23, 2011 11:17 am

Re: Make one-shot from debounce code?

Post by mwilson »

It might be that `break;` statement. It exits the routine whenever a key is found pressed. But the routine doesn't update the switch status. `previous[index] = reading;` is only executed when a press is not detected. If that line were repeated before the `break;` ??? (`break;` exits the entire `for` loop.)

I haven't tested anything here. I too am having trouble picking out the consequences of the different switch levels and time limits.

DanPolka
 
Posts: 108
Joined: Tue Feb 18, 2014 5:31 am

Re: Make one-shot from debounce code?

Post by DanPolka »

@mwilson,

Thanks, that does make some sense! I'm not sure whether I'd realized that switch status wasn't updated except when key was not pressed!

What I think I need to be able to do is to prevent the function from returning until after the key is released, allowing it to escape if release happens either within a given short time, or after a longer hold time. The short-time return might approximate a one-shot, and the longer time could reflect a longer hold down of the button.

I do want to allow for other ways of pressing the key, like double-tap and deliberate auto-repeats for certain keys (but not others), but this might be a start!

DanPolka
 
Posts: 108
Joined: Tue Feb 18, 2014 5:31 am

Re: Make one-shot from debounce code?

Post by DanPolka »

I now see that I'm not quite accurate as to what I thought the debounce code is doing in my program; I said,
It repeatedly reports that the key is pressed (if it's still held down), instead of just reporting it once.
But actually for some keys it does NOT cause repeated actions on hold the key down, it only does this for keys whose actions take more than a little bit of time (like outputting speech from WaveShield), which may, I guess, be taking longer than the 100 ms debounce time specified in the program, so when the key-pin is looked at next, it may seem to have been re-pressed, I guess.

I'm now trying to figure out exactly what this debounce code does, so I might alter it to work as I want.

Here's the best I have been able to figure it out so far, any corrections/additions would be appreciated!
(What I'd like to be able to do with it is cut the debounce part out of the scan switches part into a separate function, so I could call it more than once for checking for double-taps, and I'm not sure how to make just the debounce part as a function, passing necessary parameters, etc.)

Code: Select all

byte check_switches()
{
  static byte previous[4];     // array of previous state of button input pins
  static long time[4];      // array of a point in time, reset for & on each keys pressing
  byte reading;       // a momentary reading of the state of a button pin
  byte pressed;       // a return of the PIN NUMBER for a button that has been pressed
  byte index;  // a zero based counter for the for-loop, used to access the (zero based) arrays
  pressed = 0;  // if no button pressed, return zero

  for (byte index = 0; index < 4; ++index) {  // loop through the button pin array, from 0 to 3
    reading = digitalRead(14 + index);    // read each pin in succession as loop progresses
    
    // THIS IS WHERE THE DEBOUNCE OCCURS:
    // it looks to see if the CURRENT immediate state of an button input pin is LOW,
    // AND the last(?) known recorded state of that pin was HIGH, 
    // AND this moment in time (millis()) minus the TIME of the LAST time the key wasn't pressed???? (not sure about this)
    if (reading == LOW && previous[index] == HIGH && millis() - time[index] > DEBOUNCE)
    {
      // switch has been pressed
      time[index] = millis();  // saving the moment in time this button was pressed
      pressed = index + 1;  // accounting for zero-based array index
      break;  // exiting from for loop
    }
    previous[index] = reading;   // not sure why this is HERE, and not ALSO just before the <break>???
  }
  // return switch number (1 - 4)
  return (pressed);
}

DanPolka
 
Posts: 108
Joined: Tue Feb 18, 2014 5:31 am

Re: Make one-shot from debounce code?

Post by DanPolka »

I found some code which seems to do almost all that I want, once I (hopefully!) tweaked it to work with more than one button. It responds to 4 different kinds of keypresses. If anyone else is interested, the original code's at:
http://jmsarduino.blogspot.com/2009/10/ ... -hold.html

Locked
Please be positive and constructive with your questions and comments.

Return to “Microcontrollers”