How to control LED parameters with multiple button pushes

My initial thought was to use 4 buttons and assign specific values to the buttons. For example Button 1 100Hz, Button2 200 Hz, Button 3 -1000 Hz and so on but it seems very complicated and I could not get any working idea how to implement it.
Instead I’m using three buttons, one for each parameter. For example button 1 defines the frequency ( period) and the value will change with the number of pushes. Button2 control On -time and Button3 OFF-time. Once all parameters are entered Button4 is pushed to complete the entry of ALL parameters. I’m using EZ button program and if /else.
I have a problem with the code. Instead of values for parameters I’m getting 0 for all my parameters.

include <ezButton.h>
const int ledPin = 11;
ezButton button1(2);  // create Button object that attach to pin 2;
ezButton button2(3);  // create Button object that attach to pin 3;
ezButton button3(4);
ezButton button4(5);
int period = 0;
float power = 0;
float runtime = 0;
int ledon = 0;
int ledoff = 0;
int countt = 0;
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  button1.setDebounceTime(50); // set debounce time to 50 milliseconds
  button2.setDebounceTime(50); // set debounce time to 50 milliseconds
  button3.setDebounceTime(50);
  button4.setDebounceTime(50);
  button1.setCountMode(COUNT_FALLING);
  button2.setCountMode(COUNT_FALLING);
  button3.setCountMode(COUNT_FALLING);
  button4.setCountMode(COUNT_FALLING);
}
void loop() {
  button1.loop(); // MUST call the loop() function first
  button2.loop(); // MUST call the loop() function first
  button3.loop();
  button4.loop();
  int btn1State = button1.getState();
  int btn2State = button2.getState();
  int btn3State = button3.getState();
  int btn4State = button4.getState();
  unsigned long btn1Count = button1.getCount();
  unsigned long btn2Count = button2.getCount();
  unsigned long btn3Count = button3.getCount();
  unsigned long btn4Count = button4.getCount();
  Serial.print("button 1 count: ");
  Serial.println(btn1Count);
  Serial.print("button 2 count: ");
  Serial.println(btn2Count);
  Serial.print("button 3 count: ");
  Serial.println(btn3Count);
  Serial.print("button 4 count: ");
  Serial.println(btn4Count);
  if (btn1Count % 1 == 0) {
    int period = 12500;
  }
  else if (btn1Count % 2 == 0) {
    int period = 10000;
  }
  else if (btn1Count % 3 == 0) {
    int period = 4000;
  }
  else if (btn1Count % 4 == 0) {
    int period = 2000;
  }

  if (btn2Count % 1 == 0) {
    float power = 1;
  }
  else if (btn2Count % 2 == 0) {
    float power = 0.8;
  }
  else if (btn2Count % 3 == 0) {
    float power = 0.6;
  }
  else  if (btn2Count % 4 == 0) {
    float power = 0.4;
  }
  else {
    delay (50);
  }

  if (btn3Count % 1 == 0) {
    float runtime = 6000;
  }
  else  if (btn3Count % 2 == 0) {
    float runtime = 8000;
  }
  else  if (btn3Count % 3 == 0) {
    float runtime = 20000;
  }

  else if (btn3Count % 4 == 0) {
    float runtime = 30000;
  }
  else {
    delay (50);
  }

  if ( btn4Count! == 0) {
    ledon = period * power;
    ledoff = period * (1 - power);
    countt = runtime / period * 1000;
    Serial.print("period: ");
    Serial.println(period);
    Serial.print("power: ");
    Serial.println(power);
  }
  else {
    delay (50);
  }

  for (int x = 0; x < countt; x++) {
    if (x == countt - 1) {
      digitalWrite(ledPin, LOW);
      delay (1000000);
    }
    else {
      digitalWrite(ledPin, HIGH);
      delayMicroseconds(ledon);
      digitalWrite(ledPin, LOW);
      delayMicroseconds(ledoff);
    }
  }
}

I believe float here, and in all the places except the one place you want it, is causing you trouble.

Leave this as is:

int period = 0;
float power = 0;
float runtime = 0;
int ledon = 0;
int ledoff = 0;
int countt = 0;

and remove int and float where it appears before those variables elsewhere.

Google

  C++ variable scope

and you will learn why.

a7

1 Like

Thank you! I will try.

Really dumb mistake. I removed int and float and It returns the parameters after button is pressed but it still does not work properly. No matter how many times I press the button and what button count I get it always return the value of the prameter corresponding to a single press of the button.

Another problem is no matter what debounce time I choose I get periodically 2 counts for one button press. I don't think the problem is keypad as I tried 4 different pads with the same result. I suppose the problem with EZ button library.

Hello
I´ve read your post and I think you are missing one button as follows
buttons 1/2 == +/- duty cylce
buttons 3/4 == +/- period length
button 5 == set values for duty cylcle and period length
Have a nice day and enjoy coding in C++.

hello, I've got 4 buttons and I don't use any toggle switches.

That you were the very first person to ever make!

Now you have real problems, so post the new code in a new post and we can get started… I’m prolly not the only one who stopped thinking about it after seeing the mistake.

a7

Well, I guess once that line is executed you'll misinterpretate any phenomen you may observe - or believe to observe

Will do

All phenomena definitely occur before it gets executed.

Can you explain again in detail what you want to acheive here?

So 4 buttons.... Pressing each increment a value for a variable. What if you want to decrement a value?

Is this just to control a single LED?

There are no increments but fixed parameters . I have sets of 4 values for each parameter. For example the frequency parameter has following values: 12500, 10000, 4000, 2000.
1 Button 1 press suppose to return 12500. 2 Button1 presses suppose to return 10000 and so on.
Its a LED string but you can consider it a single LED

Okay. I think that there might be simpler ways to do what you want here. Can you describe (without using values/code) the behaviour you want from pressing each of the buttons?

I want Button1 to set different frequencies for LED blinking,
Button 2 different LED powers.
Button 3 sets the time how long the LED is blinking .
Once I enter all three parameters I want to press start button (Button 4) and activate the program.

I will have a signal LED that will indicate button press. If any button is pressed one time the LED will blink one time, if the same button pressed 2 times the LED will blink 2 times .... I have not added it to my code yet but it should be easy.

I made all suggested changes but the problems are the same.
The debounce function does not work.
Assigned parameters don't depend on the number of button presses and the program always assigns the parameter corresponding to one button press. For example Button 1 is pressed 4 times but the value of period is 12500 instead of 2000.

Serial.println(btn1Count);
  Serial.print("button 2 count: ");
  Serial.println(btn2Count);
  Serial.print("button 3 count: ");
  Serial.println(btn3Count);
  Serial.print("button 4 count: ");
  Serial.println(btn4Count);
  
  if (btn1Count %1  == 0)    {
    period = 12500;
  }
  else if (btn1Count % 2 == 0) {
    period = 10000;
  }
  else if (btn1Count % 3 == 0) {
    period = 4000;
  }
  else if (btn1Count % 4 == 0) {
    period = 2000;
  }

  if (btn2Count % 1 == 0) {
      power = 1;
  }
  else if (btn2Count % 2 == 0) {
      power = 0.8;
  }
  else if (btn2Count % 3 == 0) {
       power = 0.6;
  }
  else  if (btn2Count % 4 == 0) {
       power = 0.4;
  }
  else {
    delay (1);
  }

  if (btn3Count % 1 == 0) {
       runtime = 6000;
  }
  else  if (btn3Count % 2 == 0) {
       runtime = 8000;
  }
  else  if (btn3Count % 3 == 0) {
       runtime = 20000;
  }

  else if (btn3Count % 4 == 0) {
       runtime = 30000;
  }
  else {
    delay (1);
  }

  if ( btn4Count > 0) {
    ledon = period * power;
    ledoff = period * (1 - power);
    countt = runtime / period * 1000;
    Serial.print("period: ");
    Serial.println(period);
    Serial.print("power: ");
    Serial.println(power);
  }
  else {
    delay (1);
  }

  for (int x = 0; x < countt; x++) {
    if (x == countt - 1) {
      digitalWrite(ledPin, LOW);
      delay (10000);
    }
    else {
      digitalWrite(ledPin, HIGH);
      delayMicroseconds(ledon);
      digitalWrite(ledPin, LOW);
      delayMicroseconds(ledoff);
    }
  }
}

Please reply on this thread (this topic) to this message I am writing here on this thread and

show us the current program that compiles, runs and does not do what you want or expect.

Just hit Reply and stay right here, ‘K?

a7

Here is the program.

type or #include <ezButton.h>
const int ledPin = 11;
ezButton button1(3);  // create Button object that attach to pin 2;
ezButton button2(2);  // create Button object that attach to pin 3;
ezButton button3(5);
ezButton button4(4);
int period = 0;
float power = 0;
float runtime = 0;
int ledon = 0;
int ledoff = 0;
int countt = 0;
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  button1.setDebounceTime(65); // set debounce time to 50 milliseconds
  button2.setDebounceTime(55); // set debounce time to 50 milliseconds
  button3.setDebounceTime(55);
  button4.setDebounceTime(55);
  button1.setCountMode(COUNT_FALLING);
  button2.setCountMode(COUNT_FALLING);
  button3.setCountMode(COUNT_FALLING);
  button4.setCountMode(COUNT_FALLING);
}
void loop() {
  button1.loop(); // MUST call the loop() function first
  button2.loop(); // MUST call the loop() function first
  button3.loop();
  button4.loop();
  int btn1State = button1.getState();
  int btn2State = button2.getState();
  int btn3State = button3.getState();
  int btn4State = button4.getState();
  unsigned long btn1Count = button1.getCount();
  unsigned long btn2Count = button2.getCount();
  unsigned long btn3Count = button3.getCount();
  unsigned long btn4Count = button4.getCount();
  Serial.print("button 1 count: ");
  Serial.println(btn1Count);
  Serial.print("button 2 count: ");
  Serial.println(btn2Count);
  Serial.print("button 3 count: ");
  Serial.println(btn3Count);
  Serial.print("button 4 count: ");
  Serial.println(btn4Count);
  
  if (btn1Count %1  == 0)    {
    period = 12500;
  }
  else if (btn1Count % 2 == 0) {
    period = 10000;
  }
  else if (btn1Count % 3 == 0) {
    period = 4000;
  }
  else if (btn1Count % 4 == 0) {
    period = 2000;
  }

  if (btn2Count % 1 == 0) {
      power = 1;
  }
  else if (btn2Count % 2 == 0) {
      power = 0.8;
  }
  else if (btn2Count % 3 == 0) {
       power = 0.6;
  }
  else  if (btn2Count % 4 == 0) {
       power = 0.4;
  }
  else {
    delay (1);
  }

  if (btn3Count % 1 == 0) {
       runtime = 6000;
  }
  else  if (btn3Count % 2 == 0) {
       runtime = 8000;
  }
  else  if (btn3Count % 3 == 0) {
       runtime = 20000;
  }

  else if (btn3Count % 4 == 0) {
       runtime = 30000;
  }
  else {
    delay (1);
  }

  if ( btn4Count > 0) {
    ledon = period * power;
    ledoff = period * (1 - power);
    countt = runtime / period * 1000;
    Serial.print("period: ");
    Serial.println(period);
    Serial.print("power: ");
    Serial.println(power);
  }
  else {
    delay (1);
  }

  for (int x = 0; x < countt; x++) {
    if (x == countt - 1) {
      digitalWrite(ledPin, LOW);
      delay (10000);
    }
    else {
      digitalWrite(ledPin, HIGH);
      delayMicroseconds(ledon);
      digitalWrite(ledPin, LOW);
      delayMicroseconds(ledoff);
    }
  }
}

Here is the serial monitor:
button 1 count: 4
button 2 count: 4
button 3 count: 4
button 4 count: 2
period: 12500
power: 1.00

Haha, x mod 1 is… 0.

Anything modulo 1 is zero.

The range of values for an integer modulo operation of n is 0 to n − 1 inclusive (a mod 1 is always 0 ; a mod 0 is undefined, possibly resulting in a division by zero error in some programming languages).

HTH

a7

OK, refueled.

  btn1Count % 4

will cycle through the values 0, 1, 2, 3 repeat.

So like

  if ((btn1Count %4)  == 0) {
     period = 12500;
  }
  else if ((btn1Count % 4) == 1) {
     period = 10000;
  }
  else if ()btn1Count % 4) == 2) {
     period = 4000;
  }
  else if ()btn1Count % 4) == 3) {
     period = 2000;
  }

HTH

a7

I did it with:

``
`if (btn1Count == 1) { // period value in us
period = 12500;
}
else if (btn1Count == 2) {
period = 10000;
}
else if (btn1Count == 3) {
period = 4000;
}
else if (btn1Count == 4) {
period = 2000;
}

It returns proper values of entered parameters. However the math does not work in my code.

period: 10000
power: 90
ledon: 21568.00
ledoff: 16960.00

ledon supposed to be 9000000