Controlling 3 loads using push button

Hello

I 've been doing a project and I have to control 3 different loads using a button. I tried using this code:

int led1 = 2;
int led2 = 3;
int led3 = 4;
int controle1 = 9;
int controle2 = 10;
int controle3 = 11;

void setup()
{
pinMode (led1, OUTPUT);
pinMode (controle1 , INPUT);
pinMode (led2, OUTPUT);
pinMode (controle2 , INPUT);
pinMode (led3, OUTPUT);
pinMode (controle3 , INPUT);
}

void loop()
{
delay(10); // Delay a little bit to improve simulation performance
digitalWrite(led1 , LOW);
digitalWrite(led2 , LOW);
digitalWrite(led3 , LOW);

while( digitalRead(led1) == 0 ) {
if (digitalRead(controle1) == 0) {
digitalWrite(led1, HIGH);
delay (3000);
}
}
while ( digitalRead(led1) == 1 ) {
if (digitalRead(controle1) == 0) {
digitalWrite(led1, LOW);
delay (3000);
}
}
while ( digitalRead(led2) == 0) {
if (digitalRead(controle2) == 0) {
digitalWrite(led2, HIGH);
delay (3000);
}
}
while ( digitalRead(led2) == 1) {
if (digitalRead(controle2) == 0) {
digitalWrite(led2, LOW);
delay (3000);
}
}

while ( digitalRead(led3) == 0) {
if (digitalRead(controle3) == 0) {
digitalWrite(led3, HIGH);
delay (3000);
}
}
while ( digitalRead(led3) == 1) {
if (digitalRead(controle3) == 0) {
digitalWrite(led3, LOW);
delay (3000);
}
}
}

But when I tested it I got one problem, the output would only work in the order led1 turn on , led 1 turn off, led2 turn on and this goes on, I couldn't use the second load first and I also couldn't turn two leds on at the same time.
Thanks in advance.

Your while loops and delays are blocking everything else. Take a look at the Blink Without Delay example and the following guides:
http://forum.arduino.cc/index.php?topic=503368.0
http://forum.arduino.cc/index.php?topic=223286.0

Once you understand that, you can make abstraction of the concept and put it inside a class. This is especially useful if you need the same code multiple times (e.g. for your three loads).

class TimerOutput {
  public:
    TimerOutput(uint8_t pin)
      : pin(pin) {
      pinMode(pin, OUTPUT);  // Set the pin as a digital output
    }
    void turnOff() {
      digitalWrite(pin, LOW);  // Turn off the output
      timerActive = false;     // Disable the timer
    }
    void turnOn() {
      digitalWrite(pin, HIGH);  // Turn on the output
      timerActive = false;      // Disable the timer
    }
    void turnOnFor(unsigned long duration) {
      digitalWrite(pin, HIGH);  // Turn on the output
      timerActive = true;       // Enable the timer
      startOnTime = millis();   // Remember the current time
      onDuration = duration;    // Remember how long it has to stay on
    }
    void refresh() {
      if (timerActive                                 // If the timer is running,
        && (millis() - startOnTime >= onDuration)) {  // and the output has been on for the desired duration or longer
        turnOff();                                    // Turn it off
      }
    }
  private:
    const uint8_t pin;
    bool timerActive = false;
    unsigned long startOnTime;
    unsigned long onDuration;
};

/* ----------------------------------------------------------------------------------------------------------------------- */

class PushButton {
  public:
    PushButton(uint8_t pin)
      : pin(pin) {
      pinMode(pin, INPUT_PULLUP);  // Set the pin as a digital input, and enable the internal pull-up resistor
    }
    bool isFalling() {  // Returns true if the input pin's state goes from high to low (i.e. if the button is pressed)
      bool currentState = digitalRead(pin);  // Read the button state
      bool falling = false;
      if (previousState != currentState) {  // If the state changed since last time
        if (currentState == LOW) {          // If the current state is low
          falling = true;                   // The input is low now, and it was high before, so it was falling
        }
        previousState = currentState;       // Remember the current state
      }
      return falling;
    }
  private:
    const uint8_t pin;
    bool previousState = HIGH;
};

/* ----------------------------------------------------------------------------------------------------------------------- */

TimerOutput led_A = { 2 }; // Initialize a TimerOutput object called 'led_A' on digital pin 2
TimerOutput led_B = { 3 };
TimerOutput led_C = { 4 };

PushButton button_A = {  9 };
PushButton button_B = { 10 };
PushButton button_C = { 11 };

void setup() {}

void loop() {
  if (button_A.isFalling()) {  // If the first button is pressed
    led_A.turnOnFor(3000);     // Turn on the first LED for 3 seconds
  }
  if (button_B.isFalling()) {
    led_B.turnOnFor(3000);
  }
  if (button_C.isFalling()) {
    led_C.turnOnFor(3000);
  }
  led_A.refresh(); // Refresh the first LED
  led_B.refresh();
  led_C.refresh();
}

As you can see, this code doesn't use any while loops or delays.

Pieter

I think you misunderstood one thnig about my code. The delay I put was so when I pressed the button it wouldn't be changing in a loop, so the person could press it and then the loud would be actived until I pressed it button again.

So you want to toggle the loads? (I.e. one press = on, second press = off.)
Then you need to debounce the pushbuttons, and remember the previous states in order to detect the falling edges:

class PushButton {
  public:
    PushButton(uint8_t pin) // Constructor (executes when a PushButton object is created)
      : pin(pin) { // remember the push button pin
      pinMode(pin, INPUT_PULLUP); // enable the internal pull-up resistor
    };
    bool isFalling() // read the button state check if the button has been pressed, debounce the button as well
    {
      bool falling = false;
      bool state = digitalRead(pin);               // read the button's state
      int8_t stateChange = state - previousState;  // calculate the state change since last time

      if (stateChange == fallingEdge) { // If the button is pressed (went from high to low)
        if (millis() - previousBounceTime > debounceTime) { // check if the time since the last bounce is higher than the threshold
          falling = true; // the button is pressed
        }
      }
      if (stateChange == risingEdge) { // if the button is released or bounces
        previousBounceTime = millis(); // remember when this happened
      }

      previousState = state; // remember the current state
      return falling; // return true if the button was pressed and didn't bounce
    };
  private:
    uint8_t pin;
    bool previousState = HIGH;
    unsigned long previousBounceTime = 0;

    const unsigned long debounceTime = 25;
    const int8_t risingEdge = HIGH - LOW;
    const int8_t fallingEdge = LOW - HIGH;
};

const uint8_t ledPin_A = 2;
const uint8_t ledPin_B = 3;
const uint8_t ledPin_C = 4;

PushButton button_A = {  9 };
PushButton button_B = { 10 };
PushButton button_C = { 11 };

void setup() {
  pinMode(ledPin_A, OUTPUT);  
  pinMode(ledPin_B, OUTPUT);  
  pinMode(ledPin_C, OUTPUT);  
}

void loop() {
  static bool ledState_A = false;
  static bool ledState_B = false;
  static bool ledState_C = false;

  if (button_A.isFalling()) {
    ledState_A = !ledState_A;  // Toggle the LED state
    digitalWrite(ledPin_A, ledState_A);  // Write the state to the pin
  }
  if (button_B.isFalling()) {
    ledState_B = !ledState_B;
    digitalWrite(ledPin_B, ledState_B);
  }
  if (button_C.isFalling()) {
    ledState_C = !ledState_C;
    digitalWrite(ledPin_C, ledState_C);
  }
}

Pieter

Hi,
Forget the while statements.

You need to detect the buttons BEING pushed, NOT in the pushed state.

This will help

Write code to get just one output to toggle ON and OFF.
Then simply write it two more times with button and load pinouts changed.

Tom... :slight_smile: