RTC controlled relays.

Hello,

I am using 4 channel relay (out of which I am using only 3) connected to arduino uno.
I need to control these 3 relays based on RTC.
if the states of those relays is specific and it has to repeat the same states every day,
then its not a problem,i could use this code format( found on the this forum)

#include <TimeAlarms.h>    //Changed Number of  alarms dtNBR_ALARMS to 30 max 255 

void setup()
{
Alarm.alarmRepeat(12,15,0, Feed);              //  Lunch                      hh,mm,ss
Alarm.alarmRepeat(8,15,0, LightOn);           //  Turn on the light 
//other alarm events

}
void loop()
{
}

//***********************************************
//Lunch
void Feed()
{
  // Put Lunch code here 
}
//***********************************************
//Turn on the light 
void LightOn()
{
  // Put LightOn code here 
}
//***********************************************

but, the state of relays changes at different time for every alternative days.

for example,

1st day-- @11:00, relay=on, relay 2=off, relay 3=on.
@11.20, r1 =on,r2=off, r3=off.
@13.20, r1=off,r2=on, r3=on.

2nd day--@11:00, relay=on, relay 2=off, relay 3=on.
--@12:00, r1 =on,r2=off, r3=off.
--@13:00, r1=off,r2=on, r3=on.

3rd day--- same as 1st
4th day--- same as 2nd

and repeats likewise for every alternative days.

how can i write or modify code for the above requirement.
kindly suggest.
Thank you.

You could manually toggle a boolean flag todayIsOdd just before 11 each morning, and do one of two sets of timings for that day.

But of course that relies on the power not going off or when Arduino restarts it would go to your initial setting of todayIsOdd which may not be correct for that day.

I'm wondering if there's some easy way to calculate if a day is even or odd (in the grand scheme of things, perhaps against the start of Unix time) from the rtc's date?

navya14:
how can i write or modify code for the above requirement.
kindly suggest.
Thank you.

there are a lot of considerations here. For example, you have to consider what to do on power-up and should the relays go into their desired state (i.e. it's in between relay events).

Also, what is day "1" if you power cycle? how do you determine of you are in an odd or even day? Or, do you just do it the lazy way and always reboot into day 1.

I recommend that you really define what it is you want to do and write that all down. Once you have that, you may want to learn about UNIX timestamps.

Turns out that RTC.get() in the DS1307RTC library tells you the number of seconds since time started.

So just divide that by 86400 to give you the number of full days in an integer. That's yesterday. Add 1 for today. Take the modulo % to see if today is even or odd.

(Edit: or don't bother adding 1. It doesn't matter if today is odd or even in the grand scheme, just that alternate days are seen as even-odd or odd-even.)

//odd or even day

#include <DS1307RTC.h>
#include <Time.h>

unsigned long noOfSeconds;
int noOfWholeDays;
int todayIsDay;
bool todayIsOdd;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  noOfSeconds = RTC.get();
  noOfWholeDays = noOfSeconds / 86400;
  todayIsDay = noOfWholeDays + 1;
  if (todayIsDay % 2 == 0)
  {
    todayIsOdd = false;
  }
  else
  {
    todayIsOdd = true;
  }

  Serial.println(noOfSeconds);
  Serial.println(noOfWholeDays);
  Serial.println(todayIsDay);
  if (todayIsOdd)
  {
    Serial.println("Today is an ODD day");
  }
  else
  {
    Serial.println("Today is an EVEN day");
  }
  Serial.println(" ");
}

void loop() {
  // put your main code here, to run repeatedly:

}

Gives this today:

1487865014
17220
17221
This is an ODD day

manor_royal:

This is an ODD day

feels normal to me.

BulldogLowell:
feels normal to me.

Har-de-har

I thought much the same....

And my logic works: today is EVEN. (I didn't sit up to watch it toggle at midnight, but this morning it's correct.)

So OP that's an easy way to handle different actions on alternate days.

(Although you don't say which RTC and library you use; ymmv.)

BulldogLowell:
Also, what is day "1" if you power cycle? how do you determine of you are in an odd or even day?

uint16_t ymdToDays(uint8_t y, uint8_t m, uint8_t d) {
  // Converts date (year, month, day) to day number.
  // Input the year as a number from 0 to 99. (0 means AD 2000)
  
  // some basic sanity checks
  if (y>99) return 0xFFFF;
  if ((m<1)||(m>12)) return 0xFFFF;
  if ((d<1)||(d>31)) return 0xFFFF;
  
  y+=4; // so that the next line can't make it go negative
  if (m<=2) {y--; m+=12;} // treat Jan. and Feb. as part of preceding year
  
  uint16_t n=365*y; // whole years (not counting leap days)
  n+=(y>>2); // add in the leap days
  n+=(31*(uint16_t)m); // take care of months (assuming 31 days per month)
  
  // the next few lines compensate for short months
  if     (m>11) n-=4;
  else if (m>9) n-=3;
  else if (m>6) n-=2;
  else if (m>4) n-=1;
  
  n+=d; // take care of the day of the month
  
  return (n-1495); // make 2000-01-01(Sat) be day 0
}

BulldogLowell:
I recommend that you really define what it is you want to do and write that all down. Once you have that, you may want to learn about UNIX timestamps.

odometer:

uint16_t ymdToDays(uint8_t y, uint8_t m, uint8_t d) {

// Converts date (year, month, day) to day number.
  // Input the year as a number from 0 to 99. (0 means AD 2000)
 
  // some basic sanity checks
  if (y>99) return 0xFFFF;
  if ((m<1)||(m>12)) return 0xFFFF;
  if ((d<1)||(d>31)) return 0xFFFF;
 
  y+=4; // so that the next line can't make it go negative
  if (m<=2) {y--; m+=12;} // treat Jan. and Feb. as part of preceding year
 
  uint16_t n=365y; // whole years (not counting leap days)
  n+=(y>>2); // add in the leap days
  n+=(31
(uint16_t)m); // take care of months (assuming 31 days per month)
 
  // the next few lines compensate for short months
  if    (m>11) n-=4;
  else if (m>9) n-=3;
  else if (m>6) n-=2;
  else if (m>4) n-=1;
 
  n+=d; // take care of the day of the month
 
  return (n-1495); // make 2000-01-01(Sat) be day 0
}

that's a lot of busy work where what @manor_royal did it condenses to a single line:

if(now() / (60*60*24) % 2)
  {
    processTimer(oddDays);
  }
  else
  {
    processTimer(evenDays);
  }

odometer:
Year 2038 problem - Wikipedia

Oh no! I guess the clock is ticking, we only have 20 years to find a solution.

yeah!!

I used that even odd concept for alternative days. It worked.
I used RTClib and Timealarm libraries for my code.

Thank you everyone.

I am trying to use the same code for the same reason. I can't figure out some things that I explain below:
1.Is the function 'alarm' correct to make it run on alternate days?The reason I do that is the nano do things at specific time from the RTC.

if (todayIsOdd)
  {
    Serial.println("Today is an ODD day");
  }
  else
  {
    Serial.println("Today is an EVEN day");
      Alarm.alarmRepeat(13,58,0,AlarmAction);
  }

2.Will the above run the third day? I wondering because the 'if' statement is placed at the setup.
Here the code:

//odd or even day

#include <TimeAlarms.h>
#include <Wire.h> 
#include <Time.h>
#include <DS1307RTC.h>

unsigned long noOfSeconds;
int noOfWholeDays;
int todayIsDay;
bool todayIsOdd;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time"); 
 digitalWrite(52, HIGH);
 digitalWrite(50, HIGH);
 digitalWrite(48, HIGH);
 digitalWrite(46, HIGH);
 digitalWrite(44, HIGH);
 digitalWrite(42, HIGH);
 digitalWrite(40, HIGH);
 digitalWrite(38, HIGH); 

  //definition of the relays as outputs   
  pinMode(52, OUTPUT);
  pinMode(50, OUTPUT);
  pinMode(48, OUTPUT);
  pinMode(46, OUTPUT);
  pinMode(44, OUTPUT);
  pinMode(42, OUTPUT);
  pinMode(40, OUTPUT);
  pinMode(38, OUTPUT);

  noOfSeconds = RTC.get();
  noOfWholeDays = noOfSeconds / 86400;
  todayIsDay = noOfWholeDays + 1;
  if (todayIsDay % 2 == 0)
  {
    todayIsOdd = false;
  }
  else
  {
    todayIsOdd = true;
  }
  Serial.println(noOfSeconds);
  Serial.println(noOfWholeDays);
  Serial.println(todayIsDay);
 if (todayIsOdd)
  {
    Serial.println("Today is an ODD day");
  }
  else
  {
    Serial.println("Today is an EVEN day");
      Alarm.alarmRepeat(13,58,0,AlarmAction);
  }
  Serial.println(" ");
}

void loop() {
  digitalClockDisplay();
  Alarm.delay(1000); // wait one second between clock display
  }
void AlarmAction () {
   
  // functions to be called when an alarm triggers:
  Serial.println("POTISMA");  
  digitalWrite(52, LOW); //RELAY 1 ON
  delay(300000);               //wait 4 min 
  digitalWrite(52, HIGH);  //RELAY 1 OFF
  digitalWrite(50, LOW); //RELAY 2 ON
  delay(300000);               //wait  4 min
  digitalWrite(50, HIGH);  //RELAY 2 OFF
  digitalWrite(48, LOW); //RELAY 3 ON
  delay(400000);               //wait 5 min
  digitalWrite(48, HIGH);  //RELAY 3 OFF
  digitalWrite(46, LOW); //RELAY 4 ON
  delay(400000);               //wait 5 min
  digitalWrite(46, HIGH);  //RELAY 4 OFF
  digitalWrite(44, LOW); //RELAY 5 ON
  delay(400000);               //wait 5 min
  digitalWrite(44, HIGH);  //RELAY 5 OFF
  digitalWrite(42, LOW); //RELAY 6 ON
  delay(400000);               //wait 5 min
  digitalWrite(42, HIGH);  //RELAY 6 OFF
  digitalWrite(40, LOW); //RELAY 7 ON
  delay(5000);               //wait 5 min
  digitalWrite(40, HIGH);  //RELAY 7 OFF
  digitalWrite(38, LOW); //RELAY 8 ON
  delay(5000);               //wait 5 min
  digitalWrite(38, HIGH);  //RELAY 8 OFF
}
void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print("-");
  Serial.print(day());
  Serial.print("/");
  Serial.print(month());
  Serial.print("/");
  Serial.print(year()); 
  Serial.println(); 
  delay(30000);
}
void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

nikakis30:

  {

Serial.println("Today is an EVEN day");
     Alarm.alarmRepeat(13,58,0,AlarmAction);
 }



[/code]

This looks like it will set up an alarm to trigger every day, and you don't want that.

Here is some info I found:

Here is how you create an alarm to trigger a task repeatedly at a particular time of day:
Alarm.alarmRepeat(8,30,0, MorningAlarm);
This would call the function MorningAlarm() at 8:30 am every day.

If you want the alarm to trigger only once you can use the alarmOnce method:
Alarm.alarmOnce(8,30,0, MorningAlarm);
This calls a MorningAlarm() function in a sketch once only (when the time is next 8:30am)

I found that information at: GitHub - PaulStoffregen/TimeAlarms: Time library add-on, schedule alarms to occur at specific dates/times

If you want accuracy, think about NTP or celllular time.