Control LED brightness with Push Button

I am trying to have an LED that flashes every 3 seconds at one brightness level and then when a button is pressed the level of brightness changes. The first thing I wanted to try do was just get the LED to change brightness when the button is pressed. However, when I set this up using the image and the code below, the LED just changed brightness without the button being pressed at all. Any help on what may be causing this error would be appreciated.

int pinLed=9;
int pinButton=12;
int push_button_state = 0;
int led_brightness = 0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(pinButton, INPUT);
  pinMode(pinLed, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
  analogWrite(pinLed, led_brightness);
  push_button_state = digitalRead(pinButton);
  if (push_button_state == HIGH) {
    led_brightness = led_brightness +63;
  }
if (led_brightness > 255) {
  led_brightness = 0;
  analogWrite(pinLed, led_brightness);
}
delay(100);
}

My eyes are going nuts trying to untie that diagram. Please post a real, conventional schematic. Yes, I could figure it out. But I have better things to do.

Probably, you've wired your switch to be on all the time.

I tried to implement it on the Wokwi Arduino Simulator.

Here is the simulation link: blink-no-delay.ino - Wokwi Arduino and ESP32 Simulator

Please try this and see what you meant here or not. if not, Please break your requirements into multiple sub-functions(reading button, blinking LED for a certain period, etc). And verify one by one. Later you can merge them together.

/* Blink an LED without using delay() */
#define LED 9
#define BUTTON 12
unsigned long timeOn = 500;
unsigned long changeTime = 0;
void setup() {
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
}
unsigned char ledValue = 0;

void loop() {
  if (millis() >= changeTime)  {
    ledValue = !ledValue;
    analogWrite(LED, ledValue);
    changeTime = millis() + timeOn;
  }
  if (digitalRead(BUTTON) == 0) {
    ledValue = ledValue + 20;
    if (ledValue > 240) {
      ledValue = 0;
    }
  }
}

chrome_V4vqTcwR85

1 Like

With those 4 terminal 6mm tactile switches, wire to diagonal terminals to avoid a short.

1 Like

it looks like you've wired the button switch between ground and a 10k resistor to 5V and then a 10k resistor between that same pin to pin 12. as @groundFungus suggests, you can use an internal pullup resistor by configuring the pin as INPUT_PULL and you don't need any other resistor between the switch and pin

doing above, the pin will be pulled LOW when the button is pressed.

but the other thing to consider is that your code increases the led_brightness as long as the button is active, not with each press. to detect a press, the code needs to keep track of the button state and recognize a change in state and then the state that is active (i.e. LOW)

since analogWrite() is called at the top of loop(), there's no need to call it again when led_brightness wraps.

of course you only need to check for wrap after increasing it when a button press is detected as well as only needing to call analogWrite() when there's a button press

1 Like

Thank you, I will have a go at this and will see if I can implement the requirements in stages

Hi I think I have incorporated using INPUT_PULLUP but I am having trouble changing the state of the LED and I think it is because I am not correctly keeping track of the LED state. Just wondering would you have any advice for this?

post your code

Any time that you make any change to your code, post the newest version so that we can keep up.

1 Like
int buttonPin = 12; // the number of the push button pin
int ledPin = 9;     // the number of the LED pin

int ledBrightness = 255; //level of brightness
int buttonState; //variable to save state of button
int lastState= LOW; // button previous state

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);  // set push button pin into input mode
  pinMode(ledPin, OUTPUT);    // set LED pin into output mode
}

void loop() {
  buttonState = digitalRead(buttonPin); //read state of button
  digitalWrite(ledPin, ledBrightness); //assign brightness level to LED
    if (lastState == 0 && buttonState == HIGH) {
      ledBrightness = 255-63;
   } 
    else {
     delay(500);
     digitalWrite(ledPin, 0);
  }
}

At the moment the LED remains on the one level of brightness even when the button is not pushed. I was hoping when the button is not pushed it would turn off and turn on again. I was also wondering do I need to incorporate anything to handle the bounce for the push button.

  • where is lastState updated?
    it needs to be updated whenever there is a state change, not just the one you're looking for
  • where is ledBrightness used? you replaced using analogWrite() with digitalWrite()
  • why is there a 1/2 sec delay in the else case?
  • if you simply want to toggle the LED on/off consider
digitalWrite (ledPin, ! digitalRead (ledPin));
1 Like

You need an analogWrite() not a digitalWrite().

Look at the following to properly detect a button press: StateChangeDetection

1 Like

See also state change detection for active low inputs for information on using switches connected to ground instead of Vcc.

1 Like

@groundFungus. FYI, I always reference your tutorial rather than the original. :grinning:

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.