Controlling Relays By Day Of The Week & Time

I discovered the Arduino board and this amazing group about three weeks ago. I stumbled upon this quite by accident in search of a solution to a project I am working on. I've learned quite a bit from many users in this group and would like to say THANK YOU!

Phase 1 of my project is pretty basic. I need to control the on and off times of a four relay board by day of the week, as well as the time the relay is turned on and the day and time it is turned off. (details to follow)

I have been searching the forums, YouTube videos, etc. and have learned how to connect and control the individual relays using some of the examples found here, there and everywhere in between.

And now I need some expert advice.

I am using an Arduino UNO with a DS1307 RTC.

I have installed the SparkFun_DS1307_RTC_Arduino_Library-master and am able to set the time and Serial.print the date, time, day of the week, etc., etc. I can control each relay using a modified version of the "blink" program, but that's about the extent of my knowledge so far.

PROJECT OUTLINE
Phase 1 of my project is to activate Relay1 at 6 PM on Monday and turn off at 6 AM on Tuesday. Relay2 will turn on at 6 PM on Tuesday and turn off at 6 AM on Wednesday. Relay3 will turn on at 6 PM on Wednesday and turn off at 6 AM on Thursday. Relay4 will turn on at 6 PM on Thursday and turn off at 6 AM on Friday. The schedule will resume on the following Monday.

1.) No two relays will be on at the same time.
2.) The start time and stop times are the same. (for now)
3.) Only the day of the week and relay number changes. (for now)
4.) If there is a power outage, the program must sense the correct day and time so it will resume power to the correct relay and not wait for the next cycle.

Can someone point me in the right direction, share a link or video that would help me on this project?

Future plans would include a GUI to manually set the date and time as well as set different on/off times and days for the individual relays.

Thanks in advance,

Chuck Hager

Hi Chuck, welcome to the group!
This should be posted in the Projects forum.

Throw away the DS1307 as it is not a great RTC.
Get a DS3231 RTC (~$2.00 eBay) it works same as the 1307 but is much much better hardware.
You can use the 1307 until the 3231 arrives.

Arduino links of interest.

Listing of downloadable 'Arduino PDFs' :
Either Google >>>- - - - > arduino filetype: pdf
Or
https://www.google.ca/search?q=arduino+filetype%3A+pdf&rlz=1C9BKJA_enCA739CA739&oq=arduino+filetype%3A+pdf&aqs=chrome..69i57j69i65.1385j0j7&hl=en-US&sourceid=chrome-mobile&ie=UTF-8

Listing of downloadable 'C++ PDFs' :
Either Google >>>- - - - > C++ filetype: pdf
Or
https://www.google.ca/search?q=c%2B%2B+filetype%3A+pdf&rlz=1C9BKJA_enCA739CA739&oq=c%2B%2B+filetype%3A+pdf&aqs=chrome..69i57.22790j0j7&hl=en-US&sourceid=chrome-mobile&ie=UTF-8

Arduino cheat sheet:

Troubleshooting common errors:

Watch these:
Arduino programming syntax:

Arduino arithmetic operators:

Arduino control flow:

Arduino data types:

Some things to read

https://learn.adafruit.com/category/learn-arduino

https://learn.sparkfun.com/tutorials/how-to-read-a-schematic

Language Reference:

Foundations:

How and Why to avoid delay():
http://playground.arduino.cc/Code/AvoidDelay

Demonstration code for several things at the same time.
http://forum.arduino.cc/index.php?topic=223286.0

Useful links:
https://forum.arduino.cc/index.php?topic=384198.0

Arduino programming traps, tips and style guide:

Jeremy Blume:

Arduino products:

Motors/MOSFETs

Switches:

Share tips you have come across, 500+ posts:
https://forum.arduino.cc/index.php?topic=445951.0

Images from above:
https://www.google.com/search?q=“Share+tips+you+have”+larryD+site:https://forum.arduino.cc&prmd=nmvi&source=lnms&tbm=isch&sa=X&ved=0ahUKEwiJw-zu68ncAhXPGTQIHWCDCNwQ_AUIFCgE&biw=1024&bih=653

Debug discussion:
https://forum.arduino.cc/index.php?topic=215334.msg3823890#new

.

Thank you larryd. I'm looking forward to digesting all the material you provided. Sorry for posting in the wrong group. I'm still trying to figure my way around this forum.

DS3231 RTC is now on the way!

Thread moved as requested.

chuckhager:
PROJECT OUTLINE
Phase 1 of my project is to activate Relay1 at 6 PM on Monday and turn off at 6 AM on Tuesday. Relay2 will turn on at 6 PM on Tuesday and turn off at 6 AM on Wednesday. Relay3 will turn on at 6 PM on Wednesday and turn off at 6 AM on Thursday. Relay4 will turn on at 6 PM on Thursday and turn off at 6 AM on Friday. The schedule will resume on the following Monday.

1.) No two relays will be on at the same time.
2.) The start time and stop times are the same. (for now)
3.) Only the day of the week and relay number changes. (for now)
4.) If there is a power outage, the program must sense the correct day and time so it will resume power to the correct relay and not wait for the next cycle.

Can someone point me in the right direction, share a link or video that would help me on this project?

Your library numbers the days of the week thus: 1 for Sunday, 2 for Monday, and so forth, up to 7 for Saturday. In terms of these numbers, Relay1 should be on from day 2 18:00 to day 3 06:00. You can work out the day numbers and hours for the other relays. Once you've done that, you can work out a way to determine, given a day number and an hour number, which (if any) of the relays should be on at that particular day and hour. This will be at the heart of your project.

Once you have grasped the basics and your project is working, I have a suggestion for "Phase 2" of the project. Your GUI could be a simple web page you can access from laptop or smartphone over your home WiFi. Potentially from anywhere in the world, although that's a little more difficult. No need for an RTC, the Arduino can get the time over the internet from a Network Time Server. Just an idea for the future, once you have achieved a level of confidence and experience. The hardware required is very inexpensive, such as a Wemos Mini, which are only around £5.

If you work in 6-hour intervals you could use 28 binary flags per week:

uint32_t RelaySchedules[7] = {
0b0001100000000000000000000000UL, //  Relay 0:  Sunday 6PM through Monday 6AM
0b0000000110000000000000000000UL, //  Relay 1:  Monday 6PM through Tuesday 6AM
0b0000000000011000000000000000UL, //  Relay 2:  Tuesday 6PM through Wednesday 6AM
0b0000000000000001100000000000UL, //  Relay 3:  Wednesday 6PM through Thursday 6AM
0b0000000000000000000110000000UL, //  Relay 4:  Thursday 6PM through Friday 6AM
0b0000000000000000000000011000UL, //  Relay 5:  Friday 6PM through Saturday 6AM
0b1000000000000000000000000001UL  //  Relay 6:  Saturday 6PM through Sunday 6AM
};

Then each time through loop() you get the current time, calculate which part of the week you are in, and go through the table to see if each relay should be set ON or OFF. Each relay can be set ON or OFF for any combination of the 28 time intervals in the week. You can add as many relays as you have pins for (over 50 on an Arduino MEGA). If power is lost the relays will be updated the first time through loop().

If you decide you need 1-hour resolution you could expand this to 21 bytes per relay, each byte representing the hours of an 8-hour interval.

Thank you JohnWasser. This helps a lot!

A simple state machine sketch looking at the day of the week and time of day sould work too.

I've been going through all the links you posted above larryd. Lot's of good stuff. So far I've learned, that I have a lot to learn! :slight_smile:

Seems like coding is a lot like speech. There are many ways to say the same thing.

I seem to learn a lot by studying the sketch from others. Can anyone provide a link with examples that I can look at? I have the relay on/off control handled. I just need the day of week and start stop time with the recovery after power failure examples. THANKS!

chuckhager:
Seems like coding is a lot like speech. There are many ways to say the same thing.

Yes, exactly!!

I know from experience that it is very easy to be indecisive about exactly the right way to phrase something.

chuckhager:
I've been going through all the links you posted above larryd. Lot's of good stuff. So far I've learned, that I have a lot to learn! :slight_smile:

Seems like coding is a lot like speech. There are many ways to say the same thing.

I seem to learn a lot by studying the sketch from others. Can anyone provide a link with examples that I can look at? I have the relay on/off control handled. I just need the day of week and start stop time with the recovery after power failure examples. THANKS!

Study this, come back with your questions:
https://playground.arduino.cc/code/time

Thank you larryd. Help is always appreciated. Correct me if I am wrong, but the examples in the link looks very similar to what I am currently using.

Here is a simple sketch that I am using to learn from that gets the current time from the RTC and prints it to the serial monitor. (NOTE: I have a separate sketch that I used to set the time on the RTC that is not being shown here.)

#include <SparkFunDS1307RTC.h>
#include <Wire.h>

void setup()
{
Serial.begin(9600); // Set the baud rate to use the serial monitor to view time/date output
rtc.begin(); // Call rtc.begin() to initialize the library
}

void loop()
{
rtc.update();

Serial.print(String(rtc.hour()) + ":"); // Print hour

if (rtc.minute() < 10)
Serial.print('0'); // Print leading '0' for minute
Serial.print(String(rtc.minute()) + ":"); // Print minute

if (rtc.second() < 10)
Serial.print('0'); // Print leading '0' for second
Serial.print(String(rtc.second())); // Print second

Serial.print(" - ");

// Few options for printing the day, pick one:
Serial.print(rtc.dayStr()); // Print day string
//Serial.print(rtc.dayC()); // Print day character
//Serial.print(rtc.day()); // Print day integer (1-7, Sun-Sat)

Serial.print(" - ");

Serial.print(String(rtc.month()) + "/" + // Print month
String(rtc.date()) + "/"); // Print date
Serial.println(String(rtc.year())); // Print year
delay(1000);
}

Personally, I only need the day of the week, the hour of the day, (in 24 hour time), and the minute.

I think my logic would be something like this...,

1.) Poll the clock and get the current time, day of the week and the date.
2.) If the time is between 6PM on Sunday and 6AM on Monday, then Relay1 should be on.
3.) If the time is between 6PM on Monday and 6AM on Tuesday, then Relay2 should be on.
4.) If the time is between 6PM on Tuesday and 6AM on Wednesday, then Relay3 should be on.
5.) etc., etc., etc.

I also think this logic would make sure the correct relay was on after recovering from a power outage.

Am I at least on the right track???

An example of how to do things based on TimeAlarms library

//You need these libraries:
#include <Time.h>  
//https://github.com/PaulStoffregen/Time

#include <DS1307RTC.h>     //RTC DS1307 library that returns time as a time_t

#include <Wire.h>          //Needed for IIC (I2C) comunications

#include <TimeAlarms.h>    //Changed Number of  alarms dtNBR_ALARMS to 30 
//https://github.com/PaulStoffregen/TimeAlarms


. . . 
  
//**********************  
//Day of Week Alarms
Alarm.alarmRepeat(dowMonday,18,0,0, MondayPMaction);    //6PM Monday
Alarm.alarmRepeat(dowTuesday,6,0,0, TuesdayAMaction);   //6AM Tuesday
Alarm.alarmRepeat(dowTuesday,18,0,0,TuesdayAMaction);  //6PM Tuesday
Alarm.alarmRepeat(dowWednesday,6,0,0, WednesdayAMaction);   //6AM Wednesday

etc.

. . .

//*************************
void MondayPMaction()
{
  digitalWrite(Relay1, HIGH);  //this relay ON
}

//*************************
void TuesdayAMaction()
{
  digitalWrite(Relay1, LOW);  //this relay OFF
}

//*************************
void TuesdayPMaction()
{
  digitalWrite(Relay2, HIGH); //this relay ON
}

//*************************
void WednesdayAMaction()
{
  digitalWrite(Relay2, LOW); //this relay OFF
}

etc.

This is also a good read:

The problem with larryd's suggested code above is that it won't set the relays correctly after a power outage, because an on-time event may have been missed during the outage.

This could be fixed with extra code that works as the OP described in the previous post, but that makes the alarm events redundant, I think.

PaulRB:
The problem with larryd's suggested code above is that it won't set the relays correctly after a power outage, because an on-time event may have been missed during the outage.

This could be fixed with extra code that works as the OP described in the previous post, but that makes the alarm events redundant, I think.

Could also write the relay states to EEPROM to recover from power fails.
This way user written relay changes could also be handled if that was include later in the project.

larryd:
Could also write the relay states to EEPROM to recover from power fails.

But that won't fix the problem. The problem comes when there is no power at the scheduled on-time. So the relay won't be switched and the EEPROM won't be updated.

That’s true.

Living in an area where there are no/few power fails, one becomes oblivious. :wink:

A state machine, where the current state is placed in EEPROM, would work.
The machine state is changed by an alarm event time, the new state operates on the appropriate relay over and over until a new state occurs.
Edit:
No, this won’t work either :frowning:

chuckhager:
Personally, I only need the day of the week, the hour of the day, (in 24 hour time), and the minute.

I think my logic would be something like this...,

1.) Poll the clock and get the current time, day of the week and the date.
2.) If the time is between 6PM on Sunday and 6AM on Monday, then Relay1 should be on.
3.) If the time is between 6PM on Monday and 6AM on Tuesday, then Relay2 should be on.
4.) If the time is between 6PM on Tuesday and 6AM on Wednesday, then Relay3 should be on.
5.) etc., etc., etc.

I also think this logic would make sure the correct relay was on after recovering from a power outage.

Am I at least on the right track???

Yes. That will work. It might be tricky when the interval starts at the end of one week and ends at the beginning of the next week.

const unsigned int SUNDAY = 1;
const unsigned int MONDAY = 2;
const unsigned int TUESDAY = 3;
const unsigned int WEDNESDAY = 4;
const unsigned int THURSDAY = 5;
const unsigned int FRIDAY = 6;
const unsigned int SATURDAY = 7;

unsigned int weektime(unsigned int day, unsigned int hour)
{
  return day * 24 + hour;
}

void loop()
{
  // 1.) Poll the clock and get the current time, day of the week and the date.
  rtc.update();

  unsigned int hourOfTheWeek = weektime(rtc.day(), rtc.hour());

  // 2.) If the time is between 6PM on Sunday and 6AM on Monday, then Relay1 should be on.
  digitalWrite(Relay1Pin, hourOfTheWeek >= weektime(SUNDAY, 18) && hourOfTheWeek < weektime(MONDAY, 6) );


  // 3.) If the time is between 6PM on Monday and 6AM on Tuesday, then Relay2 should be on.
  digitalWrite(Relay2Pin, hourOfTheWeek >= weektime(MONDAY, 18) && hourOfTheWeek < weektime(TUESDAY, 6) );

  // 4.) If the time is between 6PM on Tuesday and 6AM on Wednesday, then Relay3 should be on.
  digitalWrite(Relay3Pin, hourOfTheWeek >= weektime(TUESDAY, 18) && hourOfTheWeek < weektime(WEDNESDAY, 6) );

  // Relay 7 crosses the week boundary! Saturday (day 7) 6PM to Sunday (day 1) 6 AM
  // NOTE the use of '||' (OR) instead of '&&' (AND).
  digitalWrite(Relay7Pin, hourOfTheWeek >= weektime(SATURDAY, 18) || hourOfTheWeek < weektime(SUNDAY, 6) );
}

If you need more resolution, just add Minutes to weektime().

Thank you John Wasser!!! I was able to get things worked out using your example. :smiley: It's up and running!

Someday, I'll add an Ethernet port and see if I can put together a GUI for setting the relays to operate on different days and times.

I really appreciate everyone who contributed their knowledge AND their time, to help me get this up and running, as I continue to learn the language of Arduino!!