I am using a button as a switch, it turns on but doesn't turn off (Arduino)

1.5k views Asked by At

I am trying to make a button work as a switch. The code works to turn the lights "on" but the code doesn't want to turn them off.

My code works like so:

  1. If button is pressed and the lights are off, turn on the lights.
  2. If button is pressed and the lights are on, turn off the lights.

But number 2 doesn't work.

int buttonStatus = 0;
int check = 1;
int Status = 0;

void setup() {
  pinMode(5,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(13,OUTPUT);
  pinMode(2,INPUT);
}

void loop() {
  if (check = 1) {
    buttonStatus = digitalRead(2);
    if (buttonStatus == HIGH && Status == 0) {
      Status = 1;
      buttonStatus = 0;
    } else if (buttonStatus == HIGH && Status == 1) {
      Status = 0;
      buttonStatus = 0;
    }
  }

  if (Status == 1) {
    digitalWrite(5,HIGH);
    delay(50);
    digitalWrite(5,LOW);
    digitalWrite(7,HIGH);
    delay(50);
    digitalWrite(7,LOW);
    digitalWrite(9,HIGH);
    delay(50);
    digitalWrite(9,LOW);
    digitalWrite(11,HIGH);
    delay(100);
    digitalWrite(11,LOW);
    digitalWrite(13,HIGH);
    delay(100);
    digitalWrite(13,LOW);
  } else {
    digitalWrite(5,LOW);
    digitalWrite(7,LOW);
    digitalWrite(9,LOW);
    digitalWrite(11,LOW);
    digitalWrite(13,LOW);
  }
}
3

There are 3 answers

5
frarugi87 On BEST ANSWER

Ok, your description and your code tell two different things. I'm try to interprete them, but if I'm wrong just tell me and I'll try to correct the answer.

This code lets you use a pushbutton to turn on and off a light on pin 5. One press will turn it on, the other will turn it off. You have to connect the button with one end to pin 2 and the other to ground (since we are using a pull-up resistor).

I also added a small debounce delay to cope with the bounces of the mechanical switch (50ms)

byte buttonStatus;
unsigned long lastEqualButtonTime;
#define debounceTimeMs 50

void setup() {
    pinMode(5,OUTPUT);
    pinMode(2,INPUT_PULLUP);
    buttonStatus = digitalRead(2);
    lastEqualButtonTime = millis();
}

void loop() {
    byte currentButtonStatus = digitalRead(2);
    if (currentButtonStatus == buttonStatus)
        lastEqualButtonTime = millis();
    else if ((millis() - lastEqualButtonTime) > debounceTimeMs)
    {
        lastEqualButtonTime = millis();
        buttonStatus = currentButtonStatus;

        // Change only on change, not on value
        if (buttonStatus == LOW) {
            digitalWrite(5, !digitalRead(5));
        }
    }
}

When you press the button the led on pin 5 will turn on, when you press it again it will turn off.

This is the behavior you asked. Your code, on the other side, lights up a sequence of LEDs when you push the button. In this case, if you want to start the cycle with a press and then stop it with another press, you have to use a sort of simple state machine, like the one in the code. I also added a small debounce to the button, which needs again to be connected between 2 and ground.

byte buttonStatus;
unsigned long lastEqualButtonTime;
#define debounceTimeMs 50

// Statuses
#define STATE_LEDSOFF 0
#define STATE_LED5ON  1
#define STATE_LED7ON  2
#define STATE_LED9ON  3
#define STATE_LED11ON 4
#define STATE_LED13ON 5

// How much time should each led be on?
// Expressed in milliseconds
#define TIME_LED5ON   50
#define TIME_LED7ON   50
#define TIME_LED9ON   50
#define TIME_LED11ON 100
#define TIME_LED13ON 100

byte stateMachineStatus;
unsigned long stateMachineTime;

void setup() {
    pinMode(5,OUTPUT);
    pinMode(7,OUTPUT);
    pinMode(9,OUTPUT);
    pinMode(11,OUTPUT);
    pinMode(13,OUTPUT);
    pinMode(2,INPUT_PULLUP);
    buttonStatus = digitalRead(2);
    lastEqualButtonTime = millis();
    stateMachineStatus = STATE_LEDSOFF;
}

void loop() {
    byte currentButtonStatus = digitalRead(2);
    if (currentButtonStatus == buttonStatus)
        lastEqualButtonTime = millis();
    else if ((millis() - lastEqualButtonTime) > debounceTimeMs)
    {
        lastEqualButtonTime = millis();
        buttonStatus = currentButtonStatus;

        // Change only on change, not on value
        if (buttonStatus == LOW) {
            // Turn on the LEDs sequence if it was off
            if (stateMachineStatus == STATE_LEDSOFF)
            {
                stateMachineStatus = STATE_LED5ON;
                stateMachineTime = millis();
            }
            else // Turn it off if it was on
                stateMachineStatus = STATE_LEDSOFF;
        }
    }

    switch (stateMachineStatus)
    {
    case STATE_LEDSOFF:
        digitalWrite(5,LOW);
        break;
    case STATE_LED5ON:
        digitalWrite(5,HIGH);
        if ((millis() > stateMachineTime) > TIME_LED5ON)
        {
            stateMachineTime += TIME_LED5ON;
            digitalWrite(5,LOW);
            stateMachineStatus = STATE_LED7ON;
        }
        break;
    case STATE_LED7ON:
        digitalWrite(7,HIGH);
        if ((millis() > stateMachineTime) > TIME_LED7ON)
        {
            stateMachineTime += TIME_LED7ON;
            digitalWrite(7,LOW);
            stateMachineStatus = STATE_LED9ON;
        }
        break;
    case STATE_LED9ON:
        digitalWrite(9,HIGH);
        if ((millis() > stateMachineTime) > TIME_LED9ON)
        {
            stateMachineTime += TIME_LED9ON;
            digitalWrite(9,LOW);
            stateMachineStatus = STATE_LED11ON;
        }
        break;
    case STATE_LED11ON:
        digitalWrite(11,HIGH);
        if ((millis() > stateMachineTime) > TIME_LED11ON)
        {
            stateMachineTime += TIME_LED11ON;
            digitalWrite(11,LOW);
            stateMachineStatus = STATE_LED13ON;
        }
        break;
    case STATE_LED13ON:
        digitalWrite(13,HIGH);
        if ((millis() > stateMachineTime) > TIME_LED13ON)
        {
            stateMachineTime += TIME_LED13ON;
            digitalWrite(13,LOW);
            stateMachineStatus = STATE_LED5ON;
        }
        break;
    default:
        stateMachineStatus = STATE_LEDSOFF;
        break;

    }
}

This works in this way: you press the button and the board will start cycling through the LEDS. 5, 7, 9, 11, 13, 5, 7, 9, 11, 13, ... Until you press again the button. When you do this, it stops, then at the next press restarts from 5.

If you want that after the 13 it stops, change the line 105 from stateMachineStatus = STATE_LED5ON; to stateMachineStatus = STATE_LEDSOFF;.

One note: in your code the delay is too low (and it is the same that I put here): 50 ms between one led and the other cannot be noticed. If you want to actually see them in sequence, put values of at least 250 in the TIME_LEDxON defines.

DISCLAIMER: I haven't tested these codes since I don't have arduino ide installed at present. If there are some bugs, simply tell me and I'll fix them.

3
Chris8447 On

Maybe it's because of a floating pin. Have you built in a pull up or pull down resistor?

It's a common thing...

2
bnss On

Try adding debounce delay. This is common issue with switches. https://www.arduino.cc/en/Tutorial/Debounce