#include <RTClib.h>
RTC_DS1307 rtc; // RTC DS1307 with NVRAM
const int relayHidraulicPumpPin = 6;
const int relayUpPin = 7;
const int relayDownPin = 8;
const int relayInPin = 9;
const int relayOutPin = 10;
const int switchOpenPin = 11;
const int switchClosePin = 12;
const int switchUpPin = 2;
const int switchDownPin = 3;
const int switchInPin = 4;
const int switchOutPin = 5;
const int setupLedPin = 13;
const int relayOn = 1;
const int relayOff = 0;
const int switchOffStatus = 1;
int hidraulicPumpStatus = 0;
int openStatus = 0;
int openSwitchState = switchOffStatus;
int openSwitchLastState = switchOffStatus;
int openSwitchPressTime = 0;
int closeStatus = 0;
int closeSwitchState = switchOffStatus;
int closeSwitchLastState = switchOffStatus;
int closeSwitchPressTime = 0;
int upStatus = 0;
int upSwitchState = switchOffStatus;
int upSwitchLastState = switchOffStatus;
int upSwitchPressTime = 0;
int downStatus = 0;
int downSwitchState = switchOffStatus;
int downSwitchLastState = switchOffStatus;
int downSwitchPressTime = 0;
int inStatus = 0;
int inSwitchState = switchOffStatus;
int inSwitchLastState = switchOffStatus;
int inSwitchPressTime = 0;
int outStatus = 0;
int outSwitchState = switchOffStatus;
int outSwitchLastState = switchOffStatus;
int outSwitchPressTime = 0;
int openDownSeconds = 4;
int openOutSeconds = 6;
int closeUpSeconds = 5;
int closeInSeconds = 7;
int upUntilTimestamp;
int downUntilTimestamp;
int inUntilTimestamp;
int outUntilTimestamp;
int setupStatus = 0;
int setupModeEnterTime = 5;
int time;
unsigned long eventInterval = 1000;
unsigned long previousTime = 0;
unsigned long currentTime = 0;
void setup() {
// set pin modes
pinMode(relayHidraulicPumpPin, OUTPUT);
digitalWrite(relayHidraulicPumpPin, relayOff);
pinMode(relayUpPin, OUTPUT);
digitalWrite(relayUpPin, relayOff);
pinMode(relayDownPin, OUTPUT);
digitalWrite(relayDownPin, relayOff);
pinMode(relayInPin, OUTPUT);
digitalWrite(relayInPin, relayOff);
pinMode(relayOutPin, OUTPUT);
digitalWrite(relayOutPin, relayOff);
pinMode(switchOpenPin, INPUT_PULLUP);
pinMode(switchClosePin, INPUT_PULLUP);
pinMode(switchUpPin, INPUT_PULLUP);
pinMode(switchDownPin, INPUT_PULLUP);
pinMode(switchInPin, INPUT_PULLUP);
pinMode(switchOutPin, INPUT_PULLUP);
pinMode(setupLedPin, OUTPUT);
digitalWrite(setupLedPin, LOW);
// begin modules & interfaces
Serial.begin(115200);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
// load data from NVRAM, if set
int memOpenDownUpSeconds = rtc.readnvram(0);
int memOpenOutSeconds = rtc.readnvram(1);
int memCloseUpSeconds = rtc.readnvram(2);
int memCloseInSeconds = rtc.readnvram(3);
if (memOpenDownUpSeconds != 0) {
openDownSeconds = memOpenDownUpSeconds;
} else {
rtc.writenvram(0, openDownSeconds);
}
if (memOpenOutSeconds != 0) {
openOutSeconds = memOpenOutSeconds;
} else {
rtc.writenvram(1, openOutSeconds);
}
if (memCloseUpSeconds != 0) {
closeUpSeconds = memCloseUpSeconds;
} else {
rtc.writenvram(2, closeUpSeconds);
}
if (memCloseInSeconds != 0) {
closeInSeconds = memCloseInSeconds;
} else {
rtc.writenvram(3, closeInSeconds);
}
// output some instructions
Serial.println("[d]+[enter] for date/time setup");
Serial.println("[p]+[enter] for platform setup");
char buff[50];
sprintf(buff, "Press open button for %d seconds to enter platform open setup mode", setupModeEnterTime);
Serial.println(buff);
sprintf(buff, "Press close button for %d seconds to enter platform close setup mode", setupModeEnterTime);
Serial.println(buff);
}
void loop() {
time = getTimestamp();
currentTime = millis();
if (Serial.available()) {
if (setupStatus == 0) {
char input = Serial.read();
if (input == 'd') {
setupStatus = 1;
delay(500);
setupRealTimeClockModule();
} else if (input == 'p') {
setupStatus = 1;
delay(500);
setupPlatformTimmers();
}
}
}
openSwitchState = digitalRead(switchOpenPin);
if (openSwitchState != openSwitchLastState) {
if (openSwitchState != switchOffStatus && setupStatus == 0) {
openSwitchPressTime = time;
} else {
if (setupStatus == 0) {
if (setupStatus == 0 && openSwitchPressTime > 0 && (time - openSwitchPressTime) >= setupModeEnterTime) {
Serial.println("Open platform setup mode on.");
setupStatus = 1;
} else if (openSwitchPressTime > 0) {
if (!isPlatformMoving()) {
open();
delay(500);
} else if (isPlatformMoving()) {
stopAll();
delay(500);
}
}
} else if (setupStatus == 1) {
if (downSwitchPressTime > 0 || outSwitchPressTime > 0) {
rtc.writenvram(0, downSwitchPressTime);
rtc.writenvram(1, outSwitchPressTime);
Serial.println("\nPlatform timmers settings:");
showPlatformOpenTimmers();
Serial.println("Leaving open platform setup mode.");
delay(500);
} else {
Serial.println("No platform down or out movements detected.");
Serial.println("Leaving open platform setup mode without saving.");
delay(500);
}
setupStatus = 0;
}
openSwitchPressTime = 0;
}
}
openSwitchLastState = openSwitchState;
// if (!isPlatformMoving() && digitalRead(switchClosePin) != switchOffStatus) {
// close();
// delay(300);
// }
closeSwitchState = digitalRead(switchClosePin);
if (closeSwitchState != closeSwitchLastState) {
if (closeSwitchState != switchOffStatus && setupStatus == 0) {
closeSwitchPressTime = time;
} else {
if (setupStatus == 0) {
if (setupStatus == 0 && closeSwitchPressTime > 0 && (time - closeSwitchPressTime) >= setupModeEnterTime) {
Serial.println("Close platform setup mode on.");
setupStatus = 1;
} else if (closeSwitchPressTime > 0) {
if (!isPlatformMoving()) {
close();
delay(500);
} else if (isPlatformMoving()) {
stopAll();
delay(500);
}
}
} else if (setupStatus == 1) {
if (upSwitchPressTime > 0 || inSwitchPressTime > 0) {
rtc.writenvram(2, upSwitchPressTime);
rtc.writenvram(3, inSwitchPressTime);
Serial.println("\nPlatform timmers settings:");
showPlatformCloseTimmers();
Serial.println("Leaving close platform setup mode.");
delay(500);
} else {
Serial.println("No platform up or in movements detected.");
Serial.println("Leaving close platform setup mode without saving.");
delay(500);
}
setupStatus = 0;
}
closeSwitchPressTime = 0;
delay(50);
}
}
closeSwitchLastState = closeSwitchState;
if (isSetupMode()) {
digitalWrite(setupLedPin, HIGH);
} else {
digitalWrite(setupLedPin, LOW);
}
if (!isPlatformMoving() && digitalRead(switchUpPin) != switchOffStatus) {
up();
delay(300);
}
if (!isPlatformMoving() && digitalRead(switchDownPin) != switchOffStatus) {
down();
delay(300);
}
if (!isPlatformMoving() && digitalRead(switchInPin) != switchOffStatus) {
in();
delay(300);
}
if (!isPlatformMoving() && digitalRead(switchOutPin) != switchOffStatus) {
out();
delay(300);
}
if (closeStatus == 1 && upStatus == 1 && time >= upUntilTimestamp) {
stopUp();
}
if (openStatus == 1 && downStatus == 1 && time >= downUntilTimestamp) {
stopDown();
}
if (closeStatus == 1 && inStatus == 1 && time >= inUntilTimestamp) {
stopIn();
}
if (openStatus == 1 && outStatus == 1 && time >= outUntilTimestamp) {
stopOut();
}
if (isPlatformMoving() && hidraulicPumpStatus == 0) {
startHidraulicPump();
} else if (!isPlatformMoving() && hidraulicPumpStatus == 1) {
stopHidraulicPump();
}
}
boolean isSetupMode() {
return setupStatus == 1 ||
(openSwitchPressTime > 0 && (time - openSwitchPressTime) >= setupModeEnterTime) ||
(closeSwitchPressTime > 0 && (time - closeSwitchPressTime) >= setupModeEnterTime);
}
boolean isPlatformMoving() {
return (upStatus == 1 || downStatus == 1 || inStatus == 1 || outStatus == 1);
}
boolean isSwitchPressed() {
return (digitalRead(switchOpenPin) != switchOffStatus ||
digitalRead(switchClosePin) != switchOffStatus ||
digitalRead(switchUpPin) != switchOffStatus ||
digitalRead(switchDownPin) != switchOffStatus ||
digitalRead(switchInPin) != switchOffStatus ||
digitalRead(switchOutPin) != switchOffStatus);
}
void startHidraulicPump() {
hidraulicPumpStatus = 1;
digitalWrite(relayHidraulicPumpPin, relayOn);
}
void stopHidraulicPump() {
hidraulicPumpStatus = 0;
digitalWrite(relayHidraulicPumpPin, relayOff);
}
void open() {
openStatus = downStatus = outStatus = 1;
time = getTimestamp();
downUntilTimestamp = time + openDownSeconds;
outUntilTimestamp = time + openOutSeconds;
down();
out();
Serial.println("Platform is opening (down for " + String(openDownSeconds) + " seconds, out for " + String(openOutSeconds) + " seconds)...");
}
void close() {
closeStatus = upStatus = inStatus = 1;
time = getTimestamp();
upUntilTimestamp = time + closeUpSeconds;
inUntilTimestamp = time + closeInSeconds;
up();
in();
Serial.println("Platform is closing (up for " + String(closeUpSeconds) + " seconds, in for " + String(closeInSeconds) + " seconds)...");
}
void up() {
upStatus = 1;
startHidraulicPump();
digitalWrite(relayUpPin, relayOn);
}
void down() {
downStatus = 1;
startHidraulicPump();
digitalWrite(relayDownPin, relayOn);
}
void in() {
inStatus = 1;
startHidraulicPump();
digitalWrite(relayInPin, relayOn);
}
void out() {
outStatus = 1;
startHidraulicPump();
digitalWrite(relayOutPin, relayOn);
}
void stopAll() {
stopUp();
stopDown();
stopIn();
stopOut();
stopHidraulicPump();
}
void stopUp() {
upUntilTimestamp = 0;
upStatus = 0;
digitalWrite(relayUpPin, relayOff);
if (closeStatus == 1) {
if (inStatus == 0) {
closeStatus = 0;
}
Serial.println("Up stopped.");
}
}
void stopDown() {
downUntilTimestamp = 0;
downStatus = 0;
digitalWrite(relayDownPin, relayOff);
if (openStatus == 1) {
if (outStatus == 0) {
openStatus = 0;
}
Serial.println("Down stopped.");
}
}
void stopIn() {
inUntilTimestamp = 0;
inStatus = 0;
digitalWrite(relayInPin, relayOff);
if (closeStatus == 1) {
if (upStatus == 0) closeStatus = 0;
Serial.println("In stopped.");
}
}
void stopOut() {
outUntilTimestamp = 0;
outStatus = 0;
digitalWrite(relayOutPin, relayOff);
if (openStatus == 1) {
if (downStatus == 0) openStatus = 0;
Serial.println("Out stopped.");
}
}
int getTimestamp(){
return rtc.now().unixtime();
}
boolean isValidNumber(String str){
for(byte i=0;i<str.length();i++) {
if (isDigit(str.charAt(i))) {
return true;
}
}
return false;
}
void setupPlatformTimmers() {
const char txt[4][50] = { "platform open DOWN timer in seconds [0~20]",
"platform open OUT timer in seconds [0~20]",
"platform close UP timer in seconds [0~20]",
"platform close IN timer in seconds [0~20]" };
String str = "";
while (Serial.available()) {
Serial.read(); // clear serial buffer
}
for (int i = 0; i < 4; i++) {
Serial.print("Enter ");
Serial.print(txt[i]);
Serial.print(" (" + String(rtc.readnvram(i)) + ")");
Serial.print(": ");
while (!Serial.available()) {
; // wait for user input
}
str = Serial.readString();
if (str.length() > 0 && isValidNumber(str) && str.toInt() >= 0 && str.toInt() <= 20) {
if (i == 0) {
openDownSeconds = str.toInt();
Serial.println(openDownSeconds);
} else if (i == 1) {
openOutSeconds = str.toInt();
Serial.println(openOutSeconds);
} else if (i == 2) {
closeUpSeconds = str.toInt();
Serial.println(closeUpSeconds);
} else if (i == 3) {
closeInSeconds = str.toInt();
Serial.println(closeInSeconds);
}
rtc.writenvram(i, str.toInt()); // write to RTC NVRAM
} else {
Serial.println("invaid value!");
i--;
}
}
Serial.println("\nPlatform timmers settings:");
showPlatformOpenTimmers();
showPlatformCloseTimmers();
Serial.println("Exit platform setup mode.");
setupStatus = 0;
}
void showPlatformOpenTimmers () {
Serial.println(String("Open DOWN timer:\t") + rtc.readnvram(0));
Serial.println(String("Open OUT timer:\t\t") + rtc.readnvram(1));
}
void showPlatformCloseTimmers () {
Serial.println(String("Close UP timer:\t\t") + rtc.readnvram(2));
Serial.println(String("Close IN timer:\t\t") + rtc.readnvram(3));
}
void setupRealTimeClockModule() {
const char txt[6][15] = { "year [4-digit]", "month [1~12]", "day [1~31]",
"hours [0~23]", "minutes [0~59]", "seconds [0~59]" };
String str = "";
long newDate[6];
while (Serial.available()) {
Serial.read();
}
for (int i = 0; i < 8; i++) {
Serial.print("Enter ");
Serial.print(txt[i]);
Serial.print(": ");
while (!Serial.available()) {
;
}
str = Serial.readString();
if (i < 6) {
newDate[i] = str.toInt();
Serial.println(newDate[i]);
}
}
rtc.adjust(DateTime(newDate[0], newDate[1], newDate[2], newDate[3], newDate[4], newDate[5])); // write date/time to RTC
Serial.println(String("Date/time set to:\t") + rtc.now().timestamp(DateTime::TIMESTAMP_FULL));
Serial.println("Exit date/time setup mode.");
setupStatus = 0;
}