Multiple buttons, counting their presses

Hi All

Im very very green to this and have been having a tough time working something out im using

https://www.arduino.cc/en/Tutorial/StateChangeDetection

to guide me but im having a tough time writing in multiple buttons.

So far I this is the exact effect but with 8 different buttons.

in the future i want to add more than on off to different button presses but so far i cant even add a second button to the script

PLEASE HELP

// this constant won't change:
const int  buttonPin = 2;    // the pin that the pushbutton is attached to
const int ledPin = 13;       // the pin that the LED is attached to

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  // initialize serial communication:
  Serial.begin(9600);
}


void loop() {
  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
    } else {
      // if the current state is LOW then the button
      // wend from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by
  // checking the modulo of the button push counter.
  // the modulo function gives you the remainder of
  // the division of two numbers:
  if (buttonPushCounter % 4 == 0) {
    digitalWrite(ledPin, HIGH);
  } else {
    digitalWrite(ledPin, LOW);
  }

}

Then just make it easy for yourself, grab a library ;) Bounce2 will do everything you want in like 5 lines of code ;)

You could use a FOR loop to read all the button values if you use arrays to store the pin numbers and states. Something like

if (millis() - prevBtnReadMillis >= btnIntervalMillis) {
    prevBtnReadMillis += btnIntervalMillis;
    for (byte n = 0; n < mxBtns; n++) {
      byte curBtn = digitalRead(buttonPin[n]);
      if (curBtn == HIGH && curBtn != prevBtnState[n]) {
          btnCount[n] ++;
      }
      prevBtnState[n] = curBtn;
   }
 }

…R

Thanks Robin2

that looks complex. I have attached my script im using Capacative sensors not actual push buttons.
not sure this changes to much.

But i have a working script with one cap sensing button that seems to work. How would i implement your
loop into mine?

Sorry i am very very new to all this if you can bare with the stupid questions

/* //////////...................................................////////////////////////////////
Pin 22 to 1Mohm ---> pin 4 Recieve pin

totalx = capacitance value to equal the trigger.
the triggered  value to act as a toggle switch allowing programmable functions per touch.
i.e touch one fad led up 
touch two change colour 
touch three fade led down

sketch currently has fade up fade down second input can be added under the no count (buttonPushCounter % 3 == 0)

/////////////...................................................//////////////////////////////*/



#include <CapacitiveSensor.h>


long time = 0; //long time

int led = 2;
int led2 = 6;


// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

CapacitiveSensor cs_4_22 = CapacitiveSensor(4, 22); //10M Resistor between pins 4 and 22, you may also connect an antenna on pin 22
 

void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);

}


void loop() {
  

  long total1 =  cs_4_22.capacitiveSensor(30);

  if (total1 > 35) { //: capacitive trigger number
    time += total1;
    Serial.println(total1); // print the value given by sensor
    Serial.print("\t");
    buttonState = HIGH;   //activates the button counter
    
    Serial.print("Trigger tota11:"); // prints total1 has been triggered
    Serial.println(time);
    if (time > 0) {
      time = 0; //Reset the time take to the read pin
    }


    cs_4_22.reset_CS_AutoCal(); //Stops readings
    
  }else { buttonState = LOW; }// Sets to low :
  


  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // wend from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
    } else {
      // if the current state is LOW then the button
      // wend from on to off:
      Serial.println("off");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state,
  //for next time through the loop
  lastButtonState = buttonState;


  // turns on the LED every four button pushes by
  // checking the modulo of the button push counter.
  // the modulo function gives you the remainder of
  // the division of two numbers:
  if (buttonPushCounter % 2 == 0) {
    digitalWrite(led, HIGH);
  } else {
    digitalWrite(led, LOW);
  }
 
}
int led = 2;
int led2 = 6;

If you start using postfixes it’s time for an array. Or at least number all…

But you don’t have bounce with a capasative sensor. Remove the delay :wink:

// turns on the LED every four button pushes by
  // checking the modulo of the button push counter.
  // the modulo function gives you the remainder of
  // the division of two numbers:
  if (buttonPushCounter % 2 == 0) {
    digitalWrite(led, HIGH);
  } else {
    digitalWrite(led, LOW);
  }

No it does not, it turns on and off with every press… Don’t make comments that can easily conflict with the code :wink:

CapacitiveSensor cs_4_22

What a name…

Okay, edited the code

/* //////////...................................................////////////////////////////////
Pin 22 to 1Mohm ---> pin 4 Recieve pin

totalx = capacitance value to equal the trigger.
the triggered  value to act as a toggle switch allowing programmable functions per touch.
i.e touch one fad led up
touch two change colour
touch three fade led down

sketch currently has fade up fade down second input can be added under the no count (buttonPushCounter % 3 == 0)

/////////////...................................................//////////////////////////////*/



#include <CapacitiveSensor.h>

const byte LedPins[] = {2, 6};

const byte NrSamples = 30;
const byte TriggerValue = 35;

// Variables will change:
unsigned int buttonPushCounter;   // counter for the number of button presses
bool lastButtonState;     // previous state of the button

CapacitiveSensor capButton = CapacitiveSensor(4, 22); //10M Resistor between pins 4 and 22, you may also connect an antenna on pin 22
 

void setup() {
  Serial.begin(9600);
  //make all leds output...
  for(byte i = 0; i < sizeof(LedPins); i++){
    pinMode(LedPins[i], OUTPUT);
  }

}


void loop() {
  //capButton touched?
  if (capButton.capacitiveSensor(NrSamples) > TriggerValue) { 
    //last time it was not
    if(!lastButtonState){
      //save it and increment counter
      lastButtonState = true;
      buttonPushCounter++;
      
      Serial.print("number of button pushes: ");
      Serial.println(buttonPushCounter);
    }
   
  }
  //if the button is not touched save that
  else{ 
    lastButtonState = false; 
  }
}

Or for multiple buttons:

/* //////////...................................................////////////////////////////////
Pin 22 to 1Mohm ---> pin 4 Recieve pin

totalx = capacitance value to equal the trigger.
the triggered  value to act as a toggle switch allowing programmable functions per touch.
i.e touch one fad led up
touch two change colour
touch three fade led down

sketch currently has fade up fade down second input can be added under the no count (buttonPushCounter % 3 == 0)

/////////////...................................................//////////////////////////////*/



#include <CapacitiveSensor.h>

#define numberof(x) sizeof(x)/sizeof(x[0])

const byte LedPins[] = {2, 6};

const byte NrSamples = 30;
const byte TriggerValue = 35;

CapacitiveSensor capButtons[] = {{4, 5}, {7, 8}}; //10M Resistor between pins 


// Variables will change:
// counter for the number of button presses
unsigned int buttonPushCounters[numberof(capButtons)];   
// previous state of the button
bool lastButtonStates[numberof(capButtons)];

 

void setup() {
  Serial.begin(9600);
  //make all leds output...
  for(byte i = 0; i < sizeof(LedPins); i++){
    pinMode(LedPins[i], OUTPUT);
  }

}


void loop() {
  //now loop over every button
  for(byte i = 0; i < numberof(capButtons); i++){
    //capButton touched?
    if (capButtons[i].capacitiveSensor(NrSamples) > TriggerValue) { 
      //last time it was not
      if(!lastButtonStates[i]){
        //save it and increment counter
        lastButtonStates[i] = true;
        buttonPushCounters[i]++;
        
        Serial.print("number of button ");
        Serial.print(i);
        Serial.print("pushes: ");
        Serial.println(buttonPushCounters[i]);
      }
     
    }
    //if the button is not touched save that
    else{ 
      lastButtonStates[i] = false; 
    }
  }
}

septillion you legend!!!
Cheers that pretty much everything I’ve always wanted.

it works perfectly through the serial monitor. I have a quick question I want to add some LEDS into the mix
would this work?
to fade a Led up then down ?

int value1 = 0


    if (buttonPushCounters[0] % 2 == 0) {
    for (value1= 0 ; value1<= 255; value1+= 5) { // sets the value (range from 0 to 255)

      analogWrite(2, value1);
              
    }
  }
 else { 
    for (value1= 255 ; value1 >= 0; value1-= 5) {
      analogWrite (2, value1);
 
    
    
  }
   }
 }

Yeah, kind of. But it will be very quick ramp. And by using delay() you're not able to scan the buttons. So drop the for loop and do it in loop with millis.

Also, why count the button pushes if you only want to toggle between up and down?

And do you want to fade up/down endlessly?

Hi septillon

I want to count the buttons because i'll be adding more actions on different button counts. And No i don' want to fade them endlessly, simply Fade Up on An even number

(buttonPushCounters % 2 == 0) {

and

else { //odd number fade down.

later i'll add a function on specific multiple of the buttonPushCounters but that's for later.

AS for the LEDs how would i fade over mills i've been looking at a few forum threads

http://playwithmyled.com/2012/03/looping-with-the-millis-function/ http://forum.arduino.cc/index.php?topic=223703.0

Im not sure where to go from here. not even sue I got this that works but not sure where to implement it within the current script dost seem to work. fails to fade up any LED

const int LEDfade =  10;      // the number of the LED pin

// Variables will change:
long previousMillis = 0;        // will store last time LED was updated
int i = 0;

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 10;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(LEDfade, OUTPUT);
  Serial.begin(9600); //For debugging
}

void loop() {

unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;
    i = i + 2;
    analogWrite(LEDfade, i); // set the LED brightness           
    }

  

}
long previousMillis = 0;

Never ever use a signed type when working with millis…

const int LEDfade =  10;      // the number of the LED pin

Then why not call it that?

Some code to fade:

const byte FadeLedPin =  10;      // the number of the LED pin

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
//but the interval isn't growing ;)
const unsigned int Interval = 10;           // interval at which to blink (milliseconds)

//chop everything in nice small pieces and make functions of them really helps to reuse code
//Returns true if it's done
//so you can check that later on
bool fadeLed(bool up = true){
  //making it static local because you don't need it global
  
  //last time the led was updated (not blinked)
  static unsigned long previousMillis = 0;
  //last brightness used
  static byte brightness = 0; 
  
  //see if we are already done
  if((up && brightness == 255) || (!up && brightness == 0)){
    return true;
  }
  
  if(millis() - previousMillis > Interval){
    previousMillis = millis();
    
    if(up){
      brightness++;
    }
    else{
      brightness--;
    }
    analogWrite(FadeLedPin, brightness);
  }
}

void setup() {
  // set the digital pin as output:
  pinMode(FadeLedPin, OUTPUT);
  //Serial.begin(9600); //For debugging
}

void loop() {
  if(millis() < 10000){
    fadeLed();  
    //same as:
    //fadeLed(true);
    //parameter is if it need's to fade up?
  }
  else{
    fadeLed(false);
  }
}

Nice fading script but im having issues incorporating it into the capacative sensing script

how would I Drop this in for multiple LEDS im getting errors about the bool

In function 'bool fadeLed(bool)':

Sorry for being so retarded I appreciate all the help

Okay, sorry it took me more then a day.

If you want to do it for more then one led we have to create a seperate variable for each led for all fade variables. It would look something like

const byte FadeLedPins[] =  {5, 6};      // the number of the LED pin

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
//but the interval isn't growing ;)
const unsigned int Interval = 10;           // interval at which to fade (milliseconds)

//chop everything in nice small pieces and make functions of them really helps to reuse code
//Returns true if it's done
//so you can check that later on
bool fadeLed(byte nr, bool up = true){
  //making it static local because you don't need it global
 
  //last time the led was updated (not blinked)
  static unsigned long previousMillis[sizeof(FadeLedPins)] = {};
  //last brightness used
  static byte brightnesses[sizeof(FadeLedPins)] = {};
 
  //see if we are already done
  if((up && brightnesses[nr] == 255) || (!up && brightnesses[nr] == 0)){
    return true;
  }
 
  if(millis() - previousMillis[nr] > Interval){
    previousMillis[nr] = millis();
   
    if(up){
      brightnesses[nr]++;
    }
    else{
      brightnesses[nr]--;
    }
    analogWrite(FadeLedPins[nr], brightnesses[nr]);
  }
}

void setup() {
  // set the digital pin as output:
  for(byte i = 0; i < sizeof(FadeLedPins); i++){}
    pinMode(FadeLedPins[i], OUTPUT);
}
  //Serial.begin(9600); //For debugging
}

void loop() {
  if(millis() < 10000){
    fadeLed(0); 
    //same as:
    //fadeLed(0, true);
    //parameter is if it need's to fade up?
  }
  else{
    fadeLed(0, false);
    fadeLed(1);
  }
}

But it started to annoy me how unclear and limited this becomes. For example, it’s hard to set the fading time. I looked around fo a library to handle it but I couldn’t find a library I liked. So I started to make my own :D. So I make a easy to use fade library called FadeLed. You can find it at GitHub here: https://github.com/sseptillion/FadeLed. The example will show you how to use it.

But basically, all you need to do is create a FadeLed object and assign the pin

FadeLed myLed(5);
//or for multple
FadeLed myLeds[] = {5, 6};

Set the time a full fade (off to full on or vise versa) needs to take (in ms)

myLed.setTime(5000);

And once you want to fade the led just send the value to fade to (or use the .on() or .off())

myLed.on();
//same as
myLed.set(255);

In the loop all you need to do ALL the time is call

FadeLed::update();

No matter if you use 1 or 6 (max pwm on a Uno) fading leds.

I hope it’s useful to you :slight_smile:

The Library is everything I need thanks.
I have it partially working though i maybe missing something

So i declare led pins

FadeLed leds[] = {2, 6, 7, 8, 9, 10, 11, 12};

Then the fade time

  leds[0].setTime(500);
  leds[1].setTime(500);
  leds[3].setTime(500);
  leds[4].setTime(500);
  leds[5].setTime(500);
  leds[6].setTime(500);

Then the fade action

      FadeLed::update();

      //odd number button pushes
      if (buttonPushCounters[i] % 2 == 1) {

        //leds on
        leds[i].on();
      }

      //  everything else off
      else {
        leds[i].off();
      }

what happens is that the button count doesn’t respond i only fades to full brightness after 5+ touches regardless off odd or even or the remainder number.
I think I’m maybe missing this element to loop over the led until full brightness ?

for (byte i = 0; i < elements(leds); i++) {

but having it in makes no difference to the action

Let me have a look

First thing I spot, which Arduino do you use? I think a Mega because of the pins you use? By default it’s limited to 6 fading leds because that’s the number of PWM pins on a Uno. If you open FadeLed.h you can change

#define FADE_LED_MAX_LED  6
//change to
#define FADE_LED_MAX_LED  15 //number of PWM on a Mega

Sparkyduke:
Then the fade time

Do you want all the leds to have a fading time of halve a second? Also, if you want fade times of halve a second I would decrease the interval to 10ms.

If you want to set them all to halve a second you can do

FadeLed::setInterval(10);
for(byte i = 0; i < elements(leds); i++){
  leds[i].setTime(500);
}

But you need the elements() macro

#define elemens(x) sizeof(x)/sizeof(x[0])

I see two errors in the code.

First, you indeed need to loop over every button / led combo. Otherwise calling it with a ‘i’ does not make sens.

Second, although in constant fade speed it should not really matter, it’s better to only set the brightness if the counting is changed, not every loop.So save when you acted (set the brightness) as well.

So it becomes something like

void loop(){
  FadeLed::update();;
  
  //do the button counting stuff
  
  for(byte i = 0; i < elements(leds); i++){
    //check to see if it's different then the last time we acted
    if(buttonPushCounters[i] != buttonActedCounters[i]){
      //we are going to act, make the same
      buttonActedCounters[i] = buttonPushCounters[i];
      
      if(buttonPushCounters[i] % 2){
        leds[i].on();
      }
      else{
        leds[i].off();
      }
    }
  }
}

Or, even better, you can just check if the led is at a different brightness before we set it. If it’s already on the good brightness, just leave it there and don’t act at all.

void loop(){
  FadeLed::update();;
  
  //do the button counting stuff
  
  //loop over every led/button combo
  for(byte i = 0; i < elements(leds); i++){
    //what state do we want for the led?
    bool wantedState = buttonPushCounters[i] % 2
    
    //if we want on AND the led is not on
    if(wantedState && !leds[i].get()){
      //turn it on
      leds[i].on();
    }
    //if we want off AND the led is on
    else if(!wantedState && leds[i].get()){
      //turn it off
      leds[i].off();
    }
  }
}

Hi septillion

This seems to work very well thank you.
1-7 buttons are responding perfectly.

but 0 fades up and gets stuck !?
I think i didn’t define " buttonActedCounters " correctly and its not recognising the last state of button 0.

but the others fade perfectly

#include <FadeLed.h>
#include <CapacitiveSensor.h>
//gives the number of elements in an array
#define elements(x) sizeof(x)/sizeof(x[0])
#define numberof(x) sizeof(x)/sizeof(x[0])
//make two FadeLed objecs for pin 5 (leds[0]) and pin 6 
#define FADE_LED_MAX_LED  15 //number of PWM on a Mega
//Pin No for LEDs
FadeLed leds[] = {2, 6, 7, 8, 9, 10, 11, 12};




const byte NrSamples = 20;
//trigger value 
const byte TriggerValue = 35;

CapacitiveSensor capButtons[] = {{4, 22}, {4, 24}, {4, 26}, {4, 28}, {4, 30}, {4, 32}, {4, 34}}; //1M Resistor between pins


// Variables will change:
// counter for the number of button presses
unsigned int buttonPushCounters[numberof(capButtons)];
// previous state of the button
bool lastButtonStates[numberof(capButtons)];

//Unsure what state this needs to be 
unsigned int buttonActedCounters[numberof(capButtons)];



void setup() {

  Serial.begin(9600);
// setting interval and fade time 
FadeLed::setInterval(20);
for(byte i = 0; i < elements(leds); i++){
  leds[i].setTime(1000);
}

}

void loop() {
  
  
// updates the fade 
      FadeLed::update();;
//loops over the button counter 
  for (byte i = 0; i < numberof(capButtons); i++) {
    //capButton touched?
    if (capButtons[i].capacitiveSensor(NrSamples) > TriggerValue) {
      

      //last time it was not
      if (!lastButtonStates[i]) {
        //save it and increment counter
        lastButtonStates[i] = true;
        buttonPushCounters[i]++;

//print all info 
        Serial.print("number of button:  ");
        Serial.print(i);
        Serial.print("  pushes: ");
        Serial.println(buttonPushCounters[i]);


      }
// saves last state 
      else {
        lastButtonStates[i] = false;

      }
      
      
  //do the button counting stuff
  
  for(byte i = 0; i < elements(leds); i++){
    //check to see if it's different then the last time we acted
    if(buttonPushCounters[i] != buttonActedCounters[i]){
      //we are going to act, make the same
      buttonActedCounters[i] = buttonPushCounters[i];
      
      if(buttonPushCounters[i] % 2){
        leds[i].on();
      }
      else{
        leds[i].off();
      }
    }
  }
}
  }
}
#define elements(x) sizeof(x)/sizeof(x[0])
#define numberof(x) sizeof(x)/sizeof(x[0])

Stupid me uses both but they do the same :stuck_out_tongue: Not the problem but a bit weird of me :stuck_out_tongue:

Did you change FADE_LED_MAX_LED ?

And you know you have a led more then you have buttons? 7 buttons vs 8 leds… And because you loop over all 8 leds expecting a corresponding button you get some errors…

for (byte i = 0; i < numberof(leds); i++) {
        //check to see if it's different then the last time we acted
        if (buttonPushCounters[i] != buttonActedCounters[i]) {

Counter i will go from 0 to 7 but buttonPushCounters and buttonActedCounters only go up to 6 (7 buttons, makes elements 0 to 6).

So I think there is an error :smiley:

buttonActedCounters will keep track on which count we already acted. We only want to set a brightness when the number of presses changed. So now we have the option to check the counter and a variable we set equal to the counter when we set the brightness. But like I showed, you can also check the current brightness (with leds[i ].get() ) to see if it already matches the brightness we want. That was the second example.

Also, small tip, press Ctrl+T for fun and see how the code now looks way more readable :smiley:

You have posted a new question in a very old Thread so I have suggested to the Moderator to move you to your own Thread.

You will need to describe what you want to happen in more detail.

We do not give you code but we will help with your code if you have a specific problem.

If you just want someone to write a program for you please ask in the Gigs and Collaborations section of the Forum and be prepared to pay.

If you want to learn to program yourself the examples that come with the Arduino IDE are a good place to start. They probably cover all the techniques you will need. There are also many online tutorials. Also see the Useful Links Thread.

...R