Timer circuit with three relays and 8hours interval operation

I very recently have started tinkering around and am unaware of most of the technicalities,
I have three 5v relays which I want to operate in 8 hours interval daily which means any two out of the three would be active at any point of time in a day. For clear understanding; naming relays as Relay1, Relay2 and Relay3;

now, beginning at 00:00:00 Relay1 and Relay2 should be HIGH for eight hours i.e. till 08:00:00 and Relay3 should be LOW

then from 08:00:00 to 16:00:00 Relay2 and Relay3 should be HIGH and Relay1 should be LOW and

then from 16:00:00 to 24:00:00 Relay3 and Relay1 should be HIGH and Relay2 should be LOW and so on for about 999 Days.

I had written a code but I'm unable to retrieve the required output, I figure it might be the Delay function and I should refer the Blink without Delay but I'm unable to get it. Could you please help.

Here's the CODE :+1:

const int R1 =9;
const int R2 = 10;
const int R3 = 11;

void setup() {
pinMode (R1, OUTPUT);
pinMode (R2, OUTPUT);
pinMode (R3, OUTPUT);

}

void loop() {

rel1();
rel2();
rel3();
}

void rel1(){
digitalWrite(R1, HIGH);
const unsigned long eigth = 8UL36001000;
const unsigned int numOfDays = 999;
int i;
int j;
for( i=0; i<numOfDays; i++ )
{
delay(eigth);
}
digitalWrite(R1, LOW);
for( i=0; i<numOfDays; i++ )
{
delay(eigth);
}
}

void rel2() {
digitalWrite(R2, LOW);
const unsigned long eigth = 8UL36001000;
const unsigned int numOfDays = 999;
int i;
int j;
for( i=0; i<numOfDays; i++ )
{
delay(eigth);
}
digitalWrite(R2, HIGH);
for( i=0; i<numOfDays; i++ )
{
delay(eigth);
}
}

void rel3() {
digitalWrite(R3, HIGH);
const unsigned long eigth = 8UL36001000;
const unsigned int numOfDays = 999;
int i;
int j;
for( i=0; i<numOfDays; i++ )
{
delay(eigth);
}
digitalWrite(R3, LOW);
for( i=0; i<numOfDays; i++ )
{
delay(eigth);
}
}

Please follow the advise in the first topic telling how to get the best from this forum. Posting code... use autoformat in the IDE and the use code tags when posting here.

Please post the wiring diagram, not a wall paint Fritzing.

Power issues are way too common, therefore the request for wiring.

In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the </> icon from the ‘reply menu’ to attach the copied sketch.

You’re certainly on the right track.
Rewriting without delay() would be a great start.

Also, you will probably better off using some form of RTC (Real Time Clock) to keep track of time.

2 Likes

Thank you for your support, I did guess I'll require a RTC, DS1307 should work just fine I suppose. My only issue is How do I write the code, I'm unable to understand and clearly not with a coding background.
Could you please help me with the code.

Lots of volunteers will help, but you need to put effort into learning.

An RTC (ex: DS3231) is something that is needed for accurate time of day operations.

Here is a skeleton sketch I often use when a new sketch is started.

It does not use an RTC, it just uses the millis() technique BWD for timing.


//*************************************^****************************************
//  FileName.ino
//  LarryD
//  Version   YY/MM/DD     Comments
//  1.00      20/01/01     Running code
//
//
//*************************************^****************************************
 
 
//                                M A C R O S
//*************************************^****************************************
//                                         Resistor    LED
#define LEDon       HIGH           //pin----[220R]-----[>|]----GND
#define LEDoff      LOW
 
#define noCHANGE    -1             //there was no change in switch state

#define isPUSHED    LOW            //   ~50k                 normally open
#define isRELEASED  HIGH           //INPUT_PULLUP-----pin----[N.O. switch]----GND
 
#define enable      true
#define disable     false
 
//*************************************^****************************************
//                       C l a s s   m a k e T i m e r
//*************************************^****************************************
//
class makeTimer
{
#define MILLIS true
#define MICROS false
 
    //Note: since code takes time to execute, precise micro second timing is difficult.
 
    //StartTime  = the time this "TIMER" was (re)started
    //Interval   = Interval/delay time we are looking for
    //Restart    = do we start "this TIMER" again and again
    //EnableFlag = is "this TIMER" enabled/allowed to be accessed
    //TimerType  = true/MILLIS = millis(), false/MICROS = micros()
    //****************************
    //For each TIMER object you need:
    //Example:
    //   makeTimer myTimer = //create a Timer named "myTimer"
    //   {
    //     0, 200UL, true, true, MILLIS  //StartTime, Interval, Restart, EnableFlag, TimerType (MILLIS/MICROS)
    //   };
    //
    //Each TIMER object is made up of 5 variables:
    //myTimer.StartTime, myTimer.Interval, myTimer.Restart, myTimer.EnableFlag and myTimer.TimerType
    //
    //You have the following class functions:
    //myTimer.CheckTime() and  myTimer.EnableTimer()  and  myTimer.DisableTimer()
    //****************************
 
  public:
    unsigned long StartTime;
    unsigned long Interval;
    bool          Restart;
    bool          EnableFlag;
    bool          TimerType;
 
    unsigned long currentTime;
 
    //                            m a k e t i m e r ( )
    //*************************************^****************************************
    //Constructor
    //
    makeTimer(unsigned long ST, unsigned long INT, bool RES, bool ENA, bool TT)
    {
      StartTime  = ST;
      Interval   = INT;
      Restart    = RES;
      EnableFlag = ENA;
      TimerType  = TT;
 
    } //END of makeTimer()
 
    //                           C h e c k T i m e r ( )
    //*************************************^****************************************
    //Delay time expired function "CheckTime()"
    //
    bool CheckTime()
    {
      //StartTime  = the time TIMER was (re)started
      //Interval   = interval/delay we are looking for
      //Restart    = do we restart TIMER automatically
      //EnableFlag = is TIMER enabled/allowed to be accessed
      //TimerType  = use ms or us timing, MILLIS/true = millis(), MICROS/false = micros()
 
      if (TimerType == MILLIS)
      {
        //using millis() for this TIMER
        currentTime = millis();
      }
 
      else
      {
        //using micros() for this TIMER
        currentTime = micros();
      }
 
      //is the TIMER enabled and has the TIMER expired?
      if (EnableFlag == true && currentTime - StartTime >= Interval)
        //Note: if delays of < 2ms are needed use micros() and adjust 'Interval' as needed
      {
        //should we restart the TIMER automatically?
        if (Restart)
        {
          //Restart the TIMER
          StartTime = currentTime;
          //optionally
          //StartTime = StartTime + Interval;
        }
 
        //this TIMER did expired
        return true;
 
      } //END of   if(EnableFlag == true && currentTime - StartTime >= Interval)
 
      //this TIMER did not expire or it is disabled
      return false;
 
    } //END of  CheckTime()
 
    //                          E n a b l e T i m e r ( )
    //*************************************^****************************************
    //Function to enable and initialize a TIMER, ex: myTimer.EnableTimer();
    //
    void EnableTimer()
    {
      EnableFlag = true;
 
      //initialize lastTime to current millis() or micros()
      if (TimerType == true)
      {
        StartTime = millis();
      }
 
      else
      {
        StartTime = micros();
      }
 
    } //END of  EnableTimer()
 
    //                         D i s a b l e T i m e r ( )
    //*************************************^****************************************
    //Function to disable a TIMER, ex: myTimer.DisableTimer();
    //
    void DisableTimer()
    {
      EnableFlag = false;
 
    } //END of  DisableTimer()
 
}; //END of  class makeTimer
 
 
//*************************************^****************************************
//                         Instantiate TIMER objects
//*************************************^****************************************
makeTimer heartbeatLED =         //create a millisecond TIMER 'heartbeatLED'
{
  0, 200UL, true, true, MILLIS   //StartTime, Interval, Restart, EnableFlag, TimerType (MILLIS/MICROS)
};
 
//*************
makeTimer checkMySwitches =      //create a millisecond TIMER 'checkMySwitches'
{
  0, 20UL, true, true, MILLIS    //StartTime, Interval, Restart, EnableFlag, TimerType (MILLIS/MICROS)
};
 
 
//*************************************^****************************************
//                    C l a s s   d e f i n e S w i t c h
//*************************************^****************************************
//
class defineSwitch
{
  public:
    byte          pin;           //physical pin being used for this switch
    byte          closedLevel;   //pin level when the switch is closed
   
    unsigned long switchMillis;  //how long the switch was held closed
    byte          lastState;     //last state the switch was in
 
 
    //                          d e f i n e S w i t c h ( )
    //*************************************^****************************************
    //Constructor
    //
    defineSwitch(byte _pin, byte _closedLevel)
    {
      pin          = _pin;
      closedLevel  = _closedLevel;
     
      //how long the switch was closed
      switchMillis = 0;
 
      //the level of the switch when released
      lastState    = 1 - closedLevel;
 
      pinMode(pin, INPUT_PULLUP);
 
    } //END of  defineSwitch()
 
    //                         C h a n g e I n S t a t e ( )
    //*************************************^****************************************
    //check to see if there is a change in switch state
    //
    char ChangeInState()
    {
      byte currentState = digitalRead(pin);
 
      if (lastState != currentState)
      {
        //update to the new state
        lastState = currentState;
 
        if (currentState == closedLevel)
        {
          //the time the switch was closed
          switchMillis = millis();
 
          //the switch was closed/pushed
          return closedLevel;
        }
 
        else
        {
          //calculate the time the switch was closed
          switchMillis = millis() - switchMillis;
 
          //then switch was opened/released
          return 1 - closedLevel;
        }
 
      } //END of  if (lastState != currentState)
 
      //there was no change in switch state
      return -1;
 
    } //END of ChangeInState()
 
    //                             P i n S t a t e ( )
    //*************************************^****************************************
    //check to see if there is a change in switch state
    //
    byte PinState()
    {
      byte state = digitalRead(pin);
 
      return state;
     
    } //END of  PinState()
 
}; //END of  class defineSwitch
 
 
//*************************************^****************************************
//                         Instantiate switch objects
//*************************************^****************************************
//                                ~50k                  normally open
//switch are wired as such     INPUT_PULLUP-----pin-----[N.O. switch]----GND
//
//                       pin#, closed level
defineSwitch SWITCH1     = {2, isPUSHED};
defineSwitch SWITCH2     = {3, isPUSHED};
 
 
//*************************************^****************************************
//                       G l o b a l   v a r i a b l e s
//*************************************^****************************************
 
// I N P U T S
 
 
// O U T P U T S
const byte PIN_13        = 13;
const byte PIN_12        = 12;
const byte PIN_11        = 11;
 
// S R A M
 
int counter;
 
 
//                                s e t u p ( )
//*************************************^****************************************
//
void setup()
{
  Serial.begin(9600);
 
  //***************************
  pinMode(PIN_13, OUTPUT);
  pinMode(PIN_12, OUTPUT);
  pinMode(PIN_11, OUTPUT);
 
} //END of  setup()
 
 
//                                l o o p ( )
//*************************************^****************************************
//
void loop()
{
  //****************************
  //is it time to toggle the heartbeat LED
  if (heartbeatLED.CheckTime())
  {
    //Toggle heartbeatLED
    //digitalWrite(heartLED, !digitalRead(heartLED)); //generic
    PINB = 0x20; // Toggles pin D13 UNO
 
    //Toggle pins specific to UNO
    //PINB=0x20; //13 PINB=0x10; //12  PINB=0x08; //11  PINB=0x04; //10  PINB=0x02; //9  PINB=0x01; //8
    //PIND=0x80; //7  PIND=0x40; //6   PIND=0x20; //5   PIND=0x10; //4   PIND=0x08; //3  PIND=0x04; //2
 
    //if you only want this section of code to happen once
    //uncomment the next line
    //heartbeatLED.DisableTimer();
 
  } //END of   if(heartbeatLED.CheckTime())
 
  //****************************
  //is it time to check the switches ?
  if (checkMySwitches.CheckTime())
  {
    checkSwiches();
 
  } //END of   if(checkMySwitches.CheckTime())
 
 
  //****************************
  //None blocking code goes here
  //****************************
 
} //END of  loop()
 
 
//                         c h e c k S w i t c h e s ( )
//*************************************^****************************************
//
void checkSwiches()
{
  //******************************************************        SWITCH1
  //3 possibilities: noCHANGE, isPUSHED or isRELEASED
  switch (SWITCH1.ChangeInState())
  {
    //******************
    case noCHANGE:
      //do nothing
 
      break;
 
    //******************
    case isPUSHED:
      //digitalWrite(12, !digitalRead(12)); //generic
      PINB = 0x10;  //Toggles pin D12,  specific to UNO
 
      counter++;
      Serial.println(counter);
 
      break;
 
    //******************
    case isRELEASED:
      //how long was the switch pushed for ?
      Serial.print("SWITCH1 was pressed for: ");
      Serial.println(SWITCH1.switchMillis);
 
      break;
 
  } //END of  switch/case
 
  //******************************************************        SWITCH2
  //3 possibilities: noCHANGE, isPUSHED or isRELEASED
  switch (SWITCH2.ChangeInState())
  {
    //******************
    case noCHANGE:
      //do nothing
 
      break;
 
    //******************
    case isPUSHED:
      //digitalWrite(11, !digitalRead(11)); //generic
      PINB = 0x08;  //Toggles pin D11,  specific to UNO
 
      counter--;
      if (counter < 0)
      {
        counter = 0;
      }
 
      Serial.println(counter);
 
      break;
 
    //******************
    case isRELEASED:
      //how long was the switch pushed for ?
      Serial.print("SWITCH2 was pressed for: ");
      Serial.println(SWITCH2.switchMillis);
 
      break;
 
  } //END of  switch/case
 
  //******************************************************        Other switches
 
} //END of checkSwitches()
 
 
 
//*************************************^****************************************
//                            E N D  O F  C O D E
//*************************************^****************************************

1 Like

@shivansh_trivedi, there are many options.
You can start by using millis() and if that works, then upgrade to a DS3231.
For a millis-timer, you can use the millis() function directly. That is what I do.
Or you can use the code by LarryD, or a library such as LC_basetools. There are also a few tutorials. Choose what you feel the most comfortable with.

You need a single millis-timer of 8 hours, and rotate the relays every 8 hours within the millis-timer. That is not so hard, only the starting point needs some extra care.
Read the Blink Without Delay page as an introduction to a millis-timer.

When you use a RTC, such as the DS1307 or the DS3231, then it is obvious what to do in my opinion: You can use the TimeLib and add the TimeAlarms library to that.

1 Like

Your sketch layout of

void loop() {
rel1();
rel2();
rel3();
}

Just replace the delays in the methods with millis or millisDelay, see
How to write Timers and Delays in Arduino
and
Multi-tasking in Arduino
Remember for long delays to use ul (unsigned long)
as in
eightHrsDelayMs = 8ul * 60601000;
multitaskingDiagramSmall

1 Like

I have reworked the code along with RTC DS3231 as suggested by all the highly knowledgeable members here; I wish if you could please verify it and suggest me some changes if necessary.


#include <RTClib.h>
#include <Wire.h>
RTC_DS3231 RTC;

//-----------------------//
//------Variables--------//
//-----------------------//


//------First Timer 
byte onhour1=16;
byte onmin1=00;
byte onsec1=00;

byte offhour1=8;
byte offmin1=00;
byte offsec1=00;
//-----Second Timer              //hour= 0-23
byte onhour2=23;
byte onmin2=59;                   //minutes,seconds= 0-59
byte onsec2=59;

byte offhour2=16;
byte offmin2=00;
byte offsec2=00;
//-----Third Timer
byte onhour3=8;
byte onmin3=00;
byte onsec3=00;

byte offhour3=23;
byte offmin3=59;
byte offsec3=59;


//-------To convert clock into single number
unsigned long Time;
unsigned long Hour;
unsigned long Min;
unsigned long Sec;
//------To convert first timer into Single number
unsigned long on_Time1;
unsigned long on_hour1;
unsigned long on_min1;
unsigned long on_sec1;

unsigned long off_Time1;
unsigned long off_hour1;
unsigned long off_min1;
unsigned long off_sec1;
//------To convert second timer into Single number
unsigned long on_Time2;
unsigned long on_hour2;
unsigned long on_min2;
unsigned long on_sec2;

unsigned long off_Time2;
unsigned long off_hour2;
unsigned long off_min2;
unsigned long off_sec2;
//------To convert Third timer into Single number
unsigned long on_Time3;
unsigned long on_hour3;
unsigned long on_min3;
unsigned long on_sec3;

unsigned long off_Time3;
unsigned long off_hour3;
unsigned long off_min3;
unsigned long off_sec3;


//-------Pins
byte Relay1 =9;//Relay1 to pin 9
byte Relay2 =10; //Relay2 to pin 10
byte Relay3 =11; //Relay3 to pin 11
//------Relay States
boolean Relay1State;

boolean Relay2State;

boolean Relay3State;



void setup() { 
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
  pinMode(Relay3, OUTPUT);
     
     Wire.begin();
     RTC.begin();

}

void loop() {
    
DateTime now = RTC.now();        // Clock call
now = RTC.now();


//-------------Conversion----------//

//---------Converting clock time into single number 
 
Hour = now.hour();
Min = now.minute();
Sec = now.second();
Time = (Hour*10000+ Min*100 +Sec*1);  

//--------Converting firt timer on/off into single number
on_hour1=onhour1;
on_min1=onmin1;
on_sec1=onsec1;
on_Time1=(on_hour1*10000 + on_min1*100 + on_sec1);

off_hour1=offhour1;
off_min1=offmin1;
off_sec1=offsec1;
off_Time1=(off_hour1*10000 + off_min1*100 + off_sec1);
//--------Converting second timer on/off into single number
on_hour2=onhour2;
on_min2=onmin2;
on_sec2=onsec2;
on_Time2=(on_hour2*10000 + on_min2*100 + on_sec2);

off_hour2=offhour2;
off_min2=offmin2;
off_sec2=offsec2;
off_Time2=(off_hour2*10000 + off_min2*100 + off_sec2);
//--------Converting third timer on/off into single number
on_hour3=onhour3;
on_min3=onmin3;
on_sec3=onsec3;
on_Time3=(on_hour3*10000 + on_min3*100 + on_sec3);

off_hour3=offhour3;
off_min3=offmin3;
off_sec3=offsec3;
off_Time3=(off_hour3*10000 + off_min3*100 + off_sec3);   



//----RelayState Function----//
if(onhour1 == offhour1 && onmin1==offmin1 && onsec1==offsec1){
   Relay1State=LOW;
}

if(on_Time1 < off_Time1){
  
             if(Time >= on_Time1 && Time < off_Time1){  //Start
             Relay1State= HIGH;
             }
             else if(Time >= off_Time1) {
             Relay1State= LOW;
             }
             else{
             Relay1State= LOW;
             }
}
if (on_Time1 > off_Time1){

            if(Time >= on_Time1 && Time <= 235959){     //Start
            Relay1State= HIGH;  
            }
            else if(Time < off_Time1 ){
            Relay1State= HIGH;
            }
            else if(Time >= off_Time1 && Time < on_Time1){
            Relay1State= LOW;  
            }
}
//----RelayState2 Function----//
if(onhour2 == offhour2 && onmin2==offmin2 && onsec2==offsec2){
   Relay2State=LOW;
}

if(on_Time2 < off_Time2){
  
             if(Time >= on_Time2 && Time < off_Time2){  //Start
             Relay2State= HIGH;
             }
             else if(Time >= off_Time2) {
             Relay2State= LOW;
             }
             else{
             Relay2State= LOW;
             }
}
if (on_Time2 > off_Time2){

            if(Time >= on_Time2 && Time <= 235959){     //Start
            Relay2State= HIGH;  
            }
            else if(Time < off_Time2 ){
            Relay2State= HIGH;
            }
            else if(Time >= off_Time2 && Time < on_Time2){
            Relay2State= LOW;  
            }
}
//----RelayState3 Function----//
if(onhour3 == offhour3 && onmin3==offmin3 && onsec3==offsec3){
   Relay3State=LOW;
}

if(on_Time3 < off_Time3){
  
             if(Time >= on_Time3 && Time < off_Time3){  //Start
             Relay3State= HIGH;
             }
             else if(Time >= off_Time3) {
             Relay3State= LOW;
             }
             else{
             Relay3State= LOW;
             }
}
if (on_Time3 > off_Time3){

            if(Time >= on_Time3 && Time <= 235959){     //Start
            Relay3State= HIGH;  
            }
            else if(Time < off_Time3 ){
            Relay3State= HIGH;
            }
            else if(Time >= off_Time3 && Time < on_Time3){
            Relay3State= LOW;  
            }
}


//-------Relay function
if(Relay1State ==HIGH){
  digitalWrite(Relay1,HIGH);
}  
else{
  digitalWrite(Relay1,LOW);
}
if(Relay2State ==HIGH){
  digitalWrite(Relay2,HIGH);
}
else{
  digitalWrite(Relay2,LOW);
}
if(Relay3State ==HIGH){
  digitalWrite(Relay3, HIGH);
}
else{
  digitalWrite(Relay3,LOW);
}

}

Let’s assume Hour = 23. (11PM)

When you multiply Hour by 10000, what do you get ?

Well ,if its 11p.m. i.e. 23:00:00, we should be getting 230000.
I'm sorry but can't understand the context here? Is there an issue?

Example:

if( Hour == 23 && Min == 30 && Sec == 00)
{
  // put the things here that you want to do when it is 23:30:00.
}
1 Like

Ohkay, I guess I get the point trying to be made here, is it the usage of too many vars.?

Here is an example that was offered to a previous user showing how to use the RTC for event timing.

You should be able to see how things were done.

now = rtc.now();

//******************************
//are we into a new second ?
if (lastSecond != now.second())
{
  //update to this new second
  lastSecond = now.second();

    //is it 5AM ?  
    //******************************
    if (now.hour() == 5 && now.minute() == 0 && now.second() == 0)
    {
      Serial.println("Chicken feeder is opening. \n");
    }

    //is it 1:30:05 PM ?  
    //******************************
    else if (now.hour() == 13 && now.minute() == 30 && now.second() == 5)
    {
      Serial.println("Chicken feeder is opening again. \n");
    }


} //END of    if (lastSecond != now.second())

1 Like

With your updated code, you could get a lot of benefits by making a timer struct,, and an array[] of those timer struct…
The code will be shorter, tighter and more maintainable.

—- becomes

struct {
  unsigned long on_Time;
  unsigned long on_hour;
  unsigned long on_min;
  unsigned long on_sec;
} timer_struct;

const unsigned int numberOfTimers = 4;
timer_struct myTimers[numberOfTimers];

Then you refer to as many timers you need as…
. myTimer[n].on_Hour = <avalue>;
and so on…

It’s unlikely, you’ll need longs for hours, minutes and seconds…

1 Like

Thanks a lot, will surely imply this!

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