Controlling multiple timed relays off buttons

I'm trying to get an arduino, either a Leonardo or an Uno,
to output 5v to turn on a set of 3 relays from a set of 3 button inputs.
button 1 controls relay 1, etc.
I want each relay to be on concurrently with the other relays depending on button press.
I want the relays to be on for 2 minutes after a button press.
I originally tried the delay function and realized that will not allow other inputs during it.
I'm trying to compile and I'm getting this error exit status 1

Compilation error: expected unqualified-id before 'switch'

I realize now that this code does not allow for timing, do I need to use milli's?

/*

*/
const int Input1 = 2;
const int Input2 = 3;
const int Input3 = 4;
const int Relay1 = 7;
const int Relay2 = 8;
const int Relay3 = 9;
const int LedPin = 13;
int sw1Status, sw2Status, sw3Status, sw4Status;
int order = 1; // default is to set all relays off.
// the relay output
//variable
//int ButtonState1 = 0;
//int ButtonState2 = 0;
//int ButtonState3 = 0;

void setup() {
//Serial.begin(9600);  
pinMode(Input1, INPUT);
pinMode(Input2, INPUT); 
pinMode(Input3, INPUT);

pinMode(Relay1, OUTPUT);
pinMode(Relay2, OUTPUT);
pinMode(Relay3, OUTPUT);
pinMode(LedPin, OUTPUT);
}

void loop() {
  // read the buttons status
  sw1Status = digitalRead(Input1);
  sw2Status = digitalRead(Input2);
  sw3Status = digitalRead(Input3);
  //sw4Status = digitalRead(sw4);

  if (sw1Status == HIGH) { // if button 1 pressed
    order = 2; // go to case 2
  }
  if (sw2Status == HIGH) {
    order = 3;
  }
  if (sw3Status == HIGH) {
    order = 4;
  }
    else { // else go to case 1, which will turns off all relays
    order = 1;
    }
  }

  switch (order) {
    case 1: // if order equals 1
      digitalWrite(Relay1, LOW);
      digitalWrite(Relay2, LOW);
      digitalWrite(Relay3, LOW);
      break;

    case 2: // if order equals 2
      digitalWrite(relay1, HIGH);
      break;

    case 3: // if order equals 3
      digitalWrite(relay2, HIGH);
      break;

    case 4: // if order equals 4
      digitalWrite(relay3, HIGH);
      break;

    default: // if none of above cases is valid go to case 1
      order = 1;
      break;
  }
}

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

The problem with the posted code which causes the error is that you have code outside of any function. Where do you think that the loop() function ends ?

As to doing concurrent timing, yes, you need to use millis()

See Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE

Read How to get the best out of this forum and post your code using code tags </>.

If you properly format your code you will see you have an extra closing bracket before the switch statement. Also, case matters for variables.

I would suggest you look at the following tutorial Example-code for timing based on millis()

I would start with this sketch I already have for StateChangeDetection and ButtonDebounce on multiple buttons:

const byte ButtonCount = 3;
const byte ButtonPins[ButtonCount] = {2, 3, 4};
const unsigned long DebounceTime = 30;

boolean ButtonWasPressed[ButtonCount];  // Defaults to 'false'
unsigned long ButtonStateChangeTime = 0; // Debounce timer common to all buttons

void setup()
{
  Serial.begin(115200);

  for (byte i = 0; i < ButtonCount; i++)
  {
    pinMode (ButtonPins[i], INPUT_PULLUP);  // Button between Pin and Ground
  }
}

void loop()
{
  checkButtons();
}

void checkButtons()
{
  unsigned long currentTime = millis();

  // Update the buttons
  for (byte i = 0; i < ButtonCount; i++)
  {
    boolean buttonIsPressed = digitalRead(ButtonPins[i]) == LOW;  // Active LOW

    // Check for button state change and do debounce
    if (buttonIsPressed != ButtonWasPressed[i] &&
        currentTime - ButtonStateChangeTime > DebounceTime)
    {
      // Button state has changed
      ButtonStateChangeTime = currentTime;
      ButtonWasPressed[i] = buttonIsPressed;
      if (ButtonWasPressed[i])
      {
        // Button i was just pressed
      }
      else
      {
        // Button i was just released
      }
    }
  }
}

Then, since each button has a Relay, I'll put them together into something I'll call a 'Channel':

const byte ChannelCount = 3;
const unsigned long INTERVAL = 2ul * 60ul * 1000ul; // Two Minutes

const byte ButtonPins[ChannelCount] = {2, 3, 4};
const byte RelayPins[ChannelCount] = {7, 8, 9};
const unsigned long DebounceTime = 30;

boolean ButtonWasPressed[ChannelCount];  // Defaults to 'false'
unsigned long ButtonStateChangeTime = 0; // Debounce timer common to all buttons
boolean RelayIsOn[ChannelCount];  // Defaults to 'false'
unsigned long ChannelOnTime[ChannelCount];

void setup()
{
  Serial.begin(115200);

  for (byte i = 0; i < ChannelCount; i++)
  {
    pinMode (ButtonPins[i], INPUT_PULLUP);  // Button between Pin and Ground
    digitalWrite (RelayPins[i], HIGH);  // Relay off.
    pinMode (RelayPins[i], OUTPUT);
  }
}

void loop()
{
  checkButtons();
  checkRelays();
}

void checkButtons()
{
  unsigned long currentTime = millis();

  // Update the buttons
  for (byte i = 0; i < ChannelCount; i++)
  {
    boolean buttonIsPressed = digitalRead(ButtonPins[i]) == LOW;  // Active LOW

    // Check for button state change and do debounce
    if (buttonIsPressed != ButtonWasPressed[i] &&
        currentTime - ButtonStateChangeTime > DebounceTime)
    {
      // Button state has changed
      ButtonStateChangeTime = currentTime;
      ButtonWasPressed[i] = buttonIsPressed;
      if (ButtonWasPressed[i])
      {
        // Button i was just pressed.  Turn on relay.
        digitalWrite(RelayPins[i], LOW);
        RelayIsOn[i] = true;
        ChannelOnTime[i] = millis();
      }
      else
      {
        // Button i was just released
      }
    }
  }
}

// See if it is time to turn any relays off
void checkRelays()
{
  unsigned long currentTime = millis();

  // Update the relays
  for (byte i = 0; i < ChannelCount; i++)
  {
    if (RelayIsOn[i] && currentTime - ChannelOnTime[i] >= INTERVAL)
    {
      // Time to turn the relay off
      digitalWrite(RelayPins[i], HIGH);
      RelayIsOn[i] = false;
    }
  }
}

As everyone else has said get your code together! Read forum guide and edit your post :pencil2: :point_down:<|> :point_up_2:

I would then open a brand new sketch and call it button and work on code to get a button functioning with millis timing and debounce. Do research. Then add a second button to a new sketch called buttons. Then consider using arrays and you have as many buttons as you want in a new sketch called buttons_arrays. Then encapsulate the code in a function.
Open a new sketch called relay and get one relay working, then a new one called relays, then one with arrays called relays_arrays etc, then encapsulate in a function.

Then merge both codes into a new sketch “buttons_relays_arrays” and call your button function in loop to keep an eye on button presses. Then call your relay function in whatever state you need it to function.

Since you have already used millis timing for your button code it is trivial to add an adjustable delay that is non blocking

Always work on a simple block of code. Always save regularly to new sketch with a sensible name. Work iteratively and all bugs will be in the small difference between last save and current sketch.

Also you end up with lots of sensible, encapsulated code that you can reuse

Thanks for the tips, I ended up just using macromatic relay timers instead.

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