Arduino Forum

Using Arduino => Programming Questions => Topic started by: Yigiter007 on Feb 26, 2014, 11:09 pm

Title: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 26, 2014, 11:09 pm
I'm trying to program a menu system into my project and I need to debounce multiple buttons. I tried modifying the debounce function to receive a pin number and debounce that pin, but for whatever reason it wouldn't debounce more than one button, now i tried making a separate debounce function for each button and calling each one and it works. The problem is the buttons aren't very responsive and there is a delay before I can press the button again or a different button quickly. Is there a problem with my code getting delayed or is the program at a different spot when a another button is pressed. I don't know if I should go back and make a combined debounce function that receives a pin or if I can fix this. I can't post the code here since its too big. So i uploaded the file for everyone to see. Thank you in advance for any responses.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 26, 2014, 11:49 pm
Here is my attempt to make a debounce function that receives a pin number. It works when its called once if its called again neither button works.

Quote

const int buttonPin6 = 6;    // the number of the pushbutton pin
const int buttonPin7 = 7;    // the number of the pushbutton pin
const int buttonPin8 = 8;    // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin


int buttonState;             // the current reading from the input pin
int lastButtonState=HIGH;   // the previous reading from the input pin
long lastDebounceTime = 0;  // the last time the output pin was toggled
int ledState=LOW;         // the current state of the output pin
long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin6, INPUT);
  pinMode(buttonPin7, INPUT);
  pinMode(buttonPin8, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
debounce(buttonPin8);
debounce(buttonPin9);

}

int debounce(int buttonPin)
{
  int reading = digitalRead(buttonPin);
  if (reading != lastButtonState)
  {lastDebounceTime = millis();}
  
  if ((millis() - lastDebounceTime) > debounceDelay)
  {
    if (reading != buttonState)
    {
      buttonState = reading;

      if (buttonState == LOW)
      {
        ledState = !ledState;
      }
    }
  }
  
  // set the LED:
  digitalWrite(ledPin, ledState);

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState = reading;
}

Title: Re: Problem debouncing multiple buttons
Post by: Jiggy-Ninja on Feb 27, 2014, 12:08 am
indiYou only have a single lastDebounceTime variable. You need one for each button. You also need a previousState for each button, and a buttonState variable for each individual button.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 27, 2014, 12:11 am
In my first post I have a variable for each debounce function for each pin.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 27, 2014, 04:45 am
I've done some more testing and i figured out that i have to hold the button down longer for debounce to notice it. I tried changing debouncedelay down and up and it doesn't affect it.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 27, 2014, 06:25 am
I also tried putting debounce call functions in a switch case but the same thing happens.

Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Feb 27, 2014, 06:57 am
You have to use arrays to hold everything, button pins, last states and previous times. Have a counter based on the number of buttons you have ie 2. Use an IF statement to increment the counter if it is less then the number of buttons, and reset counter to 0 if it goes over the number of buttons.

You can use the same debounce sketch you have for the one button, but now make everything arrays.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 27, 2014, 08:05 pm
So I put all the variables for debounce into arrays along with any other variables I have that have similar functions. I only have one debounce function that gets sent a pin and it debounces that pin and it works and sees all the pins and I'm able to display it on my GLCD and the LED pin 13 lights up when I press it the buttons, BUT the response time is very slow for the buttons and I still have to keep the button pushed down an second for two for it to read. I think there is something wrong with the way i'm testing the debounce pins. Because its the same if there is separate functions for if the variables are in arrays or not. I think the code is lagging behind as it makes each look to test the buttons, so it i press a button normally it might not be in the section of the loop that's testing that button. Do i need to setup interrupts or change the for/switch setup for debounce? I posted my so that you can see it. I posted the file of my and the code itself (I hope it doesn't look too awkward in the forum or break any forum rules.) Thanks in advance for any responses.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 27, 2014, 08:09 pm
/*00000000      Libraries included    00000000*/

#include <SerialGraphicLCD.h>
#include <SoftwareSerial.h>

/*00000000      GLCD screen size  00000000*/

#define maxX 127//159
#define maxY 63 //127

/*00000000      variables for PINS    00000000*/

//Bup Bdown Bleft Bright Bcenter But1 But2 But3
const int buttonPin[8]={4,5,6,7,8,9,10,11};
const int ledPin13 = 13;       // the number of the LED pin

/*00000000    variables for debounce    00000000*/

//Bup Bdown Bleft Bright Bcenter But1 But2 But3
int buttonNumber[8]={0,1,2,3,4,5,6,7};
int buttonState[8];
int lastButtonState[8]={HIGH,HIGH,HIGH,HIGH,HIGH,HIGH,HIGH,HIGH};
long lastDebounceTime[8];
long debounceDelay[8]={10,10,10,10,10,10,10,10};
int reading[8];
int ledState=LOW;         // the current state of the output pin

/*00000000    buttonlook variables for buttons    00000000*/

int buttonlook[8]={0,0,0,0,0,0,0,0}; //variables to store if button is pressed for pin10

/*00000000    variables for menus    00000000*/

int menustack[6]={1,0,0,0,0,0}; //array acting as stack for menu porder when hopping from one menu to the other.
                               // set array size to number of menus desired
int currentmenuspot=1;
int prevmenuspot=1;
int menustackspot=0;
int menunumber;

int menupage=0; //0=Mainmenu 1=AirQ 2=TEMP 3=HEART 4=MORE
int optionrow[4][4]={{11,12,13,14},{21,22,23,24},{31,32,33,34},{41,42,43,44}}; //2D array as a map for menu options
int optionspotx=0;
int optionspoty=0;

int enterbuttons[4]={0,0,0,0}; //debounce puts a 1 to be later tested if button was pressed 1=pressed 0=not pressed

/*00000000    LCD class declaration    00000000*/
LCD LCD;
/*00000000    SETUP    00000000*/

void setup()
{
  pinMode(buttonPin[0], INPUT);     //button on pin 4
  pinMode(buttonPin[1], INPUT);     //button on pin 5
  pinMode(buttonPin[2], INPUT);     //button on pin 6
  pinMode(buttonPin[3], INPUT);     //button on pin 7
  pinMode(buttonPin[4], INPUT);     //button on pin 8
  pinMode(buttonPin[5], INPUT);     //button on pin 9
  pinMode(buttonPin[6], INPUT);     //button on pin 10
  pinMode(buttonPin[7], INPUT);     //button on pin 11

  pinMode(ledPin13, OUTPUT);   // pin 13 on board LED
  LCD.setBacklight(20);
  LCD.clearScreen();

  LCD.setHome();
  LCD.printStr(" Program starts in "); //displays "program is starting in 10/9/8 etc"
   
  for(int i = 5; i >= 0; i--) //splash screen
    {
      LCD.setX(113);
      LCD.setY(0);
      LCD.printNum(i);
      delay(500);
    }
  LCD.clearScreen();
  delay(500);
}

/*00000000    LOOP    00000000*/

void loop()
{
 
selectmove(); //retrieves states of buttons to see if they were pressed
optionrowdisplay(); //display if buttons were pressed

}

/*00000000    displays when buttons are pressed     00000000*/

void optionrowdisplay()
{
  LCD.setHome();
  LCD.printStr("x spot ");
  delay(50);
  LCD.setX(50);
  LCD.setY(00);
  LCD.printNum(optionspotx);
  delay(50);
 
  LCD.setX(0);
  LCD.setY(9);
  LCD.printStr("y spot ");
  delay(50);
  LCD.setX(50);
  LCD.setY(9);
  LCD.printNum(optionspoty);
  delay(50);
 
  LCD.setX(0);
  LCD.setY(18);
  LCD.printStr("center but ");
  delay(50);
  LCD.setX(70);
  LCD.setY(18);
  LCD.printNum(enterbuttons[1]);
  delay(50);
 
  LCD.setX(0);
  LCD.setY(27);
  LCD.printStr("button 1 ");
  delay(50);
  LCD.setX(70);
  LCD.setY(27);
  LCD.printNum(enterbuttons[0]);
  delay(50);

}

void selectmove()
{
 
for(int i=0; i<8; i++)
{
cleardebounce(); //clears debounces variables
debounce(buttonNumber); //debounces input pins
if(buttonlook==1) //loops through all the pins
{

  switch(i)
          {
              case 0:        //action for when Bup button is pressed
                if(optionspoty!=3)
                  {
                    optionspoty=optionspoty+1;
                  }
                break;

              case 1:       //action for when Bdown button is pressed
                if(optionspoty!=0)
                  {
                    optionspoty=optionspoty-1;   
                  }
                break;
               
              case 2:        //action for when Bleft button is pressed
                if(optionspotx!=0)
                  {
                    optionspotx=optionspotx-1;
                  }
                break;
               
              case 3:        //action for when Bright button is pressed
                if(optionspotx!=3)
                  {
                    optionspotx=optionspotx+1;
                  }
                break;
               
              case 4:        //action for when Bcenter button is pressed
                    enterbuttons[0]=1;
                break;
               
              case 5:        //action for when But1 button is pressed
                    enterbuttons[1]=1;
                break;
               
              case 6:        //action for when But2 button is pressed
                    enterbuttons[2]=1;
                break;
               
              case 7:        //action for when But3 button is pressed
                    enterbuttons[3]=1;
                break;
               
            }

}


}

}

/*00000000   debounce functions    00000000*/


void cleardebounce() //clears variables so that they may be retested. Must be called before each debounce.
{
  for(int i=0; i<7; i++)
    {
      buttonlook=0;
    }
   
  for(int i=0; i<3; i++)
    {
      enterbuttons=0;
    }
}

/*00000000   debounce   00000000*/

int debounce(int buttonNumber) //recieves a pin and debounces that pin
{
  reading[buttonNumber] = digitalRead(buttonPin[buttonNumber]);
  if (reading[buttonNumber] != lastButtonState[buttonNumber])
  {lastDebounceTime[buttonNumber] = millis();}
 
  if ((millis() - lastDebounceTime[buttonNumber]) > debounceDelay[buttonNumber])
  {
    if (reading[buttonNumber] != buttonState[buttonNumber])
    {
      buttonState[buttonNumber] = reading[buttonNumber];

      if (buttonState[buttonNumber] == LOW)
      {
        ledState = !ledState;
        buttonlook[buttonNumber]=1;        //changes variable to 1 to be later tested if true
      }
    }
  }
 
  // set the LED:
  digitalWrite(ledPin13, ledState);// lights the LED so you know button was pressed

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState[buttonNumber] = reading[buttonNumber];
}
Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Feb 27, 2014, 08:55 pm
Those delay even though they are small, they will slow the code down incorrectly. Look into the Blink without Delay sketch to replace those delays.

As for the debounce code.
Code: [Select]
/*
Debounce
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Debounce
*/

// constants won't change. They're used here to
// set pin numbers:
const byte MAX_PINS = 4; // how many buttons to look for
const byte buttonPin[MAX_PINS] = {A0,A1,A2,A3}; // Number of buttons
const byte ledPins[MAX_PINS] = {13,12,11,10}; // the number of the LEDs
const long debounceDelay = 50; // the debounce time; increase if the output flickers

byte counter=0;
boolean currentState[MAX_PINS]; // Initial storage for the state of the button
boolean buttonState[MAX_PINS]; // the current state from the input pin
boolean lastButtonState[MAX_PINS] = {LOW,LOW,LOW,LOW}; // the previous state from the input pin
long lastDebounceTime[MAX_PINS] = {0,0,0,0}; // the last time the output pin was toggled

void setup()
{
  for(byte i = 0; i <= MAX_PINS; i++)
  {
    pinMode(buttonPin[i], INPUT); //set button states
    pinMode(ledPins[i], OUTPUT); // set LED states
  }
}

void loop()
{
  counter < MAX_PINS? counter++ : counter = 0;

  currentState[counter] = digitalRead(buttonPin[counter]);// look at button input and record it.
 
  if (currentState[counter] != lastButtonState[counter]) // Check to see if the state has changed, indicating button is not held
    lastDebounceTime[counter] = millis();

  if ((millis() - lastDebounceTime[counter]) > debounceDelay) // check debounce time
    buttonState[counter] = currentState[counter];
 
  digitalWrite(ledPins[counter], buttonState[counter]); // light specific LED
 
  lastButtonState[counter] = currentState[counter]; // save current state to last state
  //Serial.print("counter: ");
  //Serial.print(counter);
  //Serial.println();

}

This can be made into a function like how you have yours, then all you need to return is "buttonState[counter]"
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 28, 2014, 02:31 am
so i took the blinknodelay and turned it into a function.  The on board LED now responses very well proving you right HazardsMind. The only thing now is the screen is now going crazy with the things its suppose to display and displaying the desired text all over the screen in random spots. Here is the function below.

const int ledPin =  13;          // the number of the LED pin
int ledState = LOW;              // ledState used to set the LED
long previousMillis[100];        // will store last time LED was updated
unsigned long currentMillis[100];
int actionstate;                 //variable to check if request time has been passed
long interval;                   // interval at which to blink (milliseconds)

void setup()
{
  pinMode(ledPin, OUTPUT);      // set the digital pin as output:
  for(int i=0; i>99; i++){previousMillis=0;}// fills array with zeros
}

void loop()
{
actionstate=timecheck(1000, 1);  //first number is amount to be delayed second is to change array spot for each call of function
if(actionstate==1){ledswap();}   //if sent time has passed if statement is true function will be run. Insert delayed function here
}

int timecheck(long interval, int i)
{
  currentMillis = millis();

  if(currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;   // save the last time function was performed
      actionstate = 1;
    }
  else
    {actionstate = 0;}
 
return actionstate;
}

void ledswap() // test function to call and do something
{
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
}
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 28, 2014, 02:36 am
Here is an example of how i am using it. (whole code is included in attached file.)

Quote

actionstate=timecheck(50, 0);  
if(actionstate==1)
{
 LCD.setHome();
 LCD.printStr("x spot ");
}
 
actionstate=timecheck(50, 1);  
if(actionstate==1)
{
 LCD.setX(50);
 LCD.setY(00);
 LCD.printNum(optionspotx);
}

Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 28, 2014, 03:16 am
i noticed that it display numbers correctly, like when i use
Code: [Select]
LCD.printNum(optionspoty), but when i try to print out a string using
Code: [Select]
LCD.printStr("x spot "); it bugs out. Maybe there is something with the buffer or something when i try to display text at high speeds. I also tried displaying the text once and then the values repetitively. and it still bugs out.
Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Feb 28, 2014, 04:04 am
Can you please fix you post and put your code inside code tags. Its the # symbol above the smiley faces.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Feb 28, 2014, 05:34 am
did i fix it correctly?
Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Feb 28, 2014, 05:43 am
Post your full code in code tags.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 01, 2014, 06:51 pm
Whole code was too big for one comments I split it among two comments
Quote

/*00000000      Libraries included    00000000*/

#include <SerialGraphicLCD.h>
#include <SoftwareSerial.h>

/*00000000      GLCD screen size  00000000*/

#define maxX 127//159
#define maxY 63 //127

/*00000000      variables for PINS    00000000*/

//Bup Bdown Bleft Bright Bcenter But1 But2 But3
const int buttonPin[8]={4,5,6,7,8,9,10,11};
const int ledPin13 = 13;       // the number of the LED pin

/*00000000    variables for debounce    00000000*/

//Bup Bdown Bleft Bright Bcenter But1 But2 But3
int buttonNumber[8]={0,1,2,3,4,5,6,7};
int buttonState[8];
int lastButtonState[8]={HIGH,HIGH,HIGH,HIGH,HIGH,HIGH,HIGH,HIGH};
long lastDebounceTime[8];
long debounceDelay[8]={10,10,10,10,10,10,10,10};
int reading[8];
int ledState=LOW;         // the current state of the output pin

/*00000000    delay replacement is timecheck variables    00000000*/

long previousMillis[100];        // will store last time LED was updated
unsigned long currentMillis[100];
int actionstate;
long interval;
int optionrowTextDisplayCounter=false;

/*00000000    buttonlook variables for buttons    00000000*/

int buttonlook[8]={0,0,0,0,0,0,0,0}; //variables to store if button is pressed for pin10

/*00000000    variables for menus    00000000*/

int menustack[6]={1,0,0,0,0,0}; //array acting as stack for menu porder when hopping from one menu to the other.
                               // set array size to number of menus desired
int currentmenuspot=1;
int prevmenuspot=1;
int menustackspot=0;
int menunumber;

int menupage=0; //0=Mainmenu 1=AirQ 2=TEMP 3=HEART 4=MORE
int optionrow[4][4]={{11,12,13,14},{21,22,23,24},{31,32,33,34},{41,42,43,44}}; //2D array as a map for menu options
int optionspotx=0;
int optionspoty=0;

int enterbuttons[5]={0,0,0,0,0}; //debounce puts a 1 to be later tested if button was pressed 1=pressed 0=not pressed
int enterbuttoncounter[5]={0,0,0,0,0};

/*00000000    LCD class declaration    00000000*/
LCD LCD;
/*00000000    SETUP    00000000*/

void setup()
{
  
  pinMode(buttonPin[0], INPUT);     //button on pin 4
  pinMode(buttonPin[1], INPUT);     //button on pin 5
  pinMode(buttonPin[2], INPUT);     //button on pin 6
  pinMode(buttonPin[3], INPUT);     //button on pin 7
  pinMode(buttonPin[4], INPUT);     //button on pin 8
  pinMode(buttonPin[5], INPUT);     //button on pin 9
  pinMode(buttonPin[6], INPUT);     //button on pin 10
  pinMode(buttonPin[7], INPUT);     //button on pin 11
 
  pinMode(ledPin13, OUTPUT);   // pin 13 on board LED
  
  for(int i=0; i>99; i++){previousMillis=0;}
  
  LCD.setBacklight(20);
  LCD.clearScreen();

  LCD.setHome();
  LCD.printStr(" Program starts in "); //displays "program is starting in 10/9/8 etc"
    
  for(int i = 5; i >= 0; i--) //splash screen
    {
      LCD.setX(113);
      LCD.setY(0);
      LCD.printNum(i);
      delay(500);
    } 
  LCD.clearScreen();
  delay(500);
}

/*00000000    LOOP    00000000*/

void loop()
{
  
selectmove(); //retrieves states of buttons to see if they were pressed
optionrowValueDisplay(); //display if buttons were pressed
optionrowTextDisplay();

}

/*00000000    displays when buttons are pressed     00000000*/

void optionrowValueDisplay()
{

actionstate=timecheck(200, 1);  
if(actionstate==1)
{
  LCD.setX(50);
  LCD.setY(00);
  LCD.printNum(optionspotx);
}

actionstate=timecheck(200, 3);  
if(actionstate==1)
{
  LCD.setX(50);
  LCD.setY(9);
  LCD.printNum(optionspoty);
}

actionstate=timecheck(200, 5);  
if(actionstate==1)
{
  LCD.setX(70);
  LCD.setY(18);
  LCD.printNum(enterbuttoncounter[0]);
}

actionstate=timecheck(200, 7);  
if(actionstate==1)
{
  LCD.setX(70);
  LCD.setY(27);
  LCD.printNum(enterbuttoncounter[1]);
}

actionstate=timecheck(200, 12);  
if(actionstate==1)
{
  LCD.setX(70);
  LCD.setY(36);
  LCD.printNum(enterbuttoncounter[2]);
}

actionstate=timecheck(200, 13);  
if(actionstate==1)
{
  LCD.setX(70);
  LCD.setY(45);
  LCD.printNum(enterbuttoncounter[3]);
}


}

Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 01, 2014, 06:51 pm
Quote

void optionrowTextDisplay()
{
  
if(optionrowTextDisplayCounter==true)
  {
      actionstate=timecheck(125, 0);  
      if(actionstate==1)
        {
          LCD.setHome();
          LCD.printStr("x spot ");
        }
      actionstate=timecheck(125, 2);  
      if(actionstate==1)
        {
          LCD.setX(0);
          LCD.setY(9);
          LCD.printStr("y spot ");
        }
      actionstate=timecheck(125, 4);  
      if(actionstate==1)
        {
          LCD.setX(0);
          LCD.setY(18);
          LCD.printStr("center but ");
        }
      actionstate=timecheck(125, 6);  
      if(actionstate==1)
        {
          LCD.setX(0);
          LCD.setY(27);
          LCD.printStr("button 1 ");
        }
     optionrowTextDisplayCounter=true;
  }
}

void selectmove()
{
  
for(int i=0; i<8; i++)
{
cleardebounce(); //clears debounces variables
debounce(buttonNumber); //debounces input pins
if(buttonlook==1) //loops through all the pins
{

  switch(i)
          {
              case 0:        //action for when Bup button is pressed
                if(optionspoty!=3)
                  {
                    optionspoty=optionspoty+1;
                  }
                break;

              case 1:       //action for when Bdown button is pressed
                if(optionspoty!=0)
                  {
                    optionspoty=optionspoty-1;   
                  } 
                break;
               
              case 2:        //action for when Bleft button is pressed
                if(optionspotx!=0)
                  {
                    optionspotx=optionspotx-1;
                  } 
                break;
                
              case 3:        //action for when Bright button is pressed
                if(optionspotx!=3)
                  {
                    optionspotx=optionspotx+1;
                  } 
                break;
                
              case 4:        //action for when Bcenter button is pressed
                    enterbuttons[0]=1;
                    ++enterbuttoncounter[0];
                break;
                
              case 5:        //action for when But1 button is pressed
                    enterbuttons[1]=1;
                    ++enterbuttoncounter[1];
                break;
                
              case 6:        //action for when But2 button is pressed
                    enterbuttons[2]=1;
                    ++enterbuttoncounter[2];
                break;
                
              case 7:        //action for when But3 button is pressed
                    enterbuttons[3]=1;
                    ++enterbuttoncounter[3];
                break;
               
            }

}


}

}

/*00000000   debounce functions    00000000*/


void cleardebounce() //clears variables so that they may be retested. Must be called before each debounce.
{
  for(int i=0; i<7; i++)
    {
      buttonlook=0;
    }
    
  for(int i=0; i<4; i++)
    {
      enterbuttons=0;
    }
}

/*00000000   debounce   00000000*/

int debounce(int buttonNumber) //recieves a pin and debounces that pin
{
  reading[buttonNumber] = digitalRead(buttonPin[buttonNumber]);
  if (reading[buttonNumber] != lastButtonState[buttonNumber])
  {lastDebounceTime[buttonNumber] = millis();}
  
  if ((millis() - lastDebounceTime[buttonNumber]) > debounceDelay[buttonNumber])
  {
    if (reading[buttonNumber] != buttonState[buttonNumber])
    {
      buttonState[buttonNumber] = reading[buttonNumber];

      if (buttonState[buttonNumber] == LOW)
      {
        ledState = !ledState;
        buttonlook[buttonNumber]=1;        //changes variable to 1 to be later tested if true
      }
    }
  }
  
  // set the LED:
  digitalWrite(ledPin13, ledState);// lights the LED so you know button was pressed

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState[buttonNumber] = reading[buttonNumber];
}

/*00000000   timecheck   00000000*/

int timecheck(long interval, int i)
{
  currentMillis = millis();
 
  if(currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;   // save the last time function was performed
      actionstate = 1;
    }
  else
    {actionstate = 0;}
  
return actionstate;
}

Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 01, 2014, 06:56 pm
For whatever reason when I post the code in the comments in forum code format it took out the brackets next to my variables. in
Code: [Select]
int timecheck(long interval, int i) each variable is a spot in an array, so
Code: [Select]
currentMillis is actually
Code: [Select]
currentMillis[i] where the function sends i a place in the array for that particular call so that the values of timecheck are stores and different from other times the function is called.
Title: Re: Problem debouncing multiple buttons
Post by: 68tjs on Mar 01, 2014, 06:58 pm
Have a look on boards schematics (Arduino, Texas, NXP, ST etc....) all use hardware debouncing , not software debouncing.
Put a capacitor in parallel with switch button (100nF)  it will works simply.
Title: Re: Problem debouncing multiple buttons
Post by: Jiggy-Ninja on Mar 01, 2014, 07:14 pm
That's because you used Quote tags instead of Code tags.

I use a struct for my buttons, with an appropriate debounce function like this:
In a separate button.h file (because Arduino IDE is stupid about function prototypes):
Code: [Select]
#ifndef DEBOUNCE_H
#define DEBOUNCE_H

typedef struct
{
  unsigned char pin;
  unsigned char level;
  unsigned char edge;
  unsigned char prev_level;

  unsigned long t_prev_ms;
  unsigned long debounce_delay;
} button_t;

void debounce_button( button_t* );
void init_button( button_t*, unsigned char, unsigned long, unsigned char=1 );

#endif

In button.c
Code: [Select]
#include "Arduino.h"
#include "button.h"

void debounce_button( button_t *b )
{
  unsigned long t_now_ms = millis();
  byte curr_level = digitalRead( b->pin );

  // Edge can only be active for one cycle.
  // Clear it at the beginning.
  b->edge = 0;
 
  // If the button level has changed, reset the debounce timestamp.
  if( curr_level != b->prev_level )
    b->t_prev_ms = t_now_ms;

  // If the debounce timer has not been reset for the duration of the debounce interval,
  // The current state is valid.
  if( t_now_ms - b->t_prev_ms > b->debounce_delay )
  {
    // If the new level is different from the old,
    //  set the edge flag.
    if( b->level != curr_level )
      b->edge = 1;
    b->level = curr_level;
  }
  b->prev_level = curr_level;
}

void init_button( button_t *b, unsigned char pin, unsigned long debounce, unsigned char level )
{
  b->pin = pin;
  b->level = level;
  b->edge = 0;
  b->prev_level = level;
  b->t_prev_ms = 0;
  b->debounce_delay = debounce;
}

I made a library out of my code for my own use, but you can adapt it to how you need. Instead of using a struct like I did, you can use parallel arrays to achieve the same thing.

On thing I strongly recommend against, do not perform actions in your debounce function. Your debounce function should strictly determine the state of the switch.

Here's a sample sketch I used for 1 button:
Code: [Select]
#include "button.h"

button_t button;
byte LED_level = LOW;

void setup() {
  // put your setup code here, to run once:
  init_button( &button, 12, 50 );
 
  pinMode( button.pin, INPUT_PULLUP );
  pinMode( 13, OUTPUT );
}

void loop() {
  // put your main code here, to run repeatedly:
  debounce_button( &button );
 
  if( (button.level==LOW) && button.edge )
  {
    LED_level = (LED_level==HIGH) ? LOW : HIGH;
  }
 
  digitalWrite( 13, LED_level );
}
Title: Re: Problem debouncing multiple buttons
Post by: graynomad on Mar 02, 2014, 12:06 am
Quote
For whatever reason when I post the code in the comments in forum code format it took out the brackets next to my variables.

CODE tags, not a quote. [ i ] is a BB code for italics.

Go back and change your posts.

______
Rob
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 06, 2014, 09:04 pm
On a scale of one to ten my programming skills are a 2 maybe 3. I don't know how to do structs, i haven't seen them before or quite understand them. Can I take your code as is and plug it into mine and just change the names of the calls? I don't mind learning about them i just need a little guidance.
Title: Re: Problem debouncing multiple buttons
Post by: graynomad on Mar 06, 2014, 11:10 pm
So you are ignoring our (multiple) requests for code tags. Good luck with the project.

______
Rob
Title: Re: Problem debouncing multiple buttons
Post by: Grumpy_Mike on Mar 06, 2014, 11:18 pm
Quote
On a scale of one to ten my programming skills are a 2 maybe 3.

And on a scale of one to ten you social skills are a -5.

If you will not do what is asked of you, for the very good reason of the forum software not mangling your code then why should any one help you?
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 09, 2014, 08:22 pm
Code: [Select]
/*00000000      Libraries included    00000000*/

#include <SerialGraphicLCD.h>
#include <SoftwareSerial.h>

/*00000000      GLCD screen size  00000000*/

#define maxX 127//159
#define maxY 63 //127

/*00000000      variables for PINS    00000000*/

//Bup Bdown Bleft Bright Bcenter But1 But2 But3
const int buttonPin[8]={4,5,6,7,8,9,10,11};
const int ledPin13 = 13;       // the number of the LED pin

/*00000000    variables for debounce    00000000*/

//Bup Bdown Bleft Bright Bcenter But1 But2 But3
int buttonNumber[8]={0,1,2,3,4,5,6,7};
int buttonState[8];
int lastButtonState[8]={HIGH,HIGH,HIGH,HIGH,HIGH,HIGH,HIGH,HIGH};
long lastDebounceTime[8];
long debounceDelay[8]={10,10,10,10,10,10,10,10};
int reading[8];
int ledState=LOW;         // the current state of the output pin

/*00000000    delay replacement is timecheck variables    00000000*/

long previousMillis[100];        // will store last time LED was updated
unsigned long currentMillis[100];
int actionstate;
long interval;
int optionrowTextDisplayCounter=false;

/*00000000    buttonlook variables for buttons    00000000*/

int buttonlook[8]={0,0,0,0,0,0,0,0}; //variables to store if button is pressed for pin10

/*00000000    variables for menus    00000000*/

int menustack[6]={1,0,0,0,0,0}; //array acting as stack for menu porder when hopping from one menu to the other.
                               // set array size to number of menus desired
int currentmenuspot=1;
int prevmenuspot=1;
int menustackspot=0;
int menunumber;

int menupage=0; //0=Mainmenu 1=AirQ 2=TEMP 3=HEART 4=MORE
int optionrow[4][4]={{11,12,13,14},{21,22,23,24},{31,32,33,34},{41,42,43,44}}; //2D array as a map for menu options
int optionspotx=0;
int optionspoty=0;

int enterbuttons[5]={0,0,0,0,0}; //debounce puts a 1 to be later tested if button was pressed 1=pressed 0=not pressed
int enterbuttoncounter[5]={0,0,0,0,0};

/*00000000    LCD class declaration    00000000*/
LCD LCD;
/*00000000    SETUP    00000000*/

void setup()
{
 
  pinMode(buttonPin[0], INPUT);     //button on pin 4
  pinMode(buttonPin[1], INPUT);     //button on pin 5
  pinMode(buttonPin[2], INPUT);     //button on pin 6
  pinMode(buttonPin[3], INPUT);     //button on pin 7
  pinMode(buttonPin[4], INPUT);     //button on pin 8
  pinMode(buttonPin[5], INPUT);     //button on pin 9
  pinMode(buttonPin[6], INPUT);     //button on pin 10
  pinMode(buttonPin[7], INPUT);     //button on pin 11

  pinMode(ledPin13, OUTPUT);   // pin 13 on board LED
 
  for(int i=0; i>99; i++){previousMillis[i]=0;}
 
  LCD.setBacklight(20);
  LCD.clearScreen();

  LCD.setHome();
  LCD.printStr(" Program starts in "); //displays "program is starting in 10/9/8 etc"
   
  for(int i = 5; i >= 0; i--) //splash screen
    {
      LCD.setX(113);
      LCD.setY(0);
      LCD.printNum(i);
      delay(500);
    }
  LCD.clearScreen();
  delay(500);
}

/*00000000    LOOP    00000000*/

void loop()
{
 
selectmove(); //retrieves states of buttons to see if they were pressed
optionrowValueDisplay(); //display if buttons were pressed
optionrowTextDisplay();

}

/*00000000    displays when buttons are pressed     00000000*/

void optionrowValueDisplay()
{

actionstate=timecheck(200, 1); 
if(actionstate==1)
{
  LCD.setX(50);
  LCD.setY(00);
  LCD.printNum(optionspotx);
}

actionstate=timecheck(200, 3); 
if(actionstate==1)
{
  LCD.setX(50);
  LCD.setY(9);
  LCD.printNum(optionspoty);
}

actionstate=timecheck(200, 5); 
if(actionstate==1)
{
  LCD.setX(70);
  LCD.setY(18);
  LCD.printNum(enterbuttoncounter[0]);
}

actionstate=timecheck(200, 7); 
if(actionstate==1)
{
  LCD.setX(70);
  LCD.setY(27);
  LCD.printNum(enterbuttoncounter[1]);
}

actionstate=timecheck(200, 12); 
if(actionstate==1)
{
  LCD.setX(70);
  LCD.setY(36);
  LCD.printNum(enterbuttoncounter[2]);
}

actionstate=timecheck(200, 13); 
if(actionstate==1)
{
  LCD.setX(70);
  LCD.setY(45);
  LCD.printNum(enterbuttoncounter[3]);
}


}

void optionrowTextDisplay()
{
 
if(optionrowTextDisplayCounter==true)
  {
      actionstate=timecheck(125, 0); 
      if(actionstate==1)
        {
          LCD.setHome();
          LCD.printStr("x spot ");
        }
      actionstate=timecheck(125, 2); 
      if(actionstate==1)
        {
          LCD.setX(0);
          LCD.setY(9);
          LCD.printStr("y spot ");
        }
      actionstate=timecheck(125, 4); 
      if(actionstate==1)
        {
          LCD.setX(0);
          LCD.setY(18);
          LCD.printStr("center but ");
        }
      actionstate=timecheck(125, 6); 
      if(actionstate==1)
        {
          LCD.setX(0);
          LCD.setY(27);
          LCD.printStr("button 1 ");
        }
     optionrowTextDisplayCounter=true;
  }
}

void selectmove()
{
 
for(int i=0; i<8; i++)
{
cleardebounce(); //clears debounces variables
debounce(buttonNumber[i]); //debounces input pins
if(buttonlook[i]==1) //loops through all the pins
{

  switch(i)
          {
              case 0:        //action for when Bup button is pressed
                if(optionspoty!=3)
                  {
                    optionspoty=optionspoty+1;
                  }
                break;

              case 1:       //action for when Bdown button is pressed
                if(optionspoty!=0)
                  {
                    optionspoty=optionspoty-1;   
                  }
                break;
               
              case 2:        //action for when Bleft button is pressed
                if(optionspotx!=0)
                  {
                    optionspotx=optionspotx-1;
                  }
                break;
               
              case 3:        //action for when Bright button is pressed
                if(optionspotx!=3)
                  {
                    optionspotx=optionspotx+1;
                  }
                break;
               
              case 4:        //action for when Bcenter button is pressed
                    enterbuttons[0]=1;
                    ++enterbuttoncounter[0];
                break;
               
              case 5:        //action for when But1 button is pressed
                    enterbuttons[1]=1;
                    ++enterbuttoncounter[1];
                break;
               
              case 6:        //action for when But2 button is pressed
                    enterbuttons[2]=1;
                    ++enterbuttoncounter[2];
                break;
               
              case 7:        //action for when But3 button is pressed
                    enterbuttons[3]=1;
                    ++enterbuttoncounter[3];
                break;
               
            }

}


}

}

/*00000000   debounce functions    00000000*/


void cleardebounce() //clears variables so that they may be retested. Must be called before each debounce.
{
  for(int i=0; i<7; i++)
    {
      buttonlook[i]=0;
    }
   
  for(int i=0; i<4; i++)
    {
      enterbuttons[i]=0;
    }
}

/*00000000   debounce   00000000*/

int debounce(int buttonNumber) //recieves a pin and debounces that pin
{
  reading[buttonNumber] = digitalRead(buttonPin[buttonNumber]);
  if (reading[buttonNumber] != lastButtonState[buttonNumber])
  {lastDebounceTime[buttonNumber] = millis();}
 
  if ((millis() - lastDebounceTime[buttonNumber]) > debounceDelay[buttonNumber])
  {
    if (reading[buttonNumber] != buttonState[buttonNumber])
    {
      buttonState[buttonNumber] = reading[buttonNumber];

      if (buttonState[buttonNumber] == LOW)
      {
        ledState = !ledState;
        buttonlook[buttonNumber]=1;        //changes variable to 1 to be later tested if true
      }
    }
  }
 
  // set the LED:
  digitalWrite(ledPin13, ledState);// lights the LED so you know button was pressed

  // save the reading.  Next time through the loop,
  // it'll be the lastButtonState:
  lastButtonState[buttonNumber] = reading[buttonNumber];
}

/*00000000   timecheck   00000000*/

int timecheck(long interval, int i)
{
  currentMillis[i] = millis();

  if(currentMillis[i] - previousMillis[i] > interval)
    {
      previousMillis[i] = currentMillis[i];   // save the last time function was performed
      actionstate = 1;
    }
  else
    {actionstate = 0;}
 
return actionstate;
}
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 09, 2014, 08:24 pm
Sorry I thought I had fixed the previous posted code. Here is the same code posted in code format. Sorry about the delayed response. (also attached the file if anyone wants it)
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 11, 2014, 06:37 am
Did anyone look at my code? Or did everyone leave this topic. Sorry for the delayed code format fix.
Title: Re: Problem debouncing multiple buttons
Post by: graynomad on Mar 12, 2014, 02:59 pm
I'm looking at it but it's hard to see what's happening with all the other code. You should really have a test program that does nothing but debounce the buttons and get that module working, then add it to the LCD stuff.

______
Rob
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 13, 2014, 06:12 am
The debounce function works, but I think either my pseudo time delay I created or something with the way LCD.printStr is  displaying text doesn't work. I can see the LED pin 13 light up when i test the debounce function and it works with no delay.

The  LCD.printNum function works fine and displays the numbers correctly and I used printNum and printStr the same just put them in different functions since the text only needs to be put once and stays there until it is cleared or over written.

Could it be since that I'm running through the whole code without delays that the LCD.printStr isn't getting enough time to display its text before it gets called again further down the code? Maybe something to do with the buffer.

I can chop my code up into modular pieces and test different functions if you want me to.
Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Mar 13, 2014, 06:22 am
Something in here is backwards. Adding some spaces may help you find the problem.
Quote
for(int i=0; i>99; i++){
    previousMillis[ i ]=0;
  }
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 13, 2014, 07:00 am

Something in here is backwards. Adding some spaces may help you find the problem.
Quote
for(int i=0; i>99; i++){
    previousMillis[ i ]=0;
  }



I see i made that backward i changed it to this

Code: [Select]
  for(int i = 0 ; i < 99; i++)
        {
          previousMillis[i]=0;
        }


The purpose of that line was to fill up the array with 0 so that there is an initial value for the debounce function.

I changed it and tried uploading it to my board, but it still does the same thing.

What the GLCD does is that it displays the numbers i want then it displays the same number all around the first ones some even overlapping other numbers. The initial numbers will change so its keeping track and displaying the numbers from the array. After a while the GLCD stops updating certain numbers and doesn't display any new numbers, but the debounce light still works when i press the buttons.  Also the last two buttons cause the GLCD to display a number that increases continuously without a button push.
Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Mar 13, 2014, 08:32 am
Could you attach a picture of what your seeing on your GLCD?
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 13, 2014, 09:25 am
Here is a series of pictures that are order in chronological order left to right and what action is being done.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 13, 2014, 09:25 am
pic 2
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 13, 2014, 09:27 am
Download them and open them on your desktop, the forum opens them inside the reply box in its full size and cuts it off.
Title: Re: Problem debouncing multiple buttons
Post by: Grumpy_Mike on Mar 13, 2014, 12:34 pm

Download them and open them on your desktop, the forum opens them inside the reply box in its full size and cuts it off.

Shan't.
If you read the "how to use this forum" sticky post it tells you to resize them before posting.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 13, 2014, 10:40 pm
Sorry about that, I missed that line in the forum guide. Here are the images (http://imagizer.imageshack.us/v2/800x600q90/855/b6fw.jpg)
(http://imagizer.imageshack.us/v2/800x600q90/196/9sec.jpg)
Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Mar 13, 2014, 11:06 pm
There are a few things you should fix. For starters, all of these:
Quote
actionstate=timecheck(125, 0);  
   if(actionstate==1)
You can condense these to just if( timecheck(125, 0) )  

Another thing is your debounce function should return something. You can change this to have a boolean variable and return the state  of that variable.
Quote
int debounce(int buttonNumber) //recieves a pin and debounces that pin
{
  static boolean ButtonOut = false;

 reading[buttonNumber] = digitalRead(buttonPin[buttonNumber]);
 if (reading[buttonNumber] != lastButtonState[buttonNumber])
 {
   lastDebounceTime[buttonNumber] = millis();
 }

 if ((millis() - lastDebounceTime[buttonNumber]) > debounceDelay[buttonNumber])
 {
   if (reading[buttonNumber] != buttonState[buttonNumber])
   {
     buttonState[buttonNumber] = reading[buttonNumber];

     if (buttonState[buttonNumber] == LOW)
     {
       ledState = !ledState;
       //buttonlook[buttonNumber]=1;        //changes variable to 1 to be later tested if true
       ButtonOut = true;   // if at any time one of the buttons is LOW, it will set the variable TRUE
       

     }
   }
 }

 // set the LED:
 digitalWrite(ledPin13, ledState);// lights the LED so you know button was pressed

 // save the reading.  Next time through the loop,
 // it'll be the lastButtonState:
 lastButtonState[buttonNumber] = reading[buttonNumber];

return ButtonOut; // will return false if no button is LOW and will return true if one of them is
}


Now once that is changed, you can do this as well.
Code: [Select]

   if(debounce(buttonNumber[i]) ) //debounces input pins, loops through all the pins
   {
     switch(i)
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 18, 2014, 05:54 am
So I changed the code to the way you stated HazardsMind.

Changing the calls to  if( timecheck(125, 0) )  worked fine.

But when i changed debounce to return a value like you posted. The display on the GLCD starts showing numbers all over that are rapidly increase. Similar to the very last picture picture i sent

LED pin 13 lights up on the all the button pushs
Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Mar 18, 2014, 06:30 am
Tell me something, why did you do this, when the array buttonNumber has the elements 0 - 7 in it already?
Quote
for(int i=0; i<8; i++)
{

cleardebounce(); //clears debounces variables
debounce(buttonNumber[ i ]); //debounces input pins
if(buttonlook==1) //loops through all the pins


As for the LCD, its possible it has something to do with all the LCD.setX();  and LCD.setY(); Check them again and see if your letter spacing is correct.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 21, 2014, 10:37 pm
I'm not sure what you are asking. The array buttonNumber[ i ] has the numbers 0-7 in it and never changes. The loop cycles through 0-7.

Code: [Select]
for(int i=0; i<8; i++) //loops through 0 - 7
{
cleardebounce(); //clears debounces variables
debounce(buttonNumber[ i ]); //debounces input pin i and saves that value into buttonlook[buttonNumber] / buttonlook[i]
if(buttonlook==1) //if that button was pressed it does the corresponding action in the switch case 


The LCD.setX();  and LCD.setY() are the same commands I've been using. When I had the delays in my program they worked and displayed text, I then changed all the delays in the code and left the LCD.setx, LCDsety, LCD.printStr, and LCD.printNum the same. That's when the commands stopped working. If i put a delay(50) after the LCDprintStr it works.
Title: Re: Problem debouncing multiple buttons
Post by: HazardsMind on Mar 21, 2014, 11:03 pm
I dont have your LCD, so I can't do any tests to see why its not working.

Quote
I'm not sure what you are asking. The array buttonNumber[ i ] has the numbers 0-7 in it and never changes. The loop cycles through 0-7.

What I'm asking is why use an array with 0-7 in it, when you can just use the FOR loop that already cycles through 0-7. There is no difference of the 0-7 in the array to the 0-7 in the FOR loop, so why add in something that is not needed?
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Mar 21, 2014, 11:31 pm
I see what you're asking. I setup the array because I have numerous buttons and I want to separate some of them by function. Like navigation buttons and action buttons. This way I can reference them by the array and not by pins. And in the future If add more buttons I can just make the array larger. Also the array might be later setup to not be in chronological order if I have to switch pins around or add a pin that's not in numerical order.
Title: Re: Problem debouncing multiple buttons
Post by: Yigiter007 on Apr 01, 2014, 06:51 am
So I talked with sparkfun tech support and they said I need to remove software serial from code. Problem is I don't know how to do that. The demo program library for the GLCD uses software serial and If I just comment out softwareserial it says it has errors in the regular SerialGraphicLCD library. So i think softwareserial and SerialGraphicLCD library are intertwined and need each other.

Here are a few of the lines of the errors

error: 'SoftwareSerial' does not name a type
In constructor 'LCD::LCD()':

error: 'serial' was not declared in this scope
In member function 'void LCD::printStr(char*)':