News:

SMF for DIYStompboxes.com!

Main Menu

Arduino Uno. 3 button switcher

Started by Buffalo Tom, September 05, 2022, 04:16:22 PM

Previous topic - Next topic

Buffalo Tom

Hi. This is a selector that is supposed to have only one relay at the time activated. This code works but how can I add so it's not possible to press more than one switch at the time?


int button1 = 2;   
int button2 = 3;   
int button3 = 4;   
int rly1 = 8;       
int rly2 = 9;       
int rly3 = 10;     

int buttonState;     

void setup()
{

pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);

pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);

pinMode(rly1, OUTPUT);
pinMode(rly2, OUTPUT);
pinMode(rly3, OUTPUT);

digitalWrite(rly1, HIGH);
digitalWrite(rly2, LOW);
digitalWrite(rly3, LOW);

}
void loop()
{
  buttonState = digitalRead(button1);
  if (buttonState == LOW)
  {
    digitalWrite(rly1, HIGH); 
    digitalWrite(rly2, LOW);
    digitalWrite(rly3, LOW);
   
  }

  buttonState = digitalRead(button2);
  if (buttonState == LOW)
  {
    digitalWrite(rly1, LOW); 
    digitalWrite(rly2, HIGH);
    digitalWrite(rly3, LOW);
   
  }

  buttonState = digitalRead(button3);
  if (buttonState == LOW)
  {
    digitalWrite(rly1, LOW); 
    digitalWrite(rly2, LOW);
    digitalWrite(rly3, HIGH);
   
}
}

FiveseveN

Quote from: Buffalo Tom on September 05, 2022, 04:16:22 PM
how can I add so it's not possible to press more than one switch at the time?

That sounds like a mechanical issue, not a software one ;D . Since you can't prevent the user from doing that, the question should be what do you want your code to do when that happens.
As it stands, since all 3 button conditionals set/reset all the relays, the last button to un-pressed will define the state. Pressing more than one will cause it to rapidly (in the MHz) switch between states but probably won't turn on any relays until you let go. Is that what you're getting? What else are you looking for?
Quote from: R.G. on July 31, 2018, 10:34:30 PMDoes the circuit sound better when oriented to magnetic north under a pyramid?

ElectricDruid

#2
I don't agree that this is a mechanical thing. It looks liek the software to me. If you're trying to avoid lots of relay clicking, then the three switches/relays have to be treated together, not separately, as they are in this code.

At the moment, it sets the relays according to the first switch. Then it sets them according to the second switch. Then it sets them according to the third switch.

This works fine if only one switch is pressed down. If more than one is pressed, you'll get a rapid switching from one to another as the code goes around the loop. Arggh!!! clickclickclickclickclick!!!

My approach would be to test all the switches on the way in:


buttonState1 = digitalRead(button1);
buttonState2 = digitalRead(button2);
buttonState3 = digitalRead(button3);


..and only then do the tests to see what we want to do, and those should be exclusive: e.g. "if X elseif Y elseif Z", so that only one happens, not the current "if X", "if Y", "if Z"

FiveseveN

Quote from: ElectricDruid on September 05, 2022, 06:57:59 PM
I don't agree that this is a mechanical thing.

But how can you make a button impossible to be pressed1 using 1s and 0s?



___________
1 - as opposed to being read, interpreted, acted upon etc.
Quote from: R.G. on July 31, 2018, 10:34:30 PMDoes the circuit sound better when oriented to magnetic north under a pyramid?

Sweetalk

If you want to avoid the button combination you have to evaluate all the buttons at the same time to ignore those combinations. First of all in your code you're setting the buttons first in INPUT and then in INPUT_PULLUP (that second statement will override the first one). Second you'll need a button debounce routine to get better performance.

Try this code. What it does is arrange all the buttons states in the buttonState variable, button1 on bit0, button2 on bit1 and button3 on bit2. This way you can make a switch to evaluate the conditions you want and skip the combinations. When you add the debounce routine you have to modifiy this code to get the debounce state of the buttons on the buttonState variable.

This code compiles and should work. Without button debounce will act flaky, but is ok to test the general behaviour

#define BUTTON1_PIN     2     // Button 1 pin
#define BUTTON2_PIN     3     // Button 2 pin
#define BUTTON3_PIN     4     // Button 3 pin
#define RELAY1_PIN      8     // Relay 1 pin
#define RELAY2_PIN      9     // Relay 2 pin
#define RELAY3_PIN     10     // Relay 3 pin
#define BUTTON1         1     // Button 1 pressed state
#define BUTTON2         2     // Button 2 pressed state
#define BUTTON3         4     // Button 3 pressed state

int buttonState;     

void setup()
{

// SWITCHES AS INPUT PULLUP
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);

// RELAYS AS OUTPUT
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);

// INITIALIZE ALL RELAYS ON OFF STATE
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);

}
void loop()
{
  buttonState = digitalRead(BUTTON1_PIN) + 2* digitalRead(BUTTON2_PIN) + 4* digitalRead(BUTTON3_PIN); // Put all the buttons states togheter in the buttonState variable to evaluate
  /* button3 button2 button1
  0   0       0       0         No button pressed
  1   0       0       1         Button 1 pressed
  2   0       1       0         Button 2 pressed
  3   0       1       1         Button 1 + Button 2 pressed (no action)
  4   1       0       0         Button 3 pressed
*/
  switch(buttonState)
  {
    case BUTTON1:                       // Button 1
      digitalWrite(RELAY1_PIN, HIGH);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, LOW);
      break;

    case BUTTON2:                       // Button 2
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, HIGH);
      digitalWrite(RELAY3_PIN, LOW);
      break;   

    case BUTTON3:                        // Button 3
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, HIGH);
      break;
  }
   
}


I'm old fashioned and like the #define to get the constants instead of using variables (int or const int or const byte) to define states and pins, specially in Arduino where the memory isn't for spare.

niektb

#5
Quote from: Sweetalk on September 06, 2022, 05:57:47 AM
[...]

I'm old fashioned and like the #define to get the constants instead of using variables (int or const int or const byte) to define states and pins, specially in Arduino where the memory isn't for spare.
But then no shift operator instead of multiplications? :icon_sad:  ;)

ElectricDruid

Quote from: FiveseveN on September 06, 2022, 03:08:25 AM
Quote from: ElectricDruid on September 05, 2022, 06:57:59 PM
I don't agree that this is a mechanical thing.
But how can you make a button impossible to be pressed1 using 1s and 0s?
1 - as opposed to being read, interpreted, acted upon etc.
Clearly you can't, but you've already answered your own question - we don't have to *do anything about it* when someone presses more than one at once.
All that needs to happen is that we make sure that all possible inputs have safe and sensible behaviour - like Sweetalk's code shows. It deals with the three states we're interested in, and safely ignores the others. The code pasted in by the OP will react to every one of the eight possible states except for the none-pressed-down one.

Sweetalk

Quote from: niektb on September 06, 2022, 06:26:22 AM
Quote from: Sweetalk on September 06, 2022, 05:57:47 AM
[...]

I'm old fashioned and like the #define to get the constants instead of using variables (int or const int or const byte) to define states and pins, specially in Arduino where the memory isn't for spare.
But then no shift operator instead of multiplications? :icon_sad:  ;)

Quick early morning coding  :icon_mrgreen:

Buffalo Tom

Thank you very much! This is my first Arduino project and I'm very thankful for your help.  But unfortunately I cant get your code to work. Im sure I got the hardware working because if I upload the old code it works...

Quote from: Sweetalk on September 06, 2022, 05:57:47 AM
If you want to avoid the button combination you have to evaluate all the buttons at the same time to ignore those combinations. First of all in your code you're setting the buttons first in INPUT and then in INPUT_PULLUP (that second statement will override the first one). Second you'll need a button debounce routine to get better performance.

Try this code. What it does is arrange all the buttons states in the buttonState variable, button1 on bit0, button2 on bit1 and button3 on bit2. This way you can make a switch to evaluate the conditions you want and skip the combinations. When you add the debounce routine you have to modifiy this code to get the debounce state of the buttons on the buttonState variable.

This code compiles and should work. Without button debounce will act flaky, but is ok to test the general behaviour

#define BUTTON1_PIN     2     // Button 1 pin
#define BUTTON2_PIN     3     // Button 2 pin
#define BUTTON3_PIN     4     // Button 3 pin
#define RELAY1_PIN      8     // Relay 1 pin
#define RELAY2_PIN      9     // Relay 2 pin
#define RELAY3_PIN     10     // Relay 3 pin
#define BUTTON1         1     // Button 1 pressed state
#define BUTTON2         2     // Button 2 pressed state
#define BUTTON3         4     // Button 3 pressed state

int buttonState;     

void setup()
{

// SWITCHES AS INPUT PULLUP
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);

// RELAYS AS OUTPUT
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);

// INITIALIZE ALL RELAYS ON OFF STATE
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);

}
void loop()
{
  buttonState = digitalRead(BUTTON1_PIN) + 2* digitalRead(BUTTON2_PIN) + 4* digitalRead(BUTTON3_PIN); // Put all the buttons states togheter in the buttonState variable to evaluate
  /* button3 button2 button1
  0   0       0       0         No button pressed
  1   0       0       1         Button 1 pressed
  2   0       1       0         Button 2 pressed
  3   0       1       1         Button 1 + Button 2 pressed (no action)
  4   1       0       0         Button 3 pressed
*/
  switch(buttonState)
  {
    case BUTTON1:                       // Button 1
      digitalWrite(RELAY1_PIN, HIGH);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, LOW);
      break;

    case BUTTON2:                       // Button 2
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, HIGH);
      digitalWrite(RELAY3_PIN, LOW);
      break;   

    case BUTTON3:                        // Button 3
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, HIGH);
      break;
  }
   
}


I'm old fashioned and like the #define to get the constants instead of using variables (int or const int or const byte) to define states and pins, specially in Arduino where the memory isn't for spare.

potul

I think the button logic is reversed... Are you setting the buttons as pullup and shorting to grown when pressing? If yes, try to modify this line:

buttonState = !(digitalRead(BUTTON1_PIN)) + 2* !(digitalRead(BUTTON2_PIN)) + 4* !(digitalRead(BUTTON3_PIN)); // Put all the buttons states togheter in the buttonState variable to evaluate

Sweetalk

Quote from: potul on September 07, 2022, 05:17:52 AM
I think the button logic is reversed... Are you setting the buttons as pullup and shorting to grown when pressing? If yes, try to modify this line:

buttonState = !(digitalRead(BUTTON1_PIN)) + 2* !(digitalRead(BUTTON2_PIN)) + 4* !(digitalRead(BUTTON3_PIN)); // Put all the buttons states togheter in the buttonState variable to evaluate

My bad!! potul is right, the buttons are input_pullup so the normal state will read as 1 and the pressed state will read as 0. With that line changed you invert the reading and the code will work.

Or you can modify the 3 #define that sets the state for each button.
This is the table of the buttons, so now Button 1 is 6 instead of 1, Button 2 is 5 instead of 2 and Button 3 is 3 instead of 4
  0   0       0       0         All button pressed (no action)
  1   0       0       1         Button 2 + Button 3 pressed (no action)
  2   0       1       0         Button 1 + Button 3 pressed (no action)
  3   0       1       1         Button 3 pressed
  4   1       0       0         Button 1 + Button 2 pressed (no action)
  5   1       0       1         Nutton 2 pressed
  6   1       1       0         Button 1 pressed
  7   1       1       1         No button pressed (no action)


#define BUTTON1         6     // Button 1 pressed state
#define BUTTON2         5     // Button 2 pressed state
#define BUTTON3         3     // Button 3 pressed state


Remember you'll need to add a debouncing rountine to the buttons.

Buffalo Tom

Quote
#define BUTTON1         6     // Button 1 pressed state
#define BUTTON2         5     // Button 2 pressed state
#define BUTTON3         3     // Button 3 pressed state


Remember you'll need to add a debouncing rountine to the buttons.

Changed to 6, 5, 3 and it works perfect. Thanks! Very useful code. So next thing is to learn debouncing. As this is my first steps I don't know how to add debouncing but google took me to this page with ezButton library examples https://arduinogetstarted.com/library/button/example/arduino-single-button-events
* This example detects the pressed and released events of a button without debounce.

Is this the way to do it? Thanks  :)


FiveseveN

As the comment line stated, that specific example doesn't include debounce. However, the library does provide the feature: https://arduinogetstarted.com/tutorials/arduino-button-library
Here's an example with debounce: https://arduinogetstarted.com/library/button/example/arduino-single-button-debounce
Quote from: R.G. on July 31, 2018, 10:34:30 PMDoes the circuit sound better when oriented to magnetic north under a pyramid?

Buffalo Tom

Quote from: FiveseveN on September 07, 2022, 09:05:08 AM
As the comment line stated, that specific example doesn't include debounce. However, the library does provide the feature: https://arduinogetstarted.com/tutorials/arduino-button-library
Here's an example with debounce: https://arduinogetstarted.com/library/button/example/arduino-single-button-debounce

Thanks! I have installed the ezButton library. This is my code right now. Its compiling without error massages... But as you can see I've only made one button and I'm not sure I got it right. I cant tell any difference in performance.

#include <ezButton.h>

ezButton button (2);  // create ezButton object that attach to pin 2;

#define BUTTON1_PIN     2     // Button 1 pin
#define BUTTON2_PIN     3     // Button 2 pin
#define BUTTON3_PIN     4     // Button 3 pin
#define RELAY1_PIN      8     // Relay 1 pin
#define RELAY2_PIN      9     // Relay 2 pin
#define RELAY3_PIN     10     // Relay 3 pin
#define BUTTON1         6     // Button 1 pressed state
#define BUTTON2         5     // Button 2 pressed state
#define BUTTON3         3     // Button 3 pressed state

int buttonState;     

void setup()
{

  {
  Serial.begin(9600);
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
}

// SWITCHES AS INPUT PULLUP
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);

// RELAYS AS OUTPUT
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);

// INITIALIZE ALL RELAYS ON OFF STATE
digitalWrite(RELAY1_PIN, HIGH);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);

}
void loop()
{

button.loop(); // MUST call the loop() function first

  if(button.isPressed())
    Serial.println("The button is pressed");

  if(button.isReleased())
    Serial.println("The button is released");

  buttonState = digitalRead(BUTTON1_PIN) + 2* digitalRead(BUTTON2_PIN) + 4* digitalRead(BUTTON3_PIN); // Put all the buttons states togheter in the buttonState variable to evaluate
  /* button3 button2 button1
  0   0       0       0         All button pressed (no action)
  1   0       0       1         Button 2 + Button 3 pressed (no action)
  2   0       1       0         Button 1 + Button 3 pressed (no action)
  3   0       1       1         Button 3 pressed
  4   1       0       0         Button 1 + Button 2 pressed (no action)
  5   1       0       1         Nutton 2 pressed
  6   1       1       0         Button 1 pressed
  7   1       1       1         No button pressed (no action)
*/
  switch(buttonState)
  {
    case BUTTON1:                       // Button 1
      digitalWrite(RELAY1_PIN, HIGH);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, LOW);
      break;

    case BUTTON2:                       // Button 2
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, HIGH);
      digitalWrite(RELAY3_PIN, LOW);
      break;   

    case BUTTON3:                        // Button 3
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, HIGH);
      break;
  }
   
}

Buffalo Tom

Quote
Remember you'll need to add a debouncing rountine to the buttons.

Here is another code I found that does the same thing.
Does this code have debouncing rountine?


const int button1 =  2;
const int button2 =  3;
const int button3 =  4;
const int led1Pin =  8;
const int led2Pin =  9;
const int led3Pin =  10;

char bstate1 = 0;
char bstate2 = 0;
char bstate3 = 0;
unsigned long bcount1 = 0;
unsigned long bcount2 = 0;
unsigned long bcount3 = 0;

boolean timeout(unsigned long *marker, unsigned long interval) {
  if (millis() - *marker >= interval) {
    *marker += interval;
    return true;       
  }
  else return false;
}

boolean butndown(char button, unsigned long *marker, char *butnstate, unsigned long interval) {
  switch (*butnstate) {               
  case 0:
    if (button == HIGH) return false;
    else {
      *butnstate = 2;                 
      *marker = millis();             
      return false;                   
    }

  case 1:
    if (button == LOW) return false;
    else {
      *butnstate = 3;                 
      *marker = millis();             
      return false;                   
    }

  case 2:
    if (button == HIGH) {
      *butnstate = 0;                 
      return false;                   
    }
    else {
      if (millis() - *marker >= interval) {
        *butnstate = 1;               
        return true;                 
      }
      else
        return false;                 
    }

  case 3:
    if (button == LOW) {
      *butnstate = 1;                 
      return false;                   
    }
    else {
      if (millis() - *marker >= interval) {
        *butnstate = 0;               
        return false;                 
      }
      else
        return false;                 
    }
  default:                           
    { 
      *butnstate = 0;
      return false;                   
    }
  }
}

void setup() {
  pinMode(led1Pin, OUTPUT);     
  pinMode(button1, INPUT_PULLUP);
  pinMode(led2Pin, OUTPUT);     
  pinMode(button2, INPUT_PULLUP);     
  pinMode(led3Pin, OUTPUT);     
  pinMode(button3, INPUT_PULLUP);     
       
  digitalWrite (led1Pin, HIGH);
  digitalWrite (led2Pin, LOW);
  digitalWrite (led3Pin, LOW);

}

void loop() {
 
  if (butndown(digitalRead(button1), &bcount1, &bstate1, 10UL )) {
    digitalWrite (led1Pin, HIGH);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, LOW);
    delay(100);
  }
 
  if (butndown(digitalRead(button2), &bcount2, &bstate2, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, HIGH);
    digitalWrite (led3Pin, LOW);
    delay(100);
  }
 
  if (butndown(digitalRead(button3), &bcount3, &bstate3, 10UL )) {
    digitalWrite (led1Pin, LOW);
    digitalWrite (led2Pin, LOW);
    digitalWrite (led3Pin, HIGH);
    delay(100);
  }
 
}

Sweetalk

Quote from: Buffalo Tom on September 07, 2022, 01:30:32 PM
Quote from: FiveseveN on September 07, 2022, 09:05:08 AM
As the comment line stated, that specific example doesn't include debounce. However, the library does provide the feature: https://arduinogetstarted.com/tutorials/arduino-button-library
Here's an example with debounce: https://arduinogetstarted.com/library/button/example/arduino-single-button-debounce

Thanks! I have installed the ezButton library. This is my code right now. Its compiling without error massages... But as you can see I've only made one button and I'm not sure I got it right. I cant tell any difference in performance.

#include <ezButton.h>

ezButton button (2);  // create ezButton object that attach to pin 2;

#define BUTTON1_PIN     2     // Button 1 pin
#define BUTTON2_PIN     3     // Button 2 pin
#define BUTTON3_PIN     4     // Button 3 pin
#define RELAY1_PIN      8     // Relay 1 pin
#define RELAY2_PIN      9     // Relay 2 pin
#define RELAY3_PIN     10     // Relay 3 pin
#define BUTTON1         6     // Button 1 pressed state
#define BUTTON2         5     // Button 2 pressed state
#define BUTTON3         3     // Button 3 pressed state

int buttonState;     

void setup()
{

  {
  Serial.begin(9600);
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
}

// SWITCHES AS INPUT PULLUP
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);

// RELAYS AS OUTPUT
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);

// INITIALIZE ALL RELAYS ON OFF STATE
digitalWrite(RELAY1_PIN, HIGH);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);

}
void loop()
{

button.loop(); // MUST call the loop() function first

  if(button.isPressed())
    Serial.println("The button is pressed");

  if(button.isReleased())
    Serial.println("The button is released");

  buttonState = digitalRead(BUTTON1_PIN) + 2* digitalRead(BUTTON2_PIN) + 4* digitalRead(BUTTON3_PIN); // Put all the buttons states togheter in the buttonState variable to evaluate
  /* button3 button2 button1
  0   0       0       0         All button pressed (no action)
  1   0       0       1         Button 2 + Button 3 pressed (no action)
  2   0       1       0         Button 1 + Button 3 pressed (no action)
  3   0       1       1         Button 3 pressed
  4   1       0       0         Button 1 + Button 2 pressed (no action)
  5   1       0       1         Nutton 2 pressed
  6   1       1       0         Button 1 pressed
  7   1       1       1         No button pressed (no action)
*/
  switch(buttonState)
  {
    case BUTTON1:                       // Button 1
      digitalWrite(RELAY1_PIN, HIGH);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, LOW);
      break;

    case BUTTON2:                       // Button 2
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, HIGH);
      digitalWrite(RELAY3_PIN, LOW);
      break;   

    case BUTTON3:                        // Button 3
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, HIGH);
      break;
  }
   
}


You can't notice a performace change because you declared the button but didn't use it on the line that matters for the code.

buttonState = digitalRead(BUTTON1_PIN) + 2* digitalRead(BUTTON2_PIN) + 4* digitalRead(BUTTON3_PIN);

There is where you have to replace the digitalRead(BUTTONx_PIN) with the debounced one. First, create the buttons objects:
ezButton button (2);
ezButton button2 (3);
ezButton button3 (4);


Set the debounce time, something between 5 to 15mS will do the work without slowing the button down too much
button.setDebounceTime(10); // set debounce time to 50 milliseconds
button2.setDebounceTime(10); // set debounce time to 50 milliseconds
button3.setDebounceTime(10); // set debounce time to 50 milliseconds


buttonState = button.isPressed() + 2* button2.isPressed() + 4* button3.isPressed();

Buffalo Tom

Quote from: Sweetalk on September 10, 2022, 04:38:49 AM
Quote from: Buffalo Tom on September 07, 2022, 01:30:32 PM
Quote from: FiveseveN on September 07, 2022, 09:05:08 AM
As the comment line stated, that specific example doesn't include debounce. However, the library does provide the feature: https://arduinogetstarted.com/tutorials/arduino-button-library
Here's an example with debounce: https://arduinogetstarted.com/library/button/example/arduino-single-button-debounce

Thanks! I have installed the ezButton library. This is my code right now. Its compiling without error massages... But as you can see I've only made one button and I'm not sure I got it right. I cant tell any difference in performance.

#include <ezButton.h>

ezButton button (2);  // create ezButton object that attach to pin 2;

#define BUTTON1_PIN     2     // Button 1 pin
#define BUTTON2_PIN     3     // Button 2 pin
#define BUTTON3_PIN     4     // Button 3 pin
#define RELAY1_PIN      8     // Relay 1 pin
#define RELAY2_PIN      9     // Relay 2 pin
#define RELAY3_PIN     10     // Relay 3 pin
#define BUTTON1         6     // Button 1 pressed state
#define BUTTON2         5     // Button 2 pressed state
#define BUTTON3         3     // Button 3 pressed state

int buttonState;     

void setup()
{

  {
  Serial.begin(9600);
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
}

// SWITCHES AS INPUT PULLUP
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);

// RELAYS AS OUTPUT
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);

// INITIALIZE ALL RELAYS ON OFF STATE
digitalWrite(RELAY1_PIN, HIGH);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);

}
void loop()
{

button.loop(); // MUST call the loop() function first

  if(button.isPressed())
    Serial.println("The button is pressed");

  if(button.isReleased())
    Serial.println("The button is released");

  buttonState = digitalRead(BUTTON1_PIN) + 2* digitalRead(BUTTON2_PIN) + 4* digitalRead(BUTTON3_PIN); // Put all the buttons states togheter in the buttonState variable to evaluate
  /* button3 button2 button1
  0   0       0       0         All button pressed (no action)
  1   0       0       1         Button 2 + Button 3 pressed (no action)
  2   0       1       0         Button 1 + Button 3 pressed (no action)
  3   0       1       1         Button 3 pressed
  4   1       0       0         Button 1 + Button 2 pressed (no action)
  5   1       0       1         Nutton 2 pressed
  6   1       1       0         Button 1 pressed
  7   1       1       1         No button pressed (no action)
*/
  switch(buttonState)
  {
    case BUTTON1:                       // Button 1
      digitalWrite(RELAY1_PIN, HIGH);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, LOW);
      break;

    case BUTTON2:                       // Button 2
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, HIGH);
      digitalWrite(RELAY3_PIN, LOW);
      break;   

    case BUTTON3:                        // Button 3
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, HIGH);
      break;
  }
   
}


You can't notice a performace change because you declared the button but didn't use it on the line that matters for the code.

buttonState = digitalRead(BUTTON1_PIN) + 2* digitalRead(BUTTON2_PIN) + 4* digitalRead(BUTTON3_PIN);

There is where you have to replace the digitalRead(BUTTONx_PIN) with the debounced one. First, create the buttons objects:
ezButton button (2);
ezButton button2 (3);
ezButton button3 (4);


Set the debounce time, something between 5 to 15mS will do the work without slowing the button down too much
button.setDebounceTime(10); // set debounce time to 50 milliseconds
button2.setDebounceTime(10); // set debounce time to 50 milliseconds
button3.setDebounceTime(10); // set debounce time to 50 milliseconds


buttonState = button.isPressed() + 2* button2.isPressed() + 4* button3.isPressed();

Thanks!  :) Did my best to move this into the code. But there must be something more that's missing? Or something more I need to change? It does not work at all now.

Here is my code:

#include <ezButton.h>

ezButton button (2);
ezButton button2 (3);
ezButton button3 (4);

#define BUTTON1_PIN     2     // Button 1 pin
#define BUTTON2_PIN     3     // Button 2 pin
#define BUTTON3_PIN     4     // Button 3 pin
#define RELAY1_PIN      8     // Relay 1 pin
#define RELAY2_PIN      9     // Relay 2 pin
#define RELAY3_PIN     10     // Relay 3 pin
#define BUTTON1         6     // Button 1 pressed state
#define BUTTON2         5     // Button 2 pressed state
#define BUTTON3         3     // Button 3 pressed state

int buttonState;     

void setup()
{

  {
  Serial.begin(9600);
  button.setDebounceTime(10); // set debounce time to 10 milliseconds
  button2.setDebounceTime(10); // set debounce time to 10 milliseconds
  button3.setDebounceTime(10); // set debounce time to 10 milliseconds


}

// SWITCHES AS INPUT PULLUP
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);

// RELAYS AS OUTPUT
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);

// INITIALIZE ALL RELAYS ON OFF STATE
digitalWrite(RELAY1_PIN, HIGH);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);

}
void loop()
{

button.loop(); // MUST call the loop() function first

  if(button.isPressed())
    Serial.println("The button is pressed");

  if(button.isReleased())
    Serial.println("The button is released");

  buttonState = button.isPressed() + 2* button2.isPressed() + 4* button3.isPressed(); // Put all the buttons states togheter in the buttonState variable to evaluate
  /* button3 button2 button1
  0   0       0       0         All button pressed (no action)
  1   0       0       1         Button 2 + Button 3 pressed (no action)
  2   0       1       0         Button 1 + Button 3 pressed (no action)
  3   0       1       1         Button 3 pressed
  4   1       0       0         Button 1 + Button 2 pressed (no action)
  5   1       0       1         Nutton 2 pressed
  6   1       1       0         Button 1 pressed
  7   1       1       1         No button pressed (no action)
*/
  switch(buttonState)
  {
    case BUTTON1:                       // Button 1
      digitalWrite(RELAY1_PIN, HIGH);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, LOW);
      break;

    case BUTTON2:                       // Button 2
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, HIGH);
      digitalWrite(RELAY3_PIN, LOW);
      break;   

    case BUTTON3:                        // Button 3
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, HIGH);
      break;
  }
   
}

ElectricDruid

You've got an open brace { in the setup code which has no closing brace. That doesn't need to be there. That should be throwing an error and not letting anything compile.

Also if button2 and button3 are named like that, can we call "button" button1, please? It's triggering my programmer's OCD really badly! Thanks. ;)

These #defines are all wrong:

#define BUTTON1         6     // Button 1 pressed state
#define BUTTON2         5     // Button 2 pressed state
#define BUTTON3         3     // Button 3 pressed state


These constants are used to test the button states in the switch statement, so they need to match the values given in the buttonState line:

buttonState = button1.isPressed() + 2* button2.isPressed() + 4* button3.isPressed();

E.g. It should look like this:

#define BUTTON1         1     // Button 1 pressed state
#define BUTTON2         2     // Button 2 pressed state
#define BUTTON3         4     // Button 3 pressed state


If you don't understand *why* those values need to be like that, *please* ask because you'll never get better at this stuff unless you learn the bits you don't understand (Clue: It's binary, setting bits in a byte)

HTH

Buffalo Tom

Hi. Here is the code I ended up with. Im posting it here so its available if someone else is looking for a 3 button "radio" switcher. Works for me  ;)

#include <ezButton.h>

#define BUTTON1_PIN     2     // Button 1 pin
#define BUTTON2_PIN     3     // Button 2 pin
#define BUTTON3_PIN     4     // Button 3 pin
#define RELAY1_PIN      8     // Relay 1 pin
#define RELAY2_PIN      9     // Relay 2 pin
#define RELAY3_PIN     10     // Relay 3 pin
#define BUTTON1         6     // Button 1 pressed state
#define BUTTON2         5     // Button 2 pressed state
#define BUTTON3         3     // Button 3 pressed state

int buttonState;     

ezButton button1(BUTTON1_PIN);
ezButton button2(BUTTON2_PIN);
ezButton button3(BUTTON3_PIN);

void setup()
{

// SWITCHES AS INPUT PULLUP
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(BUTTON3_PIN, INPUT_PULLUP);

// RELAYS AS OUTPUT
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);

// INITIALIZE ALL RELAYS ON OFF STATE
digitalWrite(RELAY1_PIN, HIGH);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);

// DEBOUNCE
button1.setDebounceTime(50); // set debounce time to 50 milliseconds
button2.setDebounceTime(50); // set debounce time to 50 milliseconds
button3.setDebounceTime(50); // set debounce time to 50 milliseconds

}
void loop()
{
    button1.loop(); // MUST call the loop() function first
    button2.loop(); // MUST call the loop() function first
    button3.loop(); // MUST call the loop() function first

    buttonState = button1.getState() | button2.getState() << 1 | button3.getState() << 2;
   /* button3 button2 button1
    0   0       0       0         No button pressed
    1   0       0       1         Button 1 pressed
    2   0       1       0         Button 2 pressed
    3   0       1       1         Button 1 + Button 2 pressed (no action)
    4   1       0       0         Button 3 pressed
   */
  switch(buttonState)
  {
    case BUTTON1:                       // Button 1
      digitalWrite(RELAY1_PIN, HIGH);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, LOW);
      break;

    case BUTTON2:                       // Button 2
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, HIGH);
      digitalWrite(RELAY3_PIN, LOW);
      break;   

    case BUTTON3:                        // Button 3
      digitalWrite(RELAY1_PIN, LOW);
      digitalWrite(RELAY2_PIN, LOW);
      digitalWrite(RELAY3_PIN, HIGH);
      break;
  }
   
}