/* There are 2 variables changeable for you to adjust as per requirements.
1. B_variations -> Available values options are: 1 or 2 or 3 or 4 or 6 (This this interval for 2 in hours I consider them sub cycle)
2. isC_present -> Available options are: true or false (This is for confirmation of is C is present or not)
As you requested in program in to have 8 different options, my code can provide you 10 different options that can be as following:
1. B = 1, C present
2. B = 1, C not present
3. B = 2, C present
4. B = 2, C not present
5. B = 3, C present
6. B = 3, C not present
7. B = 4, C present
8. B = 4, C not present
9. B = 6, C present
10. B = 6, C not present
*/
#include <LiquidCrystal.h>
#include "RTClib.h"
/********************** Changeable variables **********************/
bool isC_present = true; // Options available true or false
int B_variation = 1; // Options available 1, 2, 3, 4 or 5 hours
/********************** Changeable variables **********************/
int relay[4] = {2, 3, 4, 5};
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
DateTime now;
// program variables
bool relayStatus[4] = {false};
bool debug = true;
int lastSecond = 0;
void setup() {
Serial.begin(115200);
for(int i=0; i < 4; i++){
pinMode(relay[i], OUTPUT);
digitalWrite(relay[i], LOW);
}
// digitalWrite(relay[0], HIGH);
lcd.begin(16, 2);
lcd.print(" Welcome!");
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
delay(2000);
lcd.clear();
}
void loop() {
now = rtc.now();
displayTime();
char currentCycle = getCycle();
if (currentCycle == 'A') {
ifPrint("Cycle A");
long runTime = getRunningTime(currentCycle);
Serial.println(runTime);
// Relay B ON for 2 minutes. B can be turned ON with either 1,2,3 or 4 hours interval
if (runTime < 120){
if(relayStatus[0]){
digitalWrite(relay[0], LOW);
relayStatus[0] = false;
}
if(relayStatus[2]){
digitalWrite(relay[2], LOW);
relayStatus[2] = false;
}
if(relayStatus[3]){
digitalWrite(relay[3], LOW);
relayStatus[3] = false;
}
if(!relayStatus[1]){
digitalWrite(relay[1], HIGH);
relayStatus[1] = true;
}
}
else if (runTime >= 120 && runTime < 240){ // checks from 2 to 4 minutes
if(isC_present){ // if C is present then turn on it and turn off B
if(relayStatus[0]){
digitalWrite(relay[0], LOW);
relayStatus[0] = false;
}
if(relayStatus[1]){
digitalWrite(relay[1], LOW);
relayStatus[1] = false;
}
if(relayStatus[3]){
digitalWrite(relay[3], LOW);
relayStatus[3] = false;
}
if(!relayStatus[2]){
digitalWrite(relay[2], HIGH);
relayStatus[2] = true;
}
}
else{
if(relayStatus[1]){ // if C is not present turn off B and turn on A and Fan
digitalWrite(relay[1], LOW);
relayStatus[1] = false;
}
if(relayStatus[2]){
digitalWrite(relay[2], LOW);
relayStatus[2] = false;
}
if(!relayStatus[0]){
digitalWrite(relay[0], HIGH);
relayStatus[0] = true;
}
if(!relayStatus[3]){
digitalWrite(relay[3], HIGH);
relayStatus[3] = true;
}
}
}
else if(runTime >= (B_variation * 3600) - 120) { //last 2 minutes of subcycle Fan turns off
if(relayStatus[3]){
digitalWrite(relay[3], LOW);
relayStatus[3] = false;
}
}
else{ // Light A and Fan remains on when nothing is on or last 2 minutes of subcycle
if(relayStatus[1]){
digitalWrite(relay[1], LOW);
relayStatus[1] = false;
}
if(relayStatus[2]){
digitalWrite(relay[2], LOW);
relayStatus[2] = false;
}
if(!relayStatus[3]){
digitalWrite(relay[3], HIGH);
relayStatus[3] = true;
}
if(!relayStatus[0]){
digitalWrite(relay[0], HIGH);
relayStatus[0] = true;
}
}
}
else {
ifPrint("Cycle B");
long runTime = getRunningTime(currentCycle);
Serial.println(runTime);
// relay A stays off in each condition.
if(relayStatus[0]){
digitalWrite(relay[0], LOW);
relayStatus[0] = false;
}
// Relay B ON for 2 minutes. B can be turned ON with either 1,2,3 or 4 hours interval
if (runTime < 120){
if(relayStatus[2]){
digitalWrite(relay[2], LOW);
relayStatus[2] = false;
}
if(relayStatus[3]){
digitalWrite(relay[3], LOW);
relayStatus[3] = false;
}
if(!relayStatus[1]){
digitalWrite(relay[1], HIGH);
relayStatus[1] = true;
}
}
else if (runTime >= 120 && runTime < 240){ // checks from 2 to 4 minutes
if(isC_present){ // if C is present then turn on it and turn off B
if(relayStatus[1]){
digitalWrite(relay[1], LOW);
relayStatus[1] = false;
}
if(relayStatus[3]){
digitalWrite(relay[3], LOW);
relayStatus[3] = false;
}
if(!relayStatus[2]){
digitalWrite(relay[2], HIGH);
relayStatus[2] = true;
}
}
else{
if(relayStatus[1]){ // if C is not present turn off B and turn on A and Fan
digitalWrite(relay[1], LOW);
relayStatus[1] = false;
}
if(relayStatus[2]){
digitalWrite(relay[2], LOW);
relayStatus[2] = false;
}
if(!relayStatus[3]){
digitalWrite(relay[3], HIGH);
relayStatus[3] = true;
}
}
}
else if(runTime >= (B_variation * 3600) - 120) { //last 2 minutes of subcycle Fan turns off
if(relayStatus[3]){
digitalWrite(relay[3], LOW);
relayStatus[3] = false;
}
}
else{ // Fan remains on when nothing is on or last 2 minutes of subcycle
if(relayStatus[1]){
digitalWrite(relay[1], LOW);
relayStatus[1] = false;
}
if(relayStatus[2]){
digitalWrite(relay[2], LOW);
relayStatus[2] = false;
}
if(!relayStatus[3]){
digitalWrite(relay[3], HIGH);
relayStatus[3] = true;
}
}
}
}
char getCycle() {
int currentHour = now.hour();
if (currentHour >= 6 && currentHour < 18) {
return 'A';
} else {
return 'B';
}
}
long getRunningTime(char cycle){
int startHour = 18;
if(cycle == 'A'){
startHour = 6;
}
int cycleHour = (now.hour() - startHour < 0) ? now.hour() - startHour + 24 : now.hour() - startHour;
int runningTimeHour = cycleHour;
while(runningTimeHour >= B_variation){
runningTimeHour -= B_variation;
}
long runningTime = runningTimeHour * 3600 + now.minute() * 60 + now.second();
return runningTime;
}
void displayTime(){
if(now.second() != lastSecond){
lcd.setCursor(4,0);
if(now.hour() < 10){
lcd.print("0");
}
lcd.print(now.hour());
lcd.print(":");
if(now.minute() < 10){
lcd.print("0");
}
lcd.print(now.minute());
lcd.print(":");
if(now.second() < 10){
lcd.print("0");
}
lcd.println(now.second());
if(now.year() < 10){
lcd.print("0");
}
lcd.setCursor(1,1);
lcd.print(now.year());
lcd.print('/');
if(now.month() < 10){
lcd.print("0");
}
lcd.print(now.month());
lcd.print('/');
if(now.day() < 10){
lcd.print("0");
}
lcd.print(now.day());
lcd.print(" ");
lcd.println(daysOfTheWeek[now.dayOfTheWeek()]);
lastSecond = now.second();
}
}
void ifPrint(const char* message) {
if (debug) {
Serial.println(message);
}
}