user37773: Desired program:
I have 3 momentary push buttons and a 4-channel relay board with my Arduino Uno. The relays are connected to 2 sinks, a shower, and a pump. Each push button should turn the pump and its respective fixture on for 10 seconds. I used a time buffer to debounce the push buttons.
Problem:
The time in which the function stays on is inconsistent. Sometimes 10 seconds, sometimes 3 seconds. Additionally all the relays turn off at the same time even if they were started at different times. they should all be individually timed and the pump should stay on as long as any of the three other relays are on.
Wiring Diagram:

Code:
//initialize and declare variables
// Pins 10,11,12,13 will be connected to their respected relays
const int pump = 13;
const int relay2 = 12;
const int relay3 = 11;
const int relay4 = 10;

//initialize pins 2,3,4 to be connected to the momentary push buttons
const int buttonPin1 = 2; 
const int buttonPin2 = 3; 
const int buttonPin3 = 4;

//these variables track the state of the buttons, low if not pressed, high if pressed
int buttonState1 = LOW; 
int buttonState2 = LOW;
int buttonState3 = LOW;

//Initialize pin states for valve check
int relay2State;
int relay3State;
int relay4State;

long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 100; // the debounce time; increase if the output flickers
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
unsigned long runTime = 10000;

void setup() {
  //set pins connected to the relays as outputs.
  pinMode(pump, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);

  //set push buttons as inputs
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);

  //initialize the starting state of the relay pins
  digitalWrite(pump, HIGH);
  digitalWrite(relay2, HIGH);
  digitalWrite(relay3, HIGH);
  digitalWrite(relay4, HIGH);
} // close void setup

void loop() {
  unsigned long currentMillis = millis();
  unsigned long currentMillis2 = millis();
  unsigned long currentMillis3 = millis();
  //sample the state of the buttons
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  buttonState3 = digitalRead(buttonPin3);
  //check to see if any valves are open
  relay2State = digitalRead(relay2);
  relay3State = digitalRead(relay3);
  relay4State = digitalRead(relay4);
  //filter out any noise by setting a time buffer
  if ((millis() - lastDebounceTime) > debounceDelay) {
    //sample the state of the buttons
    buttonState1 = digitalRead(buttonPin1);
    buttonState2 = digitalRead(buttonPin2);
    buttonState3 = digitalRead(buttonPin3);
    //check to see if any valves are open
    relay2State = digitalRead(relay2);
    relay3State = digitalRead(relay3);
    relay4State = digitalRead(relay4);
  }

  // if button1 has been pressed, let's toggle the pump and relay2 from off
  //to on for 10 seconds
  if (buttonState1 == HIGH) {
    digitalWrite(relay2, LOW); // turn relay2
    lastDebounceTime = millis(); // set the current time
  }
  if (currentMillis - previousMillis > runTime) {
    digitalWrite(relay2, HIGH); // turn relay2
    previousMillis = currentMillis;
  }
  //if button2 has been pressed, lets toggle the pump and relay3 from off
  //to on for 10 seconds
  if (buttonState2 == HIGH) {
    digitalWrite(relay3, LOW); // turn relay3 on
  }
  if (currentMillis2 - previousMillis2 > runTime) {
    previousMillis2 = currentMillis2;
    digitalWrite(relay3, HIGH); // turn relay3 off
  }
  // if button3 has been pressed, lets toggle the pump and relay4 from off to
  //on for 10 seconds
  if (buttonState3 == HIGH) {
    digitalWrite(relay4, LOW); // turn relay4 on
    lastDebounceTime = millis(); // set the current time
  }
  if (currentMillis3 - previousMillis3 > runTime) {
    previousMillis3 = currentMillis3;
    digitalWrite(relay4, HIGH); // turn relay4 off
  }
  // if any valve is open, turn the pump on
  if(relay2State == LOW || relay3State == LOW || relay4State == LOW) {
    digitalWrite(pump, LOW);
  } else {
    digitalWrite(pump, HIGH);
  }
} // close void loop

Any help would be greatly appreciated. I think I'm stuck in the time buffer for the debounce and my time checks aren't updating right.

user4143: In a program like this it rapidly becomes quite confusing with the variable names all being so similar. Because of this, this is a good candidate for creating a class to do the job for you. This is because you have sets of functionality and variables that are duplicated to do the same job with different settings (IO pins).
It would be a trivial matter to create a class that turns on an output for a specified amount of time:
class TimedOutput {
    private:
        uint8_t _pin;
        uint32_t _started;
        uint32_t _runtime;
        bool _running;

    public:
        TimedOutput(uint8_t pin, uint32_t runtime) {
            _pin = pin;
            _runtime = runtime;
            _started = 0;
            _running = false;
        }


        void begin() {
            pinMode(_pin, OUTPUT);
            digitalWrite(_pin, LOW);
        }

        void start() {
            digitalWrite(_pin, HIGH);
            _running = true;
            _started = millis();
        }

        void run() {
            if (!_running) return;
            if (millis() - _started >= _runtime) {
                digitalWrite(_pin, LOW);
                _running = false;
            }
        }
};

// Create the object
TimedOutput shower(10, 10000); // Output on pin 10 for 10 seconds
TimedOutput sink(11, 3000);    // Output on pin 11 for 3 seconds

void setup() {
    // Configure the pin
    shower.begin();
    sink.begin();
    pinMode(2, INPUT_PULLUP); // Button
    pinMode(3, INPUT_PULLUP); // Button
}

void loop() {
    // Start it if the button is pressed:
    if (digitalRead(2) == LOW) {
        shower.start();
    }

    if (digitalRead(3) == LOW) {
        sink.start();
    }

    // Do the checking for if it needs to stop:
    shower.run();
    sink.run();
}


37773: <p>Desired program:</p>

<p>I have 3 momentary push buttons and a 4-channel relay board with my Arduino Uno. The relays are connected to 2 sinks, a shower, and a pump. Each push button should turn the pump and its respective fixture on for 10 seconds. I used a time buffer to debounce the push buttons.</p>

<p>Problem:</p>

<p>The time in which the function stays on is inconsistent. Sometimes 10 seconds, sometimes 3 seconds. Additionally all the relays turn off at the same time even if they were started at different times. they should all be individually timed and the pump should stay on as long as any of the three other relays are on.</p>

<p>Wiring Diagram:</p>

<p><a href="https://i.stack.imgur.com/RpHyp.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/RpHyp.jpg" alt="enter image description here"></a></p>

<p>Code:</p>

<pre><code>//initialize and declare variables
// Pins 10,11,12,13 will be connected to their respected relays
const int pump = 13;
const int relay2 = 12;
const int relay3 = 11;
const int relay4 = 10;

//initialize pins 2,3,4 to be connected to the momentary push buttons
const int buttonPin1 = 2; 
const int buttonPin2 = 3; 
const int buttonPin3 = 4;

//these variables track the state of the buttons, low if not pressed, high if pressed
int buttonState1 = LOW; 
int buttonState2 = LOW;
int buttonState3 = LOW;

//Initialize pin states for valve check
int relay2State;
int relay3State;
int relay4State;

long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 100; // the debounce time; increase if the output flickers
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
unsigned long runTime = 10000;

void setup() {
  //set pins connected to the relays as outputs.
  pinMode(pump, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);

  //set push buttons as inputs
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);

  //initialize the starting state of the relay pins
  digitalWrite(pump, HIGH);
  digitalWrite(relay2, HIGH);
  digitalWrite(relay3, HIGH);
  digitalWrite(relay4, HIGH);
} // close void setup

void loop() {
  unsigned long currentMillis = millis();
  unsigned long currentMillis2 = millis();
  unsigned long currentMillis3 = millis();
  //sample the state of the buttons
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  buttonState3 = digitalRead(buttonPin3);
  //check to see if any valves are open
  relay2State = digitalRead(relay2);
  relay3State = digitalRead(relay3);
  relay4State = digitalRead(relay4);
  //filter out any noise by setting a time buffer
  if ((millis() - lastDebounceTime) &gt; debounceDelay) {
    //sample the state of the buttons
    buttonState1 = digitalRead(buttonPin1);
    buttonState2 = digitalRead(buttonPin2);
    buttonState3 = digitalRead(buttonPin3);
    //check to see if any valves are open
    relay2State = digitalRead(relay2);
    relay3State = digitalRead(relay3);
    relay4State = digitalRead(relay4);
  }

  // if button1 has been pressed, let's toggle the pump and relay2 from off
  //to on for 10 seconds
  if (buttonState1 == HIGH) {
    digitalWrite(relay2, LOW); // turn relay2
    lastDebounceTime = millis(); // set the current time
  }
  if (currentMillis - previousMillis &gt; runTime) {
    digitalWrite(relay2, HIGH); // turn relay2
    previousMillis = currentMillis;
  }
  //if button2 has been pressed, lets toggle the pump and relay3 from off
  //to on for 10 seconds
  if (buttonState2 == HIGH) {
    digitalWrite(relay3, LOW); // turn relay3 on
  }
  if (currentMillis2 - previousMillis2 &gt; runTime) {
    previousMillis2 = currentMillis2;
    digitalWrite(relay3, HIGH); // turn relay3 off
  }
  // if button3 has been pressed, lets toggle the pump and relay4 from off to
  //on for 10 seconds
  if (buttonState3 == HIGH) {
    digitalWrite(relay4, LOW); // turn relay4 on
    lastDebounceTime = millis(); // set the current time
  }
  if (currentMillis3 - previousMillis3 &gt; runTime) {
    previousMillis3 = currentMillis3;
    digitalWrite(relay4, HIGH); // turn relay4 off
  }
  // if any valve is open, turn the pump on
  if(relay2State == LOW || relay3State == LOW || relay4State == LOW) {
    digitalWrite(pump, LOW);
  } else {
    digitalWrite(pump, HIGH);
  }
} // close void loop
</code></pre>

<p>Any help would be greatly appreciated. I think I'm stuck in the time buffer for the debounce and my time checks aren't updating right.</p>
 4143: <p>In a program like this it rapidly becomes quite confusing with the variable names all being so similar. Because of this, this is a good candidate for creating a <code>class</code> to do the job for you. This is because you have sets of functionality and variables that are duplicated to do the same job with different settings (IO pins).</p>

<p>It would be a trivial matter to create a <code>class</code> that turns on an output for a specified amount of time:</p>

<pre><code>class TimedOutput {
    private:
        uint8_t _pin;
        uint32_t _started;
        uint32_t _runtime;
        bool _running;

    public:
        TimedOutput(uint8_t pin, uint32_t runtime) {
            _pin = pin;
            _runtime = runtime;
            _started = 0;
            _running = false;
        }


        void begin() {
            pinMode(_pin, OUTPUT);
            digitalWrite(_pin, LOW);
        }

        void start() {
            digitalWrite(_pin, HIGH);
            _running = true;
            _started = millis();
        }

        void run() {
            if (!_running) return;
            if (millis() - _started &gt;= _runtime) {
                digitalWrite(_pin, LOW);
                _running = false;
            }
        }
};

// Create the object
TimedOutput shower(10, 10000); // Output on pin 10 for 10 seconds
TimedOutput sink(11, 3000);    // Output on pin 11 for 3 seconds

void setup() {
    // Configure the pin
    shower.begin();
    sink.begin();
    pinMode(2, INPUT_PULLUP); // Button
    pinMode(3, INPUT_PULLUP); // Button
}

void loop() {
    // Start it if the button is pressed:
    if (digitalRead(2) == LOW) {
        shower.start();
    }

    if (digitalRead(3) == LOW) {
        sink.start();
    }

    // Do the checking for if it needs to stop:
    shower.run();
    sink.run();
}
</code></pre>
