Changing LED intensity in well defined steps

Hello! I have two push buttons. I want the first pushbutton to increase the analogWrite amount by 10. E.g. 10-> 20-> 30. The 2nd push button will decrement this value. The constrain function will be used to ensure the value does got go beyond 255/below 0 (e.g. value = constrain(value,0,255).

Pseudo code:

int value = 0;

loop(){
if (digitalRead(button1) == HIGH)
{ 
value +=10;
}
if(digitalRead(button2)==HIGH)
{
value -=10;
}

value = constrain(value, 0, 255);
analogWrite(11, value); // Write PWM output to pin 11.
delay(10);

}

The thing is, if I hold down the pushbutton, it will rise pretty fast to 255. That's a nice effect, but not what I want. I would like it to only increase by 10 with every push, not based on how long I hold the button down.

Do I need to look into say, a simple state machine to make this work? I have done this with state machines for more complex stuff, but with the Arduino, I'm very new to it and not sure if there are already solutions/libraries for this.

Thank you!

Do I need to look into say, a simple state machine to make this work?

You need to look at how you are reading the switch. When the switch state is HIGH, you may or may not need to increment value, depending on what it's previous state is. So, you need to record the previous state of the button press, and compare the current state to the previous state. Only when the current state is HIGH and the previous state was LOW would you increment/decrement value.

By the way, value is a lousy name. What is the value being held the value of? It is impossible to tell from the name.

You'll need to add 4 more variables, currState1, prevState1, currState2, and prevState2.

int currState1;
int prevState1 = LOW;
int currState2;
int prevState2 = LOW;

void loop()
{
   currState1 = digitalRead(button1);
   if(currState1 == HIGH && prevState1 == LOW)
   {
      value += 10;
   }
   prevState1 = currState1;

   // Do the same for switch 2, except decrement

   // Use value
}

Hi Paul! Thanks! That's a very elegant solution. I'll give that a go tonight :) And yes, value is a really bad name. I'll be sure to try and create better named variables.

Cheers!

You will probably need to adjust the step size by experiment, if the perceived brightness is what you're going off, the human eye is far from linear.

pluggy: You will probably need to adjust the step size by experiment, if the perceived brightness is what you're going off, the human eye is far from linear.

Interesting! I may try applying a lookup table (power function perhaps) to normalized values to see how they respond. Cheers!

At some point your program notices the button is pushed, takes action and... checks again.

You're not waiting for the button to be released. With a delay of 10 (ms) your program will have checked and taken action 10 times in a tenth of a second.

It's extremely hard for us, non electronic slugs, to just push the button 1/100 second and get the effect you want. Increasing the delay is a solution, but intensity will keep increasing/decreasing as long as you push a button.

If you only want to in/decrease once every time you hit the button, waiting for the pin to go low might be a better option.

Something like this :

void loop()
{
   currState1 = digitalRead(button1);
   if(currState1 == HIGH && prevState1 == LOW)
   {
      value += 10;
      while(digitalRead(button1) = HIGH){
      }
   }
   prevState1 = currState1;

   // Do the same for switch 2, except decrement

   // Use value
}
      while(digitalRead(button1) = HIGH){

I don't think that you can assign HIGH to digitalRead(button1).

There is no reason to keep doing nothing while the switch is help down., since the block that you added code to is only executed when the switch is pressed and was not pressed the last time checked.

Thank you, I'm in between programming environments and (without checking :cold_sweat:) make mistakes like that often.