/*
Wokwi: https://wokwi.com/projects/408364396627342337
Forum: https://forum.arduino.cc/t/need-some-insight/1299365
Based on the code from post #1 but modified version
*/
const byte sensorPin = A0; // Pin connected to the sensor's analog output
const byte ledPin = 13;
int sensorValue = 0; // Variable to store sensor reading
float moisturePercent = 0.0;
const byte pumpRelayPin = 8;
bool relayOn = false;
float lastMoisturePercent = 0; // Store the last moisture reading
byte moistureRange = 0;
unsigned long lastMeasurement = 0; // Store the time of the last moisture measurement
unsigned long lastChangeTime = 0; // Store the time of the last moisture change
unsigned long relayOnTime = 0; // Store the time when the relay was turned on
unsigned long currentTime = 0; // Store the current time
const unsigned long timeout = 10000; // 10 seconds for timeout
const unsigned long relayDelay = 15000; // 1 minute for relay delay
const unsigned long INTERVAL = 1000; // One Measurement every second
// Calibration values (based on observed sensor extremes)
const int dryValue = 783; // Sensor value when completely dry
const int wetValue = 380; // Sensor value when completely wet
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT); // Set LED pin as an output
pinMode(pumpRelayPin, OUTPUT); // Set relay pin as an output
digitalWrite(pumpRelayPin, HIGH); // Start with relay OFF
lastMoisturePercent = 100;
digitalWrite(ledPin, LOW);
}
void loop() {
currentTime = millis(); // Get the current time in milliseconds
if (currentTime - lastMeasurement > INTERVAL) {
lastMeasurement = currentTime;
readSensor(); // Read the value from the sensor
determineMoistureRange(); // Determine the moisture range
handleLeds(); // Switch statement for LED flashing pattern
handlePump();
}
}
void readSensor() {
sensorValue = analogRead(sensorPin);
Serial.print("Raw sensor value: ");
Serial.println(sensorValue);
sensorValue = constrain(sensorValue, wetValue, dryValue);
moisturePercent = 100.0 * (float)(dryValue - sensorValue) / (dryValue - wetValue);
Serial.print("Soil moisture level: ");
Serial.print(moisturePercent);
Serial.println("%");
}
void determineMoistureRange() {
moistureRange = 0; // Everything larger than 25% and lower than 76%
// 0% - 25%
if (moisturePercent <= 25.00) {
moistureRange = 1;
}
// 76% - 100%
if (moisturePercent >= 76.00) {
moistureRange = 4;
}
}
void handleLeds() {
switch (moistureRange) {
case 1:
digitalWrite(ledPin, HIGH); // LED ON continuously
break;
case 4:
digitalWrite(ledPin, HIGH); // Turn LED ON
delay(150); // Wait 150 ms for ON duration,
// No problem as long as it is much shorter than INTERVAL and other timings
digitalWrite(ledPin, LOW); // Turn LED OFF
break;
default:
digitalWrite(ledPin, LOW); // LED OFF for other ranges
break;
}
}
void handlePump() {
// if moisture is low and pump is OFF
if (moisturePercent <= 10.00 && !relayOn) {
digitalWrite(pumpRelayPin, LOW); // LOW to turn the relay ON (most relays are active-low)
relayOn = true;
Serial.println("Relay ON - Moisture is too low!");
lastChangeTime = currentTime;
relayOnTime = currentTime; // Record the time when the relay was turned on
}
// if moisture is sufficient and pump is ON
if (moisturePercent >= 60.00 && relayOn) {
// Check if pump has been ON for a sufficient time
if (currentTime - relayOnTime >= relayDelay) {
relayOn = false;
digitalWrite(pumpRelayPin, HIGH); // HIGH to turn the relay OFF
Serial.println("Relay OFF - Moisture is sufficient.");
lastChangeTime = currentTime;
}
}
// Check if the moisture level has changed; if it has, reset the change timer
if (moisturePercent != lastMoisturePercent) {
lastChangeTime = currentTime;
lastMoisturePercent = moisturePercent;
}
// If timeout have expired without moisture change, turn the relay off
if (relayOn && (currentTime - lastChangeTime >= timeout)) {
digitalWrite(pumpRelayPin, HIGH); // HIGH to turn the relay OFF
relayOn = false; // Track that the relay is OFF
Serial.println("Relay OFF - No change in moisture level for 10 seconds.");
}
}