Here is a version of your code where the 5 minute-waiting is done none-blocking.
You seem to be a real beginner in coding.
So I recommend
Take a look into this tutorial:
Arduino Programming Course
It is easy to understand and has a good mixture between explaining important concepts and example-codes to get you going. So give it a try and report your opinion about this tutorial.
In this code-version I made a "small" structural change.
The lines of code that do switch on / off the pumps is moved into its own function.
You can see a function as a group of compenents that build a senseful sub-unit.
Your plant-watering system is build from subunits
- pumps
- tubing
- tank
- microcontroller
- etc.
The pump is build from multiple parts
These parts together are the pump
And in this sense you have parts of your code that do
switch on off the pumps
an these parts are put into its own function with name
switchOnOffPumps()
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
int moisture1 = A0;
int moisture2 = A1;
int moisture3 = A2;
int moisture4 = A3;
// declare moisture values
int moisture1_value = 0 ;
int moisture2_value = 0 ;
int moisture3_value = 0 ;
int moisture4_value = 0 ;
// set water relays
int relay1 = 6;
int relay2 = 7;
int relay3 = 8;
int relay4 = 9;
//relay state 1:open 0:close
int relay1_state_flag = 0;
int relay2_state_flag = 0;
int relay3_state_flag = 0;
int relay4_state_flag = 0;
unsigned long my5MinuteTimer;
void setup() {
// use the serial monitor to make visible what is going on in your code
Serial.begin(115200);
Serial.println("Setup-Start");
// initialize the LCD
//lcd.begin();
lcd.init();
Serial.println("lcd.begin() done");
// Turn on the blacklight and print a message.
lcd.backlight();
// declare relay as output
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
my5MinuteTimer = millis(); // initialise variable "my5MinuteTimer" with actual runtime
}
void loop() {
float value1 = analogRead(A0);
moisture1_value = map(value1, 590, 360, 0, 100); delay(20);
if (moisture1_value < 0) {
moisture1_value = 0;
}
float value2 = analogRead(A1);
moisture2_value = map(value2, 600, 360, 0, 100); delay(20);
if (moisture2_value < 0) {
moisture2_value = 0;
}
float value3 = analogRead(A2);
moisture3_value = map(value3, 600, 360, 0, 100); delay(20);
if (moisture3_value < 0) {
moisture3_value = 0;
}
float value4 = analogRead(A3);
moisture4_value = map(value4, 600, 360, 0, 100); delay(20);
if (moisture4_value < 0) {
moisture4_value = 0;
}
// HERE were your lines of code that do aansturing pomp 1-4
// I moved them into their own function with name switchOnOffPumps()
// CHECK if 300000 milliseconds = 5 minutes time have passed by
if ( TimePeriodIsOver(my5MinuteTimer, 300000) ) { // replaces your delay(300000)
// only if REALLY 300000 milliseconds = 5 minutes time have passed by
// execute the lines of code inside function with name "switchOnOffPumps()"
switchOnOffPumps();
}
lcd.setCursor(0, 1);
lcd.print(moisture1_value);
lcd.setCursor(3, 1);
lcd.print("%");
lcd.setCursor(4, 1);
lcd.print(moisture2_value);
lcd.setCursor(7, 1);
lcd.print("%");
lcd.setCursor(8, 1);
lcd.print(moisture3_value);
lcd.setCursor(11, 1);
lcd.print("%");
lcd.setCursor(12, 1);
lcd.print(moisture4_value);
lcd.setCursor(15, 1);
lcd.print("%");
if (relay1_state_flag == LOW) {
lcd.setCursor(0, 0);
lcd.print("1");
}
if (relay2_state_flag == LOW) {
lcd.setCursor(1, 0);
lcd.print("2");
}
if (relay3_state_flag == LOW) {
lcd.setCursor(2, 0);
lcd.print("3");
}
if (relay4_state_flag == LOW) {
lcd.setCursor(3, 0);
lcd.print("4");
}
// no delay needed because the "delaying is done by the if-condition
// if (TimePeriodIsOver(my5MinuteTimer, 300000)
// delay(300000)
} // END of function loop()
void switchOnOffPumps() {
//aansturing pomp 1
if (moisture1_value < 30) {
digitalWrite(relay1, LOW);
relay1_state_flag = 0;
delay(1000);
digitalWrite(relay1, HIGH);
}
else if (moisture1_value > 55) {
digitalWrite(relay1, HIGH);
relay1_state_flag = 1;
delay(1000);
digitalWrite(relay2, LOW);
}
//aansturing pomp 2
if (moisture2_value > 30) {
digitalWrite(relay2, LOW);
relay2_state_flag = 0;
delay(50);
}
else if (moisture2_value < 55) {
digitalWrite(relay2, HIGH);
relay2_state_flag = 1;
delay(50);
}
//aansturing pomp 3
if (moisture3_value < 30) {
digitalWrite(relay3, LOW);
relay3_state_flag = 0;
delay(50);
}
else if (moisture3_value > 55) {
digitalWrite(relay3, HIGH);
relay1_state_flag = 1;
delay(50);
}
//aansturing pomp 4
if (moisture4_value < 30) {
digitalWrite(relay4, LOW);
relay4_state_flag = 0;
delay(50);
}
else if (moisture4_value > 20) {
digitalWrite(relay4, HIGH);
relay4_state_flag = 1;
delay(50);
}
lcd.clear();
} // END of function switchOnOffPumps()
// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
I have done this to make it easier to understand that only that part of the code
that switches on/off the pumps gets executed only once every 5 minutes.
While all the other code is executed all the time without any pausing
Your code has three functional sub-units
- reading in moisture-values
- switching on / off pumps
- updating LCD
Here is a code-version where these three sub-units are placed each in their own function
If you start comparing the single lines of coe you will see it are the exact same lines of code as you wrote it. Just grouped into three functions
with the names
- readInMoistureValues()
- switchOnOffPumps()
- updateLCD()
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
int moisture1 = A0;
int moisture2 = A1;
int moisture3 = A2;
int moisture4 = A3;
// declare moisture values
int moisture1_value = 0 ;
int moisture2_value = 0 ;
int moisture3_value = 0 ;
int moisture4_value = 0 ;
// set water relays
int relay1 = 6;
int relay2 = 7;
int relay3 = 8;
int relay4 = 9;
//relay state 1:open 0:close
int relay1_state_flag = 0;
int relay2_state_flag = 0;
int relay3_state_flag = 0;
int relay4_state_flag = 0;
unsigned long my5MinuteTimer;
void setup() {
// use the serial monitor to make visible what is going on in your code
Serial.begin(115200);
Serial.println("Setup-Start");
// initialize the LCD
//lcd.begin();
lcd.init();
Serial.println("lcd.begin() done");
// Turn on the blacklight and print a message.
lcd.backlight();
// declare relay as output
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
my5MinuteTimer = millis(); // initialise variable "my5MinuteTimer" with actual runtime
}
void loop() {
readInMoistureValues();
if ( TimePeriodIsOver(my5MinuteTimer, 300000) ) { // replaces your delay(300000)
// only if REALLY 300000 milliseconds = 5 minutes time have passed by
// execute the lines of code inside function with name "switchOnOffPumps()"
switchOnOffPumps();
}
updateLCD();
} // END of function loop()
void readInMoistureValues() {
float ADCvalue;
ADCvalue = analogRead(A0);
moisture1_value = map(ADCvalue, 590, 360, 0, 100); delay(20);
if (moisture1_value < 0) {
moisture1_value = 0;
}
ADCvalue = analogRead(A1);
moisture2_value = map(ADCvalue, 600, 360, 0, 100); delay(20);
if (moisture2_value < 0) {
moisture2_value = 0;
}
ADCvalue = analogRead(A2);
moisture3_value = map(ADCvalue, 600, 360, 0, 100); delay(20);
if (moisture3_value < 0) {
moisture3_value = 0;
}
ADCvalue = analogRead(A3);
moisture4_value = map(ADCvalue, 600, 360, 0, 100); delay(20);
if (moisture4_value < 0) {
moisture4_value = 0;
}
} // END of function readInMoistureValues()
void updateLCD() {
lcd.setCursor(0, 1);
lcd.print(moisture1_value);
lcd.setCursor(3, 1);
lcd.print("%");
lcd.setCursor(4, 1);
lcd.print(moisture2_value);
lcd.setCursor(7, 1);
lcd.print("%");
lcd.setCursor(8, 1);
lcd.print(moisture3_value);
lcd.setCursor(11, 1);
lcd.print("%");
lcd.setCursor(12, 1);
lcd.print(moisture4_value);
lcd.setCursor(15, 1);
lcd.print("%");
if (relay1_state_flag == LOW) {
lcd.setCursor(0, 0);
lcd.print("1");
}
if (relay2_state_flag == LOW) {
lcd.setCursor(1, 0);
lcd.print("2");
}
if (relay3_state_flag == LOW) {
lcd.setCursor(2, 0);
lcd.print("3");
}
if (relay4_state_flag == LOW) {
lcd.setCursor(3, 0);
lcd.print("4");
}
} // END of function updateLCD()
void switchOnOffPumps() {
//aansturing pomp 1
if (moisture1_value < 30) {
digitalWrite(relay1, LOW);
relay1_state_flag = 0;
delay(1000);
digitalWrite(relay1, HIGH);
}
else if (moisture1_value > 55) {
digitalWrite(relay1, HIGH);
relay1_state_flag = 1;
delay(1000);
digitalWrite(relay2, LOW);
}
//aansturing pomp 2
if (moisture2_value > 30) {
digitalWrite(relay2, LOW);
relay2_state_flag = 0;
delay(50);
}
else if (moisture2_value < 55) {
digitalWrite(relay2, HIGH);
relay2_state_flag = 1;
delay(50);
}
//aansturing pomp 3
if (moisture3_value < 30) {
digitalWrite(relay3, LOW);
relay3_state_flag = 0;
delay(50);
}
else if (moisture3_value > 55) {
digitalWrite(relay3, HIGH);
relay1_state_flag = 1;
delay(50);
}
//aansturing pomp 4
if (moisture4_value < 30) {
digitalWrite(relay4, LOW);
relay4_state_flag = 0;
delay(50);
}
else if (moisture4_value > 20) {
digitalWrite(relay4, HIGH);
relay4_state_flag = 1;
delay(50);
}
lcd.clear();
} // END of function switchOnOffPumps()
// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long & startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}