LCD Shield Kit - Preventing Buttons Repeating?
Moderators: adafruit_support_bill, adafruit

LCD Shield Kit - Preventing Buttons Repeating?

by GuitarPhil on Mon Feb 04, 2013 1:51 pm

Hi!

First off thanks to adafruit for producing this excellent solution to getting user input and displaying on an LCD while minimizing the number of i/o ports needed on the Uno. I am using it as the user interface of a guitar vintage echo effects project.

Part of my project allows the user to enter an alphanumeric name for an effects patch by using the up and down buttons to change the current character in the name, the Select button to step on to the next character in the name and the right button to exit the routine with a string containing the complete name.

The code is contained in a while () loop and is working but, because the loop executes pretty fast, the character often jumps several letters before the user can remove their finger from the up or down button.

Apart from adding a delay in the while() loop is there any way to just accept single button presses and prevent the buttons from 'auto-repeating'?

I'd really appreciate any helpful suggestions :D

Phil.

This is the relevant section of my code ...
Code: Select all | TOGGLE FULL SIZE
void NameSong(void) {

  // Here the code to allow the user to Enter a name for their patch/song

  String song = "                ";  // Initialise to a blank name
  int i = 0;                         // index into the song string
  char c = 'A';                      // current character being edited
  boolean done = false;
  int button = 0;

  lcd.clear();
  lcd.print(c);
 
  done = false;

  while (!done) {

    lcd.setCursor(i,0);
    button = lcd.readButtons();
    if (button & BUTTON_UP) {
      if (++c > 'Z')
        c = 'Z';
      lcd.print(c);
    }
    if (button & BUTTON_DOWN) {
      if (--c < 'A')
        c = 'A';
      lcd.print(c);
    }
    if (button & BUTTON_SELECT) {
      song.setCharAt(i, c);
      lcd.print(c);
      if (++i > 15)
        i = 15;
      c = 'A';
      lcd.setCursor(i,0);
      lcd.print(c);   
    }
    if (button & BUTTON_RIGHT) {
      song.setCharAt(i, c);
      done = true;
    }

    delay(250); // Try to stop button 'auto-repeat'
  }
  for (i = 0; i < 16; i++)
    UserPatch.name[i] = song.charAt(i);
}
GuitarPhil
 
Posts: 3
Joined: Mon Feb 04, 2013 1:11 pm

Re: LCD Shield Kit - Preventing Buttons Repeating?

by adafruit_support_bill on Mon Feb 04, 2013 1:58 pm

You don't need a fixed delay. You can just wait until the button is released before you start polling for the next one.
User avatar
adafruit_support_bill
 
Posts: 30760
Joined: Sat Feb 07, 2009 10:11 am

Re: LCD Shield Kit - Preventing Buttons Repeating?

by GuitarPhil on Mon Feb 04, 2013 2:21 pm

Doh! :oops:

Many thanks for that rapid and helpful reply.

Phil.
GuitarPhil
 
Posts: 3
Joined: Mon Feb 04, 2013 1:11 pm

Re: LCD Shield Kit - Preventing Buttons Repeating?

by adafruit_support_mike on Tue Feb 05, 2013 11:04 pm

There are as many ways to debounce a button as there are people doing it, but here's a software version I like:

Code: Select all | TOGGLE FULL SIZE
void setup () {
    char pinRegister = 0;
    int switchPin = 10;
    boolean switchHigh = false;
}

void loop () {
    pinRegister *= 2;                           //  shift the bits left
    pinRegister += digitalRead( switchPin );    //  append the next bit
   
    //  look for a rising edge
    if (( ! switchHigh) && (127 == pinRegister)) {  //  ( 01111111 )
        switchHigh = true;
        risingEdge();
    }
   
    //  look for a falling edge
    if (( switchHigh ) && (128 == pinRegister)) {   //  ( 10000000 )
        switchHigh = false;
        fallingEdge();
    }

    delay( 10 );
}


It checks the button once every hundredth of a second* and stores the readings as a running sequence of bits. You can think of it as the world's worst digital sampling oscilloscope: eight samples, two values, forming a moving window 0.08s wide.

( * done here with delay() because interrupts load the explanation down with details that aren't relevant to this technique )

Bad as it is, it's still good enough for switch handling. The first if() statement looks for a 0 followed by an unbroken sequence of 1s, which can only occur 0.07s after the switch noise dies out, assuming you hold the switch closed that long. Plotted on a screen, it would be the rising edge of a signal that goes high and stays high for 0.07s. The random 1s and 0s from switch bounce make it impossible for the buffer to match the pattern until everything but the last dip moves past the edge of the window. Keeping the switch pressed down holds the buffer value at 255, which also doesn't match.

The second if() statement looks for the same thing in reverse.. the falling edge following the last high bit of noise after you release the switch.

The boolean keeps short bursts of noise from being registered as rising or falling edges. It also imposes a minimum time between rising edges (in this case 0.14s), but that doesn't cause too many problems for human-speed button presses.
When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product.
User avatar
adafruit_support_mike
 
Posts: 10082
Joined: Thu Feb 11, 2010 2:51 pm

Re: LCD Shield Kit - Preventing Buttons Repeating?

by GuitarPhil on Thu Feb 07, 2013 8:48 pm

I wasn't really needing to debounce the switches. I believe they are debounced in the hardware. My problem was to stop the buttons 'autorepeating' if the user held it down. I only want one press to be detected at a time then, if they release and press again, that's ok.

Would your code solve this?

What I am doing now is: note the initial button press: button = lcd.readButtons; then poll the lcd.readButtons() routine until it returns zero (no button pressed); do the required action, then go back and read the buttons again etc.

Thanks for your help :)

Phil.
GuitarPhil
 
Posts: 3
Joined: Mon Feb 04, 2013 1:11 pm

Re: LCD Shield Kit - Preventing Buttons Repeating?

by adafruit_support_mike on Fri Feb 08, 2013 8:12 pm

GuitarPhil wrote:Would your code solve this?

Yep. You have to release the button before it will register the next press.
When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product.
User avatar
adafruit_support_mike
 
Posts: 10082
Joined: Thu Feb 11, 2010 2:51 pm