#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include <math.h>
#define NUM_FIELDS 4
#define SENSORS_PER_FIELD 4
#define BASE_SERVO_TIME 4000
#define TOTAL_SERVO_LOOP_TIME 24000
#define EXTRA_TIME 8000
const int potPins[NUM_FIELDS][SENSORS_PER_FIELD] = {
{A0, A1, A2, A3},
{A4, A5, A6, A7},
{A8, A9, A10, A11},
{A12, A13, A14, A15}
};
const int muxControlPins[4] = {6, 7, 8, 9};
const int triggerPins[NUM_FIELDS] = {10, 12, 14, 16}; // Trigger pins for each HC-SR04
const int echoPins[NUM_FIELDS] = {11, 13, 15, 17}; // Echo pins for each HC-SR04
LiquidCrystal_I2C lcd(0x27, 20, 4);
Servo servos[NUM_FIELDS];
const int servoPins[NUM_FIELDS] = {2, 3, 4, 5};
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
for (int i = 0; i < NUM_FIELDS; i++) {
servos[i].attach(servoPins[i]);
servos[i].write(0);
pinMode(triggerPins[i], OUTPUT);
pinMode(echoPins[i], INPUT);
}
for (int i = 0; i < 4; i++) {
pinMode(muxControlPins[i], OUTPUT);
}
// Display startup message
lcd.setCursor(2, 0); // Adjusted for center alignment
lcd.print("Auto-Irrigation");
lcd.setCursor(7, 1); // Adjusted for center alignment
lcd.print("System");
lcd.setCursor(9, 2); // Adjusted for center alignment
lcd.print("by");
lcd.setCursor(7, 3); // Adjusted for center alignment
lcd.print("Team 4");
delay(2000);
lcd.clear();
}
void loop() {
float moistureLevels[NUM_FIELDS];
float totalMoisture = 0;
float waterDischarge[NUM_FIELDS];
for (int field = 0; field < NUM_FIELDS; field++) {
float fieldMoistureSum = 0;
for (int sensor = 0; sensor < SENSORS_PER_FIELD; sensor++) {
int potValue = analogRead(potPins[field][sensor]);
fieldMoistureSum += map(potValue, 0, 1023, 0, 100);
}
moistureLevels[field] = fieldMoistureSum / SENSORS_PER_FIELD;
totalMoisture += (100 - moistureLevels[field]);
selectMuxChannel(field);
float distance = measureDistance(field);
float h_meters = (50 - distance) / 100.0;
waterDischarge[field] = ((0.3 + (tan(radians(15)))) * (h_meters)) * (h_meters);
displayData(field, moistureLevels[field], waterDischarge[field]);
}
for (int field = 0; field < NUM_FIELDS; field++) {
int additionalTime = (totalMoisture > 0) ? (int)(EXTRA_TIME * ((100 - moistureLevels[field]) / totalMoisture)) : 0;
int fieldTime = BASE_SERVO_TIME + additionalTime;
servos[field].write(90);
delay(fieldTime);
servos[field].write(0);
Serial.print("Field ");
Serial.print(field + 1);
Serial.print(" Avg Moisture: ");
Serial.print(moistureLevels[field]);
Serial.print("%, Q: ");
Serial.print(waterDischarge[field], 6);
Serial.print(" m^3/s, Time: ");
Serial.print(fieldTime / 1000.0, 1);
Serial.println(" s");
delay(500);
}
delay(1000);
}
void selectMuxChannel(int channel) {
for (int i = 0; i < 4; i++) {
digitalWrite(muxControlPins[i], (channel & (1 << i)) ? HIGH : LOW);
}
}
float measureDistance(int fieldIndex) {
digitalWrite(triggerPins[fieldIndex], LOW);
delayMicroseconds(2);
digitalWrite(triggerPins[fieldIndex], HIGH);
delayMicroseconds(10);
digitalWrite(triggerPins[fieldIndex], LOW);
long duration = pulseIn(echoPins[fieldIndex], HIGH);
float distance = (duration * 0.0343) / 2;
return distance;
}
void displayData(int fieldIndex, float moisture, float discharge) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Field ");
lcd.print(fieldIndex + 1);
lcd.print(" Mstr:");
lcd.setCursor(0, 1);
lcd.print(moisture, 1);
lcd.print("%");
lcd.setCursor(0, 2);
lcd.print("Q: ");
lcd.print(discharge, 6);
lcd.print(" m3/s");
delay(2000);
}