#include <Arduino.h> // Include the Arduino library
// Input pin definitions
const byte inputComfort = 2;
const byte inputExit = 3;
const byte inputLock = 8;
const byte inputUpFunction = 9;
const byte inputDownFunction = 10;
const byte inputWeather = 11;
const byte inputSpringSwitchRoofUp = 12;
const byte inputSpringSwitchRoofDown = 13;
// Output pin definitions
const byte outputUp = 7;
const byte outputDown = 6;
const byte outputWeatherDown = 5;
// Relay pin definitions
const byte Relay1 = 4; //COM4 - J4
const byte Relay2 = 5; //COM3 - J3
const byte Relay3 = 6; //COM2 - J2
const byte Relay4 = 7; //COM1 - J1
// Timing constants
#define weatherActivationDelay 1000
#define scenario1Timer 80000
#define scenario2Timer 80000
#define scenario3FirstTrigger 3000
#define scenario3SecondTrigger 3000
#define minActionDelay 1000
#define scenario4Timer 1000
#define scenario4Delay 1000
#define scenarioXActivationDelay 1000
#define dailyClosingInterval 1000
#define weeklyMaintenanceDelay 2000
#define weeklyMaintenanceInterval 5000
// Initial variables
unsigned long startMillis;
unsigned long timerStartMillis;
unsigned long lastWeatherActivation = 0;
unsigned long scenario4DeactivationTime = 0;
unsigned long lastDailyClosingTime = 0;
unsigned long lastWeeklyMaintenanceTime = 0;
unsigned long lastInputTime = 0;
bool scenario1Triggered = false;
bool scenario2Triggered = false;
bool scenario3Triggered = false;
bool scenario4Triggered = false;
bool scenario5Triggered = false;
bool scenario6Triggered = false;
bool scenario7Triggered = false;
bool scenario8Triggered = false;
bool weatherClosed = false;
bool firstRun = true;
bool dailyClosingEnabled = false;
bool dailyClosingActive = false;
bool weeklyMaintenanceEnabled = true;
bool weeklyMaintenanceActive = false;
bool weeklyMaintenanceCompleted = false;
byte upFunctionCounter = 0;
byte activeScenario = 0;
bool previousComfort = HIGH;
bool previousExit = HIGH;
bool previousLock = HIGH;
bool initialRun = false;
bool firstScenario1Activation = true;
bool firstRunComfortWeather = true;
byte scenario1ActivationCounter = 0;
static byte scenario4DeactivationCount = 0;
static byte scenario2DeactivationCount = 0;
void setup() {
pinMode(inputComfort, INPUT_PULLUP);
pinMode(inputExit, INPUT_PULLUP);
pinMode(inputLock, INPUT_PULLUP);
pinMode(inputUpFunction, INPUT_PULLUP);
pinMode(inputDownFunction, INPUT_PULLUP);
pinMode(inputWeather, INPUT_PULLUP);
pinMode(inputSpringSwitchRoofUp, INPUT_PULLUP);
pinMode(inputSpringSwitchRoofDown, INPUT_PULLUP);
pinMode(outputUp, OUTPUT);
pinMode(outputDown, OUTPUT);
pinMode(outputWeatherDown, OUTPUT);
pinMode(Relay1, OUTPUT);
pinMode(Relay2, OUTPUT);
pinMode(Relay3, OUTPUT);
pinMode(Relay4, OUTPUT);
Serial.begin(9600);
dailyClosingEnabled = false;
weeklyMaintenanceEnabled = false;
lastWeeklyMaintenanceTime = 0;
}
void deactivateAllOutputs() {
digitalWrite(outputUp, LOW);
digitalWrite(outputDown, LOW);
}
void handleScenarios(bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool weather, bool springSwitchRoofUp, bool springSwitchRoofDown, unsigned long currentMillis) {
if (comfort || exit) {
if (scenario1Triggered || scenario2Triggered || scenario3Triggered || scenario4Triggered) {
deactivateAllOutputs();
scenario1Triggered = false;
scenario2Triggered = false;
scenario3Triggered = false;
scenario4Triggered = false;
upFunctionCounter = 0;
activeScenario = 0;
// Serial.println("Comfort went high - Deactivating all scenarios.");
}
}
if (!scenario1Triggered && !comfort && !exit && lock && (!upFunction || !downFunction) && !weather && springSwitchRoofUp && springSwitchRoofDown &&
(lastWeatherActivation == 0 || (currentMillis - lastWeatherActivation >= weatherActivationDelay)) && !scenario2Triggered && (currentMillis - scenario4DeactivationTime >= scenario4Delay) && !scenario3Triggered) {
if (firstScenario1Activation) {
digitalWrite(outputWeatherDown, HIGH);
delay(scenarioXActivationDelay);
firstScenario1Activation = false;
}
scenario1Triggered = true;
firstScenario1Activation = false;
startMillis = currentMillis;
deactivateAllOutputs();
digitalWrite(outputWeatherDown, HIGH);
activeScenario = 1;
upFunctionCounter = 0;
// Serial.println("Scenario 1 activated");
}
if (scenario1Triggered && (currentMillis - startMillis >= scenario1Timer)) {
digitalWrite(outputWeatherDown, LOW);
scenario1Triggered = false;
lastWeatherActivation = currentMillis;
activeScenario = 0;
// Serial.println("Scenario 1 deactivated after timer");
}
if (scenario1Triggered) {
scenario1ActivationCounter++;
if (scenario1ActivationCounter >= 2) {
firstRunComfortWeather = false;
scenario1ActivationCounter = 0;
}
}
if (!scenario3Triggered) {
handleScenario2(currentMillis, comfort, exit, lock, upFunction, downFunction, weather, springSwitchRoofUp, springSwitchRoofDown);
}
if (!scenario2Triggered) {
handleScenario3(currentMillis, comfort, exit, lock, upFunction, downFunction, weather, springSwitchRoofUp, springSwitchRoofDown);
}
handleScenario5(currentMillis, comfort, exit, lock, upFunction, downFunction, weather, springSwitchRoofUp, springSwitchRoofDown);
handleScenario6(currentMillis, comfort, exit, lock, upFunction, downFunction, weather, springSwitchRoofUp, springSwitchRoofDown);
handleScenario7(currentMillis, comfort, exit, lock, upFunction, downFunction, weather, springSwitchRoofUp, springSwitchRoofDown);
handleScenario8(currentMillis, comfort, exit, lock, upFunction, downFunction, weather, springSwitchRoofUp, springSwitchRoofDown);
handleDailyClosing(currentMillis, comfort, exit, lock, upFunction, downFunction, springSwitchRoofUp, springSwitchRoofDown);
handleWeeklyMaintenance(currentMillis, comfort, exit, lock, upFunction, downFunction, springSwitchRoofUp, springSwitchRoofDown);
}
void handleScenario2(unsigned long currentMillis, bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool weather, bool springSwitchRoofUp, bool springSwitchRoofDown) {
if (firstRunComfortWeather) {
return;
}
if (!firstRunComfortWeather && !comfort && !exit && lock && upFunction && !downFunction && !weather && springSwitchRoofUp && springSwitchRoofDown &&
!scenario2Triggered && (currentMillis - scenario4DeactivationTime >= scenario4Delay)) {
scenario2Triggered = true;
timerStartMillis = currentMillis;
deactivateAllOutputs();
digitalWrite(outputDown, HIGH);
upFunctionCounter = 0;
// Serial.println("Scenario 2 activated and outputDown set to HIGH");
}
if (scenario2Triggered) {
if (currentMillis - timerStartMillis >= scenario2Timer) {
digitalWrite(outputDown, LOW);
scenario2Triggered = false;
scenario2DeactivationCount++;
// Serial.println("Scenario 2 deactivated after timer");
} else if (comfort || exit || !lock || !upFunction ||
(!downFunction && (currentMillis - timerStartMillis > 1000)) ||
!springSwitchRoofUp || !springSwitchRoofDown) {
digitalWrite(outputDown, LOW);
scenario2Triggered = false;
scenario2DeactivationCount++;
scenario4DeactivationTime = currentMillis;
// Serial.println("Scenario 2 deactivated due to input change");
}
}
if (scenario2DeactivationCount >= 2) {
scenario2DeactivationCount = 0;
scenario2Triggered = false;
// Serial.println("Scenario 2 deactivation count reset, scenario2Triggered set to FALSE.");
}
}
void handleScenario3(unsigned long currentMillis, bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool weather, bool springSwitchRoofUp, bool springSwitchRoofDown) {
if (firstRunComfortWeather) {
return;
}
if (!firstRunComfortWeather && !comfort && !exit && lock && !upFunction && downFunction && !weather && springSwitchRoofUp && springSwitchRoofDown && !scenario3Triggered && !scenario4Triggered && (currentMillis - scenario4DeactivationTime >= scenario4Delay)) {
if (scenario2Triggered) {
digitalWrite(outputDown, LOW);
scenario2Triggered = false;
// Serial.println("Scenario 2 deactivated due to Scenario 3 activation");
}
scenario3Triggered = true;
upFunctionCounter++;
timerStartMillis = currentMillis;
if (upFunctionCounter == 1) {
digitalWrite(outputUp, HIGH);
// Serial.println("Scenario 3 activated (1st trigger) and outputUp set to HIGH for 10 seconds");
} else if (upFunctionCounter == 2) {
digitalWrite(outputUp, HIGH);
// Serial.println("Scenario 3 activated (2nd trigger) and outputUp set to HIGH for 10 seconds");
}
}
if (scenario3Triggered) {
if (upFunctionCounter == 1 && (currentMillis - timerStartMillis >= scenario3FirstTrigger)) {
digitalWrite(outputUp, LOW);
scenario3Triggered = false;
// Serial.println("Scenario 3 (1st trigger) deactivated after timer");
} else if (upFunctionCounter == 2 && (currentMillis - timerStartMillis >= scenario3SecondTrigger)) {
digitalWrite(outputUp, LOW);
scenario3Triggered = false;
// Serial.println("Scenario 3 (2nd trigger) deactivated after timer");
}
else if (upFunctionCounter >= 3) {
digitalWrite(outputUp, LOW);
scenario3Triggered = false;
// Serial.println("Scenario 3 (2nd trigger) deactivated after timer");
}
}
if (previousComfort && !comfort && !exit) {
upFunctionCounter = 0;
}
}
void handleScenario5(unsigned long currentMillis, bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool weather, bool springSwitchRoofUp, bool springSwitchRoofDown) {
if (exit && !comfort && lock && upFunction && !downFunction && springSwitchRoofUp && springSwitchRoofDown && !scenario5Triggered && (currentMillis - startMillis >= minActionDelay)) {
scenario5Triggered = true;
digitalWrite(outputDown, HIGH);
// Serial.println("Scenario 5 activated and outputDown set to HIGH");
}
if (scenario5Triggered && (comfort || downFunction)) {
digitalWrite(outputDown, LOW);
scenario5Triggered = false;
// Serial.println("Scenario 5 deactivated");
}
}
void handleScenario6(unsigned long currentMillis, bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool weather, bool springSwitchRoofUp, bool springSwitchRoofDown) {
if (exit && !comfort && lock && !upFunction && downFunction && springSwitchRoofUp && springSwitchRoofDown && !scenario6Triggered && (currentMillis - startMillis >= minActionDelay)) {
scenario6Triggered = true;
digitalWrite(outputUp, HIGH);
// Serial.println("Scenario 6 activated and outputUp set to HIGH");
}
if (scenario6Triggered && (comfort || upFunction)) {
digitalWrite(outputUp, LOW);
scenario6Triggered = false;
// Serial.println("Scenario 6 deactivated");
}
}
void handleScenario7(unsigned long currentMillis, bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool weather, bool springSwitchRoofUp, bool springSwitchRoofDown) {
if (exit && comfort && lock && upFunction && downFunction && springSwitchRoofUp && !springSwitchRoofDown && !scenario7Triggered && (currentMillis - startMillis >= minActionDelay)) {
scenario7Triggered = true;
digitalWrite(outputDown, HIGH);
// Serial.println("Scenario 7 activated and outputDown set to HIGH");
}
if (scenario7Triggered && (!lock || springSwitchRoofDown)) {
digitalWrite(outputDown, LOW);
scenario7Triggered = false;
// Serial.println("Scenario 7 deactivated");
}
}
void handleScenario8(unsigned long currentMillis, bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool weather, bool springSwitchRoofUp, bool springSwitchRoofDown) {
if (exit && comfort && lock && upFunction && downFunction && !springSwitchRoofUp && springSwitchRoofDown && !scenario8Triggered && (currentMillis - startMillis >= minActionDelay)) {
scenario8Triggered = true;
digitalWrite(outputUp, HIGH);
// Serial.println("Scenario 8 activated and outputUp set to HIGH");
}
if (scenario8Triggered && (!lock || springSwitchRoofUp)) {
digitalWrite(outputUp, LOW);
scenario8Triggered = false;
// Serial.println("Scenario 8 deactivated");
}
}
void handleDailyClosing(unsigned long currentMillis, bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool springSwitchRoofUp, bool springSwitchRoofDown) {
static unsigned long previousMillis = 0;
static byte state = 0;
if (!dailyClosingEnabled) {
// Serial.println("Daily Closing is disabled.");
return;
}
if (firstRun) {
lastDailyClosingTime = currentMillis;
firstRun = false;
// Serial.println("First run, setting lastDailyClosingTime.");
return;
}
if (currentMillis - lastDailyClosingTime >= dailyClosingInterval) {
if (!comfort && !exit && !scenario1Triggered && !scenario2Triggered && !scenario3Triggered && dailyClosingEnabled) {
switch (state) {
case 0:
if (!dailyClosingActive) {
// Serial.println("Activating Daily Closing.");
digitalWrite(outputDown, HIGH);
previousMillis = currentMillis;
dailyClosingActive = true;
state = 1;
}
break;
case 1:
if (currentMillis - previousMillis >= scenario2Timer) {
digitalWrite(outputDown, LOW);
lastDailyClosingTime = currentMillis;
dailyClosingActive = false;
state = 0;
// Serial.println("Daily Closing completed. Resetting lastDailyClosingTime.");
}
break;
}
} else {
// Serial.println("Comfort or Exit is not HIGH, not activating Daily Closing.");
}
} else {
// Serial.println("Not enough time has passed since last Daily Closing.");
}
if (dailyClosingActive && (comfort || exit || !lock || !upFunction || !downFunction || !springSwitchRoofUp || !springSwitchRoofDown)) {
digitalWrite(outputDown, LOW);
dailyClosingActive = false;
lastDailyClosingTime = currentMillis;
state = 0;
// Serial.println("Daily Closing deactivated due to input change. Resetting timer.");
}
if (digitalRead(outputUp) == HIGH && digitalRead(outputDown) == HIGH) {
digitalWrite(outputUp, LOW);
digitalWrite(outputDown, LOW);
// Serial.println("Both outputUp and outputDown were HIGH. Resetting both to LOW.");
}
}
void handleWeeklyMaintenance(unsigned long currentMillis, bool comfort, bool exit, bool lock, bool upFunction, bool downFunction, bool springSwitchRoofUp, bool springSwitchRoofDown) {
static unsigned long previousMillis = 0;
static byte state = 0;
static bool weeklyMaintenanceActive = false;
if (!weeklyMaintenanceEnabled) {
// Serial.println("Weekly Maintenance is disabled.");
return;
}
if (firstRun) {
lastWeeklyMaintenanceTime = currentMillis;
firstRun = false;
// Serial.println("First run, setting lastWeeklyMaintenanceTime.");
return;
}
if (currentMillis - lastWeeklyMaintenanceTime >= weeklyMaintenanceInterval) {
if (!comfort && !exit && !scenario1Triggered && !scenario2Triggered && !scenario3Triggered && weeklyMaintenanceEnabled) {
switch (state) {
case 0:
if (!weeklyMaintenanceActive) {
// Serial.println("Activating Weekly Maintenance.");
digitalWrite(outputUp, HIGH);
previousMillis = currentMillis;
weeklyMaintenanceActive = true;
state = 1;
}
break;
case 1:
if (currentMillis - previousMillis >= scenario3FirstTrigger) {
digitalWrite(outputUp, LOW);
previousMillis = currentMillis;
state = 2;
}
break;
case 2:
if (currentMillis - previousMillis >= weeklyMaintenanceDelay) {
digitalWrite(outputDown, HIGH);
previousMillis = currentMillis;
state = 3;
}
break;
case 3:
if (currentMillis - previousMillis >= scenario2Timer) {
digitalWrite(outputDown, LOW);
lastWeeklyMaintenanceTime = currentMillis;
weeklyMaintenanceCompleted = true;
weeklyMaintenanceActive = false;
state = 0;
// Serial.println("Weekly Maintenance completed. Resetting lastWeeklyMaintenanceTime.");
}
break;
}
} else {
// Serial.println("Comfort or Exit is not HIGH, not activating Weekly Maintenance.");
}
} else {
// Serial.println("Not enough time has passed since last Weekly Maintenance.");
}
if (weeklyMaintenanceActive && (comfort || exit || !lock || !upFunction || !downFunction || !springSwitchRoofUp || !springSwitchRoofDown)) {
digitalWrite(outputUp, LOW);
digitalWrite(outputDown, LOW);
weeklyMaintenanceActive = false;
lastWeeklyMaintenanceTime = currentMillis;
state = 0;
// Serial.println("Weekly Maintenance deactivated due to input change. Resetting timer.");
}
if (digitalRead(outputUp) == HIGH && digitalRead(outputDown) == HIGH) {
digitalWrite(outputUp, LOW);
digitalWrite(outputDown, LOW);
// Serial.println("Both outputUp and outputDown were HIGH. Resetting both to LOW.");
}
}
void loop() {
bool comfort = digitalRead(inputComfort) == HIGH;
bool exit = digitalRead(inputExit) == HIGH;
bool lock = digitalRead(inputLock) == HIGH;
bool upFunction = digitalRead(inputUpFunction) == HIGH;
bool downFunction = digitalRead(inputDownFunction) == HIGH;
bool weather = digitalRead(inputWeather) == HIGH;
bool springSwitchRoofUp = digitalRead(inputSpringSwitchRoofUp) == HIGH;
bool springSwitchRoofDown = digitalRead(inputSpringSwitchRoofDown) == HIGH;
unsigned long currentMillis = millis();
handleScenarios(comfort, exit, lock, upFunction, downFunction, weather, springSwitchRoofUp, springSwitchRoofDown, currentMillis);
previousComfort = comfort && exit;
previousExit = comfort;
previousLock = lock;
if (firstRun) {
firstRun = false;
}
// Serial.print("Output Up: ");
// Serial.println(digitalRead(outputUp) == HIGH ? "OPEN" : "CLOSED");
// Serial.print("Output Down: ");
// Serial.println(digitalRead(outputDown) == HIGH ? "OPEN" : "CLOSED");
// Serial.print("Output Weather Down: ");
// Serial.println(digitalRead(outputWeatherDown) == HIGH ? "OPEN" : "CLOSED");
}