How to trigger Relays

I am using an Arduino Mega 2560 R3 with the relay board linked below. I want to control two of the relays (A&B). I would like to have relay-A activate for 30 seconds, then Both A&B activate for 30 seconds, and finally relay-B activate for 30 seconds. Then this would repeat again. I would like to use pins 18-19. I have only done basic programs for lighting LEDs, adding switches, and turning Pins from low to high. I don't know how to set the pins to activate the relays and set the timers so they have the 30 second overlap were they are both running. I guess I'm gonna have to run 3 separate delay times and digitalWrite both A&B at the same time to have them run with overlap in the middle delay. Any help or points in the right direction would be great.

Thanks
Billy

I don't know how to set the pins to activate the relays

Just like they had LEDs attached.

and set the timers so they have the 30 second overlap were they are both running.

Don't use timers. Use millis() to record when you turn them on, and to see if it is time to turn them off. See the blink without delay example, without delay.

PaulS:

I don't know how to set the pins to activate the relays

Just like they had LEDs attached.

and set the timers so they have the 30 second overlap were they are both running.

Don't use timers. Use millis() to record when you turn them on, and to see if it is time to turn them off. See the blink without delay example, without delay.

I didn't understand your intentions with the use of millis(), but this is what I came up with using delay()
Please remember, I have only been doing this for a few weeks.

// set varibles
int relayPinA = 18;
int relayPinB = 19;
int delayPeriod = 30000

void setup() 
{                
  // initialize the digital pin as an output
  pinMode(relayPinA , OUTPUT);
  pinMode(relayPinB , OUTPUT); 
}

void loop() 
{
//RelayA runs for 30sec, then both RelayA&B runs for 30sec, finally RelayB runs for 30sec, repeat
  digitalWrite(relayPinA , HIGH);   // Turn on relay A
  delay(delayPeriod);                  // wait for 30 second
  digitalWrite(relayPinB , HIGH);   // Turn on relay B
  delay(delayPeriod);                  // wait for 30 second
  digitalWrite(relayPinA , LOW);   // Turn off relay A
  delay(delayPeriod);                  // wait for 30 second
  digitalWrite(relayPinB , LOW);   // Turn off relay B
}

That looks as though it would work. The issue though is that those delays prevent you from doing anything else while the relay controlling is happening. If that's all you need, then it's fine, although it does beg the question around why you are using a Mega rather than a cheaper simpler Arduino.

If this is step one in a larger project though, you're going to want to take PaulS' advice and learn how to do this using millis instead.

int delayPeriod = 30000

You're missing one of these ";" but don't worry, you can have mine.
I'm surprised the compiler didn't point it out to you.

AWOL:

int delayPeriod = 30000

You're missing one of these ";" but don't worry, you can have mine.
I'm surprised the compiler didn't point it out to you.

I'm at work typing this up on notepad. The compiler would of caught it tonight at home. Thanks

wildbill:
That looks as though it would work. The issue though is that those delays prevent you from doing anything else while the relay controlling is happening. If that's all you need, then it's fine, although it does beg the question around why you are using a Mega rather than a cheaper simpler Arduino.

If this is step one in a larger project though, you're going to want to take PaulS' advice and learn how to do this using millis instead.

This is just a small part of a whole. I am wanting to insert this into an existing sketch, so it will need to run in the background while a hundred other things are going on. I have read the reference section on millis() and tried to follow what is happen in BlinkWitoutDelay sketch. I just can't follow along with what is happening in the sketch.

I just can't follow along with what is happening in the sketch.

If you strip out the comments (I suggest you do), the blink without delay sketch boils down to about four useful expressions.
Bear in mind that "loop" will execute many thousands of times a second.

Check this thread - there are a couple of replies that might help: http://arduino.cc/forum/index.php/topic,108263.0.html

It might help you to think of your requirements in simpler terms. Instead of thinking of it as relay A on for 30 then AB on for 30 then B on for 30. I just see two relays running for a minute each with the one starting 30 seconds after the other. Problem is that you can't see them this way until you come to grips with blink without delay.

I just see two relays running for a minute each

...but not using an "int" as a parameter to "delay()"

It might help you to think of your requirements in simpler terms. Instead of thinking of it as relay A on for 30 then AB on for 30 then B on for 30. I just see two relays running for a minute each with the one starting 30 seconds after the other. Problem is that you can't see them this way until you come to grips with blink without delay.

Imagine that you have a 30 second egg timer. You are going to replace the Arduino in the role of turning the relays on or off.

The trigger arrives to tell you to turn the first one on.

So, you turn it on, and flip the egg timer over. You need to stand next to the timer to note exactly when the sand runs out.

When the happens, you flip the second relay on and turn the egg timer over.

You need to stand next to the timer to note exactly when the sand runs out. When the happens, you flip the first relay off, and flip the egg timer over again.

You need to stand next to the timer to note exactly when the sand runs out. When the happens, you flip the second relay off.

Then you stand around and wait for further instructions.

That's the delay paradigm.

Now, for 30 second intervals, it's OK. But suppose the requirement was for 30 minute intervals. Being able to do nothing else for the 90 minutes the relays are on would be a problem, wouldn't it.

Suppose that instead of a 30 minute egg timer, you had a watch and a notepad.

The trigger arrives to turn the first relay on. So, you do that, and you write down when you did that. Then, you get a beer and o watch the ball game. Periodically, you get up and get another beer, and see if it's time to turn the 2nd relay on.

When it is, you do that, and write down when you did that. You can go back to watching the game, and make periodic trips to get rid of the beer. Don't forget to check the time once in a while.

When it is time to turn a relay off, you do that, and scratch out the start time.

THAT is the millis() paradigm. Got to love that approach - more beer!

The millis() function replaces the watch, and a couple of unsigned long variables replace the notepad.

Now, if you read the blink with delay example with this story in mind, does it make more sense?

That is one long way of looking at it but it does make since. Thanks for taking the time to write that all out.
This is my start. I think the code I have will start out with RelayA on then turn RelayB on in 30 seconds? Since it just repeats itself then RelayA stays on and Relay B will turn on/off every 30 seconds. I'm a little confused where to go next. Do I just rewrite the void() another time to turn RelayA off in another 30 seconds then I could repeat it again to turn relayB off in another 30 seconds? Does my time millis = 0 every time the program repeats?

// set constant varibles
const int relayPinA = 18;
const int relayPinB = 19;
const int delayPeriod = 30000;

// set varibles that change
//int relayPinA = HIGH; -not needed
//int relayPinB = LOW; -not needed
int relayStateA = HIGH;
int relalyStateB = LOW;
long previousMillis = 0

void setup() 
{                
  // initialize the digital pin as an output
  pinMode(relayPinA , OUTPUT);
  pinMode(relayPinB , OUTPUT); 
  digitalWrite(relayPinA, relayStateA)
  digitalWrite(relayPinB, relayStateB)
}
void loop()
{
unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > delayPeriod) 
{
    previousMillis = currentMillis;  

  if (relayStateB == LOW)
      relayStateB = HIGH;
    else
      relayStateB = LOW;

     digitalWrite(relayPinB, relayStateB);
 }
}

I think I need to move these two line from the setup to the beginning of the loop? This would start every repeat the same way.

digitalWrite(relayPinA, relayStateA)
digitalWrite(relayPinB, relayStateB)

The way loop() is structured now, it starts by checking to see if it is time to do something.

It shouldn't. It should first check to see if there is something to do. Is there any reason to be diddling with the state of the relay A? There isn't if it isn't on. Is there any reason to be diddling with the state of relay B? There isn't any reason to turn it off if it isn't on, and there isn't any reason to turn it on if relay A isn't on.

Only when you know if there is something to do do you need to be concerned about whether it is time to do it.

The name previousMillis is not a good name. It implies that it is the last time you looked at the clock. But, it says nothing about WHY you care what time it was then. The name currentMillis, on the other hand, is fine.

You should have names like relayAOnTime and relayBOnTime. They imply exactly what happened at some point in time, which is perfect because that is what they are supposed to imply. Be sure to set relayAOnTime back to 0 when relay A is turned off. Be sure to set it when relay A is turned on. Be sure to set relayBOnTime back to 0 when relay B is turned off. Be sure to set it when relay B is turned on. Then, you don't need to be concerned about the state of relay A or relay B. They are on if relayAOnTime or relayBOnTime is not 0, and off if they are 0.

PaulS:
The way loop() is structured now, it starts by checking to see if it is time to do something.

It shouldn't. It should first check to see if there is something to do. Is there any reason to be diddling with the state of the relay A? There isn't if it isn't on. Is there any reason to be diddling with the state of relay B? There isn't any reason to turn it off if it isn't on, and there isn't any reason to turn it on if relay A isn't on.

Only when you know if there is something to do do you need to be concerned about whether it is time to do it.

The name previousMillis is not a good name. It implies that it is the last time you looked at the clock. But, it says nothing about WHY you care what time it was then. The name currentMillis, on the other hand, is fine.

You should have names like relayAOnTime and relayBOnTime. They imply exactly what happened at some point in time, which is perfect because that is what they are supposed to imply. Be sure to set relayAOnTime back to 0 when relay A is turned off. Be sure to set it when relay A is turned on. Be sure to set relayBOnTime back to 0 when relay B is turned off. Be sure to set it when relay B is turned on. Then, you don't need to be concerned about the state of relay A or relay B. They are on if relayAOnTime or relayBOnTime is not 0, and off if they are 0.

Well the two codes below are just trying two different things. I'm sure both are wrong but I had to try. I renamed previuosMillis to pastMillis. Could think of another name to call time that has already happened. I'm not sure I understand how to do the 0 = off and anything other than 0 = on. That whole part was a little confusing. I tried starting the loop() with doing something instead of waiting for something to happen.

// set constant varibles
const int relayPinA = 18;
const int relayPinB = 19;
const int delayPeriod = 30000;

// set varibles that change
int relayAOnTime = HIGH;
int relayBOnTime = LOW;
long pastMillis = 0;

void setup() 
{                
  // initialize the digital pin as an output
  pinMode(relayPinA , OUTPUT);
  pinMode(relayPinB , OUTPUT); 
}
void loop()
{
 digitalWrite(relayPinA, relayAOnTime);
 unsigned long currentMillis = millis();
    if(currentMillis - pastMillis > delayPeriod) 
{
    pastMillis = currentMillis;  

  if (relayBOnTime == LOW)
      relayBOnTime = HIGH;
    else
      relayBOnTime = LOW;

     digitalWrite(relayPinB, relayBOnTime);
 }
unsigned long currentMillis = millis();
    if(currentMillis - pastMillis > delayPeriod) 
{
    pastMillis = currentMillis;  

  if (relayAOnTime == LOW)
      relayAOnTime = HIGH;
    else
      relayAOnTime = LOW;

     digitalWrite(relayPinA, relayAOnTime);
 }
unsigned long currentMillis = millis();
    if(currentMillis - pastMillis > delayPeriod) 
{
    pastMillis = currentMillis;  

  if (relayBOnTime == LOW)
      relayBOnTime = HIGH;
    else
      relayBOnTime = LOW;

     digitalWrite(relayPinB, relayBOnTime);
 }
}
// set constant varibles
const int relayPinA = 18;
const int relayPinB = 19;
const int delayPeriod = 30000;

// set varibles that change
long pastMillis = 0;

void setup() 
{                
  // initialize the digital pin as an output
  pinMode(relayPinA , OUTPUT);
  pinMode(relayPinB , OUTPUT); 
}
void loop()
{
 digitalWrite(relayPinA, HIGH);
 unsigned long currentMillis = millis();
    if(currentMillis - pastMillis > delayPeriod) 
{
    pastMillis = currentMillis;
    digitalWrite(relayPinB, HIGH);
 }
 unsigned long currentMillis = millis();
    if(currentMillis - pastMillis > delayPeriod) 
{
    pastMillis = currentMillis;
    digitalWrite(relayPinA, LOW);
 }
unsigned long currentMillis = millis();
    if(currentMillis - pastMillis > delayPeriod) 
{
    pastMillis = currentMillis;
    digitalWrite(relayPinB, LOW);
}
 digitalWrite(relayPinA, relayAOnTime);

You can't set a pin to some time.

You don't seem to understand that 99.999 % of the time, loop() should accomplish absolutely nothing.

ALL that it should do is some tests to see if there is anything to do. Perhaps read some pins, of the state of a pin matters.

In both of your codes, you are unconditionally diddling with the relay pin. Stop that.

I renamed previuosMillis to pastMillis.

LOL, that is not quite the concession to Paul's recommended naming convention he had in mind.

retrolefty:

I renamed previuosMillis to pastMillis.

LOL, that is not quite the concession to Paul's recommended naming convention he had in mind.

I think I just got that. How about calling it delayMillis, counterMillis, or watchMillis? Your Choice :smiley:

PaulS:

 digitalWrite(relayPinA, relayAOnTime);

You can't set a pin to some time.

You don't seem to understand that 99.999 % of the time, loop() should accomplish absolutely nothing.

ALL that it should do is some tests to see if there is anything to do. Perhaps read some pins, of the state of a pin matters.

In both of your codes, you are unconditionally diddling with the relay pin. Stop that.

LOL, sorry ... So how do i get the pins to turn HIGH/LOW without digitalWrite? I'm still confused about the 0 = off and > than 0 = on?

So how do i get the pins to turn HIGH/LOW without digitalWrite?

to start with, whilst you're learning, you don't ( I.e. just use digitalWrite), but you need to realise that the write is a persistent action; write HIGH and the HIGH state remains until you write a LOW. There is no time element in the wrote.

AWOL:

So how do i get the pins to turn HIGH/LOW without digitalWrite?

to start with, whilst you're learning, you don't ( I.e. just use digitalWrite), but you need to realise that the write is a persistent action; write HIGH and the HIGH state remains until you write a LOW. There is no time element in the wrote.

Then I need to learn another way to turn pins on and off? Any thought on where to look?