Programming relays without delays

Hey guys,

I am trying to create a program where I am able to control the relays on an 4 relay shield board to pulsing one of the GPIO pins, for example, first pulse turns on relay 1, second pulse turns off relay 1, third pulse turns on relay 3. That kind of thing. Problem is that the pulsing of the GPIO pins runs through the program to quickly. There are 22 total steps and without delays it will end up on step 16 after a 10ms pulse! I have tried implementing delays to stop this but the program can sometimes miss the inputs due to these delays. What is a better method of doing this? I have attached my program so any help would be great!

Cheers

I have tried implementing delays to stop this but the program can sometimes miss the inputs due to these delays.

So, don't use delay().
Have a look at the blink without delay example in the IDE.

Please post your code, in code tags.

The StateChangeDetection example is pertinent too I think.

There is a difference between responding to an input being high, and to it going high. The
later requires using a variable to remember the previous state of the input. Remember loop() is
supposed to (and generally does) run thousands to hundreds of thousands of times a second.

The demo Several Things at a Time is an extended example of BWoD and illustrates the use of millis() to manage timing. It may help with understanding the technique.

...R

Hey guys, thanks for all the great advice, I removed the delays and looked into the state detection example which has fixed the issue I was having with the loop being to fast, however, the program still seems to miss a lot of the inputs. I tried changing the length of the pulse that is attached to Arduino GPIO pins to 2 seconds in the hopes the program wouldn't possibly miss it, still seems to though. Is there anything stupid I have done in the code that is preventing anything?

Thanks for all the help, greatly appreciated.

int relay_1 = 4;
int relay_2 = 7;
int relay_3 = 8;
int relay_4 = 12;
int relay_5 = 0;
int relay_6 = 0;
int relay_7 = 0;
int relay_8 = 0;
int relayvar = 0;
int button_State = 0;
int last_Button_State = 0;

  void relay_1_high(){digitalWrite(relay_1,HIGH);}
  void relay_1_low(){digitalWrite(relay_1,LOW);}
  void relay_2_high(){digitalWrite(relay_2,HIGH);}
  void relay_2_low(){digitalWrite(relay_2,LOW);}
  void relay_3_high(){digitalWrite(relay_3,HIGH);}
  void relay_3_low(){digitalWrite(relay_3,LOW);}
  void relay_4_high(){digitalWrite(relay_4,HIGH);}
  void relay_4_low(){digitalWrite(relay_4,LOW);}
  void relay_5_high(){digitalWrite(relay_5,HIGH);}
  void relay_5_low(){digitalWrite(relay_5,LOW);}
  void relay_6_high(){digitalWrite(relay_6,HIGH);}
  void relay_6_low(){digitalWrite(relay_6,LOW);}
  void relay_7_high(){digitalWrite(relay_7,HIGH);}
  void relay_7_low(){digitalWrite(relay_7,LOW);}
  void relay_8_high(){digitalWrite(relay_8,HIGH);}
  void relay_8_low(){digitalWrite(relay_8,LOW);}

void setup() 
{
  // sets the relays pins as outputs
  pinMode(relay_1, OUTPUT);pinMode(relay_2, OUTPUT);   
  pinMode(relay_3, OUTPUT);pinMode(relay_4, OUTPUT);
  pinMode(2, OUTPUT);pinMode(3, INPUT);pinMode(13, OUTPUT);
  digitalWrite(2, HIGH);pinMode(3, LOW);digitalWrite(13, LOW);
  Serial.begin(57600); 
  Serial.print(relayvar);
}
void loop() 
{
  if(digitalRead(3) == HIGH){relayvar = relayvar + 1;}
  else{relayvar = relayvar;}

  button_State = digitalRead(3);
  while(button_State != last_Button_State)
  {
    if(relayvar == 1){relay_1_high();}
    else if(relayvar == 2){relay_1_low();}
    else if(relayvar == 3){relay_2_high();relay_4_high();}
    else if(relayvar == 4){relay_2_low();relay_4_low();}
    else if(relayvar == 5){relay_3_high();relay_4_high();}
    else if(relayvar == 6){relay_3_low();relay_4_low();}
    else if(relayvar == 7){relay_1_high();}
    else if(relayvar == 8){relay_1_low();}
    else if(relayvar == 9){relay_6_high();relay_8_high();}
    else if(relayvar == 10){relay_6_low();relay_8_low();}
    else if(relayvar == 11){relay_6_high();relay_7_high();}
    else if(relayvar == 12){relay_6_low();relay_7_low();}
    else if(relayvar == 13){relay_1_high();}
    else if(relayvar == 14){relay_1_low();}
    else if(relayvar == 15){relay_2_high();}
    else if(relayvar == 16){relay_2_low();}
    else if(relayvar == 17){relay_1_high();}
    else if(relayvar == 18){relay_1_low();}
    else if(relayvar == 19){relay_2_high();}
    else if(relayvar == 20){relay_2_low();}
    else if(relayvar == 21){relay_1_high();}
    else if(relayvar == 22){relay_1_low();}
    else if(relayvar == 23){relayvar = 0;}
    button_State = digitalRead(3);
  }
  last_Button_State = button_State;
}

Please use the AutoFormat tool to lay out your code in a way that is familiar and easy to follow. Putting several things on one line is no benefit to anyone.

Do this

void relay_1_high() {
    digitalWrite(relay_1,HIGH);
}

instead of

void relay_1_high(){digitalWrite(relay_1,HIGH);}

...R

Robin2:
Please use the AutoFormat tool to lay out your code in a way that is familiar and easy to follow. Putting several things on one line is no benefit to anyone.

Find it easier to understand, will make it more convenient in the future

chickwolf:
Find it easier to understand, will make it more convenient in the future

I don't know what to make of that.

And you have not posted the tidied-up version of your program.

...R

// ORNC manikin exhibit relay set one program
int relay_1 = 4;
int relay_2 = 7;
int relay_3 = 8;
int relay_4 = 12;
int relay_5 = 0;
int relay_6 = 0;
int relay_7 = 0;
int relay_8 = 0;
int relayvar = 0;
int button_State = 0;
int last_Button_State = 0;

void relay_1_high() {
  digitalWrite(relay_1, HIGH);
}
void relay_1_low() {
  digitalWrite(relay_1, LOW);
}
void relay_2_high() {
  digitalWrite(relay_2, HIGH);
}
void relay_2_low() {
  digitalWrite(relay_2, LOW);
}
void relay_3_high() {
  digitalWrite(relay_3, HIGH);
}
void relay_3_low() {
  digitalWrite(relay_3, LOW);
}
void relay_4_high() {
  digitalWrite(relay_4, HIGH);
}
void relay_4_low() {
  digitalWrite(relay_4, LOW);
}
void relay_5_high() {
  digitalWrite(relay_5, HIGH);
}
void relay_5_low() {
  digitalWrite(relay_5, LOW);
}
void relay_6_high() {
  digitalWrite(relay_6, HIGH);
}
void relay_6_low() {
  digitalWrite(relay_6, LOW);
}
void relay_7_high() {
  digitalWrite(relay_7, HIGH);
}
void relay_7_low() {
  digitalWrite(relay_7, LOW);
}
void relay_8_high() {
  digitalWrite(relay_8, HIGH);
}
void relay_8_low() {
  digitalWrite(relay_8, LOW);
}

void setup()
{
  // sets the relays pins as outputs
  pinMode(relay_1, OUTPUT); pinMode(relay_2, OUTPUT);
  pinMode(relay_3, OUTPUT); pinMode(relay_4, OUTPUT);
  pinMode(2, OUTPUT); pinMode(3, INPUT); pinMode(13, OUTPUT);
  digitalWrite(2, HIGH); pinMode(3, LOW); digitalWrite(13, LOW);
  Serial.begin(57600);
  Serial.print(relayvar);
}
void loop()
{
  if (digitalRead(3) == HIGH) {
    relayvar = relayvar + 1;
  }
  else {
    relayvar = relayvar;
  }

  button_State = digitalRead(3);
  while (button_State != last_Button_State)
  {
    if (relayvar == 1) {
      relay_1_high();
    }
    else if (relayvar == 2) {
      relay_1_low();
    }
    else if (relayvar == 3) {
      relay_2_high();
      relay_4_high();
    }
    else if (relayvar == 4) {
      relay_2_low();
      relay_4_low();
    }
    else if (relayvar == 5) {
      relay_3_high();
      relay_4_high();
    }
    else if (relayvar == 6) {
      relay_3_low();
      relay_4_low();
    }
    else if (relayvar == 7) {
      relay_1_high();
    }
    else if (relayvar == 8) {
      relay_1_low();
    }
    else if (relayvar == 9) {
      relay_6_high();
      relay_8_high();
    }
    else if (relayvar == 10) {
      relay_6_low();
      relay_8_low();
    }
    else if (relayvar == 11) {
      relay_6_high();
      relay_7_high();
    }
    else if (relayvar == 12) {
      relay_6_low();
      relay_7_low();
    }
    else if (relayvar == 13) {
      relay_1_high();
    }
    else if (relayvar == 14) {
      relay_1_low();
    }
    else if (relayvar == 15) {
      relay_2_high();
    }
    else if (relayvar == 16) {
      relay_2_low();
    }
    else if (relayvar == 17) {
      relay_1_high();
    }
    else if (relayvar == 18) {
      relay_1_low();
    }
    else if (relayvar == 19) {
      relay_2_high();
    }
    else if (relayvar == 20) {
      relay_2_low();
    }
    else if (relayvar == 21) {
      relay_1_high();
    }
    else if (relayvar == 22) {
      relay_1_low();
    }
    else if (relayvar == 23) {
      relayvar = 0;
    }
    button_State = digitalRead(3);
  }
  last_Button_State = button_State;
}

Hopefully you are able to understand it now

What is your program supposed to do? Please explain in detail.

edgemoron:
What is your program supposed to do? Please explain in detail.

Was this not explained in my first post?

Anyway, I am trying to make a sequence of relays turn on and off speakers and lights at different intervals. Something will pulse the Arduino, which will turn on relay one lets say, on the next pulse, it will turn it off, on the third pulse, relay 4 will turn on, etc etc. I actually have two Arduinos running very similar iterations of the code, one for the first four relays and one four the second for, not that this is relevant though.

Hope this clears things up a bit, not looking to provide any confusion.

  if (digitalRead(3) == HIGH) { You need to detect when pin 3 becomes HIGH, not while it is HIGH.

See the state change example in the IDE

AWOL:
See the state change example in the IDE

Thanks for the great advice, went and had a look at the state change example again and changed the bit relevant and it has solved a number of issue I was having! I have linked up a switch to test it however and seem to be suffering from some debouncing effects going on. What could I do to prevent this issue as much as possible?

Thanks for the help everyone!

chickwolf:
What could I do to prevent this issue as much as possible?

You have made changes to the program but you have not posted the new version - and PLEASE DO NOT over-write the earlier version. It is helpful to be able to compare them.

...R

Robin2:
You have made changes to the program but you have not posted the new version - and PLEASE DO NOT over-write the earlier version. It is helpful to be able to compare them.

My apologies for forgetting:

int relay_1 = 4;
int relay_2 = 7;
int relay_3 = 8;
int relay_4 = 12;
int relay_5 = 0;
int relay_6 = 0;
int relay_7 = 0;
int relay_8 = 0;
int relayvar = 0;
int button_State = 0;
int last_Button_State = 0;

void relay_1_high() {
  digitalWrite(relay_1, HIGH);
}
void relay_1_low() {
  digitalWrite(relay_1, LOW);
}
void relay_2_high() {
  digitalWrite(relay_2, HIGH);
}
void relay_2_low() {
  digitalWrite(relay_2, LOW);
}
void relay_3_high() {
  digitalWrite(relay_3, HIGH);
}
void relay_3_low() {
  digitalWrite(relay_3, LOW);
}
void relay_4_high() {
  digitalWrite(relay_4, HIGH);
}
void relay_4_low() {
  digitalWrite(relay_4, LOW);
}
void relay_5_high() {
  digitalWrite(relay_5, HIGH);
}
void relay_5_low() {
  digitalWrite(relay_5, LOW);
}
void relay_6_high() {
  digitalWrite(relay_6, HIGH);
}
void relay_6_low() {
  digitalWrite(relay_6, LOW);
}
void relay_7_high() {
  digitalWrite(relay_7, HIGH);
}
void relay_7_low() {
  digitalWrite(relay_7, LOW);
}
void relay_8_high() {
  digitalWrite(relay_8, HIGH);
}
void relay_8_low() {
  digitalWrite(relay_8, LOW);
}

void setup()
{
  // sets the relays pins as outputs
  pinMode(relay_1, OUTPUT); pinMode(relay_2, OUTPUT);
  pinMode(relay_3, OUTPUT); pinMode(relay_4, OUTPUT);
  pinMode(2, OUTPUT); pinMode(3, INPUT); pinMode(13, OUTPUT);
  digitalWrite(2, HIGH); pinMode(3, LOW); digitalWrite(13, LOW);
  Serial.begin(57600);
  Serial.print(relayvar);
}
void loop()
{
  button_State = digitalRead(3);


  if (button_State != last_Button_State)
  {
    if (button_State == HIGH)
    {
      relayvar = relayvar + 1;
      if (relayvar == 1) {
        relay_1_high();
      }
      else if (relayvar == 2) {
        relay_1_low();
      }
      else if (relayvar == 3) {
        relay_2_high();
        relay_4_high();
      }
      else if (relayvar == 4) {
        relay_2_low();
        relay_4_low();
      }
      else if (relayvar == 5) {
        relay_3_high();
        relay_4_high();
      }
      else if (relayvar == 6) {
        relay_3_low();
        relay_4_low();
      }
      else if (relayvar == 7) {
        relay_1_high();
      }
      else if (relayvar == 8) {
        relay_1_low();
      }
      else if (relayvar == 9) {
        relay_6_high();
        relay_8_high();
      }
      else if (relayvar == 10) {
        relay_6_low();
        relay_8_low();
      }
      else if (relayvar == 11) {
        relay_6_high();
        relay_7_high();
      }
      else if (relayvar == 12) {
        relay_6_low();
        relay_7_low();
      }
      else if (relayvar == 13) {
        relay_1_high();
      }
      else if (relayvar == 14) {
        relay_1_low();
      }
      else if (relayvar == 15) {
        relay_2_high();
      }
      else if (relayvar == 16) {
        relay_2_low();
      }
      else if (relayvar == 17) {
        relay_1_high();
      }
      else if (relayvar == 18) {
        relay_1_low();
      }
      else if (relayvar == 19) {
        relay_2_high();
      }
      else if (relayvar == 20) {
        relay_2_low();
      }
      else if (relayvar == 21) {
        relay_1_high();
      }
      else if (relayvar == 22) {
        relay_1_low();
      }
      else if (relayvar == 23) {
        relayvar = 0;
      }
      button_State = digitalRead(3);
    }
    last_Button_State = button_State;
  }
}
void relay_1_high() {
  digitalWrite(relay_1, HIGH);
}
void relay_1_low() {
  digitalWrite(relay_1, LOW);
}

Remind me what benefits these functions bestow?

AWOL:
Remind me what benefits these functions bestow?

It may not be clear, but the first function, turns on relay 1, and the second function, turns off relay 1. Should really get into the habit of commenting to make things clearer.

What does this do?

pinMode(3, LOW);

This does nothing.

 else {
    relayvar = relayvar;
  }

One side of your pushbutton is connected to pin3, how 'bout the other side?

chickwolf:
It may not be clear, but the first function, turns on relay 1, and the second function, turns off relay 1. Should really get into the habit of commenting to make things clearer.

Yes, I can see what they do (assuming non-inverting logic), but what bbenefit do they bestow? (Apart from bulking-out your line-count, assuming you get paid by the line-of-code)

chickwolf:
seem to be suffering from some debouncing effects going on.

Remove line 159 so you only read the button once.

AWOL:
but what bbenefit do they bestow?

I can see that they might make the action of the code more obvious. But if that is the intention I think I would prefer to call the functions relayOFF() and relayON()

...R