ok I was just guessing, I need to study up on them
I definitely did learn that certain things don't work in interrupt which is why I set up flags for them and detect them in loop.
here's the latest with a lot more logic.
What I don't know is why the serial print is necessary in delayInt() for it to work. I guess it forces the global update of the value somehow.
#include <String.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 20 chars and 4 line display
#include <RTClib.h> // REAL TIME CLOCK
RTC_DS3231 rtc;
// Ppump RELAYS
const int NUT_1_PIN = 53;
const int NUT_2_PIN = 51;
const int NUT_3_PIN = 49;
const int NUT_4_PIN = 47;
const int NUT_5_PIN = 45;
const int NUT_6_PIN = 43;
const int NUT_7_PIN = 41;
// VALVE RELAYS
const int FILL_PIN = 39;
const int MIX_PIN = 37;
const int RES1_PIN = 35;
const int RES2_PIN = 33;
// OUTPUT PUMP RELAY
const int PUMP_PIN = 31;
// GOING TO NEED PINS FOR 7 WATER LEVEL SENSORS
// 3 SENSORS FOR MIX BUCKET
// 2 FOR EACH RES
const int LEVEL_MIX_HIGH_PIN = 52;
const int LEVEL_MIX_MED_PIN = 50;
const int LEVEL_MIX_LOW_PIN = 48;
const int LEVEL_RES1_HIGH_PIN = 46;
const int LEVEL_RES1_LOW_PIN = 44;
const int LEVEL_RES2_HIGH_PIN = 42;
const int LEVEL_RES2_LOW_PIN = 40;
// RED HALT BUTTON
bool ic = false;
unsigned long lastStopPress = millis();
void stopButtonInterrupt() {
if ( millis() - lastStopPress > 2000 ) {
lastStopPress = millis(); // ez debounce
if (ic) {
ic = false;
} else {
ic = true;
}
}
}
// BLACK START BUTTON
bool startCycle = false;
bool mixRunning = false;
unsigned long lastStartPress = millis();
void startButtonInterrupt() {
if (!mixRunning) {
if ( millis() - lastStartPress > 2000 ) {
lastStartPress = millis(); // ez debounce
startCycle = true;
}
}
}
void setup() {
delay(3000);
Serial.begin(9600);
// EMERGENCY STOP
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), stopButtonInterrupt, HIGH); // CHANGE
// START
pinMode(3, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(3), startButtonInterrupt, HIGH); // CHANGE
// RTC
rtc.begin();
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// LCD
lcd.init();
lcd.clear();
lcd.backlight();
lcd.setCursor(0,0); lcd.print("A NAME HERE");
lcd.setCursor(17, 0); lcd.print("NOR"); // LCD INTERRUPT CONDITION NORMAL INITIAL STATE
// PUMP RELAY
pinMode(PUMP_PIN, OUTPUT); // OUTPUT PUMP
// VALVE RELAYS
pinMode(FILL_PIN, OUTPUT); // FILL RELAY
pinMode(MIX_PIN, OUTPUT); // BUCKET MIXER RELAY
pinMode(RES1_PIN, OUTPUT); // RES 1 OUTPUT RELAY
pinMode(RES2_PIN, OUTPUT); // RES 2 OUTPUT RELAY
// Ppump RELAYS
pinMode(NUT_1_PIN, OUTPUT);
pinMode(NUT_2_PIN, OUTPUT);
pinMode(NUT_3_PIN, OUTPUT);
pinMode(NUT_4_PIN, OUTPUT);
pinMode(NUT_5_PIN, OUTPUT);
pinMode(NUT_6_PIN, OUTPUT);
pinMode(NUT_7_PIN, OUTPUT);
}
void relay(String name, bool state) {
if (name == "PUMP") { if (state) { digitalWrite(PUMP_PIN, HIGH); } else { digitalWrite(PUMP_PIN, LOW); }}
else if (name == "FILL") { if (state) { digitalWrite(FILL_PIN, LOW); } else { digitalWrite(FILL_PIN, HIGH); }}
else if (name == "MIX" ) { if (state) { digitalWrite(MIX_PIN, LOW); } else { digitalWrite(MIX_PIN, HIGH); }}
else if (name == "RES1") { if (state) { digitalWrite(RES1_PIN, LOW); } else { digitalWrite(RES1_PIN, HIGH); }}
else if (name == "RES2") { if (state) { digitalWrite(RES2_PIN, LOW); } else { digitalWrite(RES1_PIN, HIGH); }}
else if (name == "NUT1") { if (state) { digitalWrite(NUT_1_PIN, HIGH); } else { digitalWrite(NUT_1_PIN, LOW); }}
else if (name == "NUT2") { if (state) { digitalWrite(NUT_2_PIN, HIGH); } else { digitalWrite(NUT_2_PIN, LOW); }}
else if (name == "NUT3") { if (state) { digitalWrite(NUT_3_PIN, HIGH); } else { digitalWrite(NUT_3_PIN, LOW); }}
else if (name == "NUT4") { if (state) { digitalWrite(NUT_4_PIN, HIGH); } else { digitalWrite(NUT_4_PIN, LOW); }}
else if (name == "NUT5") { if (state) { digitalWrite(NUT_5_PIN, HIGH); } else { digitalWrite(NUT_5_PIN, LOW); }}
else if (name == "NUT6") { if (state) { digitalWrite(NUT_6_PIN, HIGH); } else { digitalWrite(NUT_6_PIN, LOW); }}
else if (name == "NUT7") { if (state) { digitalWrite(NUT_7_PIN, HIGH); } else { digitalWrite(NUT_7_PIN, LOW); }}
}
void updateTime(int col, int row) {
DateTime now = rtc.now();
String year = String(now.year()).substring(2,4);
String month = String(now.month()); String day = String(now.day());
String hours = String(now.hour()); if (now.hour() < 10) {hours = "0" + hours;}
String minutes = String(now.minute()); if (now.minute() < 10) {minutes = "0" + minutes;}
String dt = month + "/" + day + "|" + hours + ":" + minutes;
// Serial.print("CLOCK: "); Serial.println(dt);
lcd.setCursor(col, row); lcd.print(dt);
}
void status(String message) {
lcd.setCursor(0,0); lcd.print(" ");
lcd.setCursor(0,0); lcd.print(message);
}
void delayInt(int secs) { // INTERRUPT SENSITIVE DELAY
int x = 0;
while (x < secs and !ic) {
x++; delay(1000);
Serial.println(ic); // required somehow
}
}
int x = 0;
void mixingCycle() {
Serial.println(ic);
if(ic){return;} status("CYCLE START"); delay(1000);
status("INITIAL FILL"); relay("FILL", true);
delayInt(10); if(ic){return;} // WOULD WAIT FOR MIN WATER LEVEL
status("MIN WATER OK"); delayInt(10); if(ic){return;}
status("PUMP/MIX ON"); relay("MIX", true); delayInt(3); if(ic){return;} relay("PUMP", true); delayInt(10); if(ic){return;}
status("DOSING SILICA"); relay("NUT1", true); delayInt(10); if(ic){return;} relay("NUT1", false); delay(1000);
status("MAX WATER FILL");
delayInt(10); if(ic){return;} // WOULD WAIT FOR FULL WATER LEVEL
status("MAX WATER OK" ); delayInt(10); if(ic){return;}
status("FILL OFF"); relay("FILL", false); delayInt(3); if(ic){return;}
status("MIXING SILICA"); delayInt(20); if(ic){return;}
status("DOSING CALMAG"); relay("NUT2", true); delayInt(10); if(ic){return;} relay("NUT2", false); delay(1000);
status("MIXING CALMAG"); delayInt(10); if(ic){return;}
status("DOSING MICRO" ); relay("NUT3", true); delayInt(10); if(ic){return;} relay("NUT3", false); delay(1000);
status("MIXING MICRO"); delayInt(10); if(ic){return;}
status("DOSING BLOOM" ); relay("NUT4", true); delayInt(10); if(ic){return;} relay("NUT4", false); delay(1000);
status("MIXING BLOOM"); delayInt(10); if(ic){return;}
status("DOSING GROW" ); relay("NUT5", true); delayInt(10); if(ic){return;} relay("NUT5", false); delay(1000);
status("MIXING GROW"); delayInt(10); if(ic){return;}
status("DOSING NECTAR"); relay("NUT6", true); delayInt(10); if(ic){return;} relay("NUT6", false); delay(1000);
status("MIXING NECTAR"); delayInt(10); if(ic){return;}
status("DOSING THRIVE"); relay("NUT7", true); delayInt(10); if(ic){return;} relay("NUT7", false); delay(1000);
status("MIXING THRIVE"); delayInt(10); if(ic){return;}
status("FINAL MIXING"); delayInt(10); if(ic){return;} // CONTINUE MIXING EVERYTHING FOR A WHILE
status("PUMP/MIX OFF"); relay("PUMP", false); delayInt(10); if(ic){return;} relay("MIX", false); delay(1000);
status("MIX CYCLE DONE!");
lcd.setCursor(0,1); lcd.print("LAST: "); updateTime(6,1);
delay(1000);
}
void disableAllRelays() {
digitalWrite(PUMP_PIN, LOW);
digitalWrite(FILL_PIN, HIGH);
digitalWrite(MIX_PIN, HIGH);
digitalWrite(RES1_PIN, HIGH);
digitalWrite(RES2_PIN, HIGH);
digitalWrite(NUT_1_PIN, LOW);
digitalWrite(NUT_2_PIN, LOW);
digitalWrite(NUT_3_PIN, LOW);
digitalWrite(NUT_4_PIN, LOW);
digitalWrite(NUT_5_PIN, LOW);
digitalWrite(NUT_6_PIN, LOW);
digitalWrite(NUT_7_PIN, LOW);
}
bool loopStartup = false;
void loop() {
if (!loopStartup) {
loopStartup = true;
disableAllRelays();
delay(3000);
}
updateTime(9,3);
// CONTROL FOR SYSTEM
// DETECT WATER LEVELS AND SET startCyle
// OR PUMP OUT EXISTING NUTRIENTS (CODE DOESN'T EXIST YET, NEED SENSORS)
// OR DECIDE IT HASN'T BEEN LONG ENOUGH AND DON'T CYCLE AT ALL
// LOGIC ETC
if (!ic) {
lcd.setCursor(17, 0); lcd.print("NOR");
if (startCycle) {
startCycle = false;
mixRunning = true;
mixingCycle(); delay(1000);
disableAllRelays();
mixRunning = false;
}
} else { // WHEN STOPPED MANUALLY
startCycle = false;
mixRunning = false;
lcd.setCursor(0, 0); lcd.print("CANCEL INT");
}
delay(1000);
}