#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
RTC_DS1307 rtc;
char daysOfTheWeek[7][24] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
const int ATOtime = 21;
const int ATOduration = 30;
const int AWCday = 6;
const int AWCtime = 12;
const int AWCduration = 30;
LiquidCrystal_I2C lcd(0x27, 20, 4);
/*
HIGH ena = drive dissabled
LOW ena = drive enabled
HIGH dir = CCW = tank drain
LOW dir = CW = tank fill
tankHigh and tankLow are normally LOW; HIGH indicates no water at that level --> external pull-up
wasteHigh is normally HIGH; LOW indicates waste tank is full --> internal pull-up
freshLow is normally HIGH; LOW indicates fresh water tank is empty --> internal pull-up
*/
#define ena_1 2
#define dir_1 3
#define ena_2 4
#define dir_2 5
#define tankHigh 6
#define tankLow 7
#define freshLow 8
#define wasteHigh 9
#define purgeFill 10
#define purgeDrain 11
#define purgeChem 12
// #define txEnable 13
#define light 14 // K4
#define filter 15 // K3
#define heater 16 // K2
#define alarm 17 // K1
int state;
unsigned int a;
int blink;
long offTime = 1000;
long onTime = 1000;
unsigned long previousMillis = 0;
// Timer_2 variables
int trigger;
int cycle;
const long duration_2 = 10000; // milliseconds
long offset_2;
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
pinMode(ena_1, OUTPUT);
pinMode(dir_1, OUTPUT);
pinMode(ena_2, OUTPUT);
pinMode(dir_2, OUTPUT);
pinMode(light, OUTPUT);
pinMode(filter, OUTPUT);
pinMode(heater, OUTPUT);
pinMode(alarm, OUTPUT);
pinMode(tankHigh, INPUT);
pinMode(tankLow, INPUT);
pinMode(freshLow, INPUT_PULLUP);
pinMode(wasteHigh, INPUT_PULLUP);
// pinMode(purgeFill, INPUT);
// pinMode(purgeDrain, INPUT);
// pinMode(purgeChem, INPUT);
pinMode(purgeFill, INPUT_PULLUP);
pinMode(purgeDrain, INPUT_PULLUP);
pinMode(purgeChem, INPUT_PULLUP);
if (! rtc.begin()) {
lcd.setCursor(0,1);
lcd.print("Couldn't find RTC");
while (1);
}
else {
lcd.setCursor(0,1);
lcd.print(" ");
}
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
DateTime now = rtc.now();
state = 0;
a = LOW;
blink = 0;
}
void loop() {
while(state == 0) {
DateTime now = rtc.now();
clock();
State();
if(state != 0) {
break;
}
lcd.setCursor(0,1);
lcd.print("OK ");
digitalWrite(alarm, LOW);
if((now.hour() == ATOtime) && (0 < now.minute()) && (now.minute() < ATOduration)) {
digitalWrite(dir_2, HIGH);
digitalWrite(ena_2, HIGH);
if(digitalRead(tankHigh) == HIGH) {
digitalWrite(dir_1, LOW);
digitalWrite(ena_1, LOW);
lcd.setCursor(0,2);
lcd.print("ATO ");
}
else if(digitalRead(tankHigh) == LOW) {
digitalWrite(dir_1, HIGH);
digitalWrite(ena_1, HIGH);
lcd.setCursor(0,2);
lcd.print("READY");
}
}
else if((digitalRead(purgeDrain) == LOW) && (digitalRead(purgeFill) == HIGH) && (digitalRead(purgeChem) == HIGH)) {
digitalWrite(dir_1, HIGH);
digitalWrite(ena_1, LOW);
lcd.setCursor(0,2);
lcd.print("DRAIN");
}
else if((digitalRead(purgeDrain) == HIGH) && (digitalRead(purgeFill) == LOW) && (digitalRead(purgeChem) == HIGH)) {
digitalWrite(dir_1, LOW);
digitalWrite(ena_1, LOW);
lcd.setCursor(0,2);
lcd.print("FILL ");
}
else if((digitalRead(purgeDrain) == HIGH) && (digitalRead(purgeFill) == HIGH) && (digitalRead(purgeChem) == LOW)) {
digitalWrite(dir_2, LOW);
digitalWrite(ena_2, LOW);
lcd.setCursor(0,2);
lcd.print("CHEM ");
}
else if((digitalRead(purgeDrain) == HIGH) && (digitalRead(purgeFill) == LOW) && (digitalRead(purgeChem) == LOW)) {
delay(20);
State();
}
else {
digitalWrite(dir_1, HIGH);
digitalWrite(ena_1, HIGH);
digitalWrite(dir_2, HIGH);
digitalWrite(ena_2, HIGH);
lcd.setCursor(0,2);
lcd.print("IDLE ");
}
}
while(state == 1) {
clock();
State();
if(state != 1) {
break;
}
lcd.setCursor(0,1);
lcd.print("FRESH");
lcd.setCursor(0,2);
lcd.print("*****");
digitalWrite(dir_1, HIGH);
digitalWrite(ena_1, HIGH);
digitalWrite(dir_2, HIGH);
digitalWrite(ena_2, HIGH);
digitalWrite(alarm, HIGH);
}
while(state == 2) {
clock();
State();
if(state != 2) {
break;
}
lcd.setCursor(0,1);
lcd.print("WASTE");
lcd.setCursor(0,2);
lcd.print("*****");
digitalWrite(dir_1, LOW);
digitalWrite(ena_1, HIGH);
digitalWrite(dir_2, LOW);
digitalWrite(ena_2, HIGH);
digitalWrite(alarm, HIGH);
}
while(state == 3) {
clock();
State();
timer_1();
if(state != 3) {
break;
}
lcd.setCursor(0,1);
lcd.print("ERROR");
lcd.setCursor(0,2);
lcd.print("*****");
digitalWrite(dir_1, LOW);
digitalWrite(ena_1, HIGH);
digitalWrite(dir_2, LOW);
digitalWrite(ena_2, HIGH);
if(blink == 0) {
digitalWrite(alarm, LOW);
digitalWrite(LED_BUILTIN, LOW);
}
else if(blink == 1) {
digitalWrite(alarm, HIGH);
digitalWrite(LED_BUILTIN, HIGH);
}
}
while(state == 4) {
clock();
trigger = 0;
timer_2();
if(digitalRead(purgeFill) == LOW || digitalRead(purgeDrain) == LOW || digitalRead(purgeChem) == LOW) {
trigger = 0;
timer_2();
}
if(cycle == 0) {
lcd.clear();
state = 0;
break;
}
else if(cycle == 1) {
lcd.setCursor(0,1);
lcd.print("CONFIG");
lcd.setCursor(0,2);
lcd.print("------");
}
}
}
void clock() {
DateTime now = rtc.now();
lcd.setCursor(0,0);
if(now.month() < 10) {
lcd.print("0");
lcd.print(now.month());
}
else {
lcd.print(now.month());
}
lcd.print("/");
if(now.day() < 10) {
lcd.print("0");
lcd.print(now.day());
}
else {
lcd.print(now.day());
}
lcd.print("/");
lcd.print(now.year());
lcd.print(" ");
if(now.hour() < 10) {
lcd.print("0");
lcd.print(now.hour());
}
else {
lcd.print(now.hour());
}
lcd.print(":");
if(now.minute() < 10) {
lcd.print("0");
lcd.print(now.minute());
}
else {
lcd.print(now.minute());
}
lcd.print(":");
if(now.second() < 10) {
lcd.print("0");
lcd.print(now.second());
}
else {
lcd.print(now.second());
}
}
void State() {
if((digitalRead(freshLow) == HIGH) && (digitalRead(wasteHigh) == HIGH)) {
state = 0;
}
else if((digitalRead(freshLow) == LOW) && (digitalRead(wasteHigh) == HIGH)) {
state = 1;
}
else if((digitalRead(freshLow) == HIGH) && (digitalRead(wasteHigh) == LOW)) {
state = 2;
}
else if((digitalRead(freshLow) == LOW) && (digitalRead(wasteHigh) == LOW)) {
state = 3;
}
else if((digitalRead(purgeFill) == LOW) && (digitalRead(purgeChem) == LOW)) {
delay(1000);
state = 4;
}
}
void timer_1() {
long currentMillis = millis();
if ((a == HIGH) && (currentMillis - previousMillis >= offTime)) {
a = LOW;
previousMillis = currentMillis;
blink = 1;
}
else if((a == LOW) && (currentMillis - previousMillis >= onTime)) {
a = HIGH;
previousMillis = currentMillis;
blink = 0;
}
}
void timer_2() {
long currentMillis = millis();
if(trigger == 1) {
offset_2 = currentMillis;
trigger = 0;
}
if(currentMillis < (offset_2 + duration_2)) {
cycle = 1;
}
if(currentMillis > (offset_2 + duration_2)) {
cycle = 0;
}
}