#include <WiFi.h>
#include <WebServer.h>
#include "DHTesp.h"
// Wi-Fi (replace with your SSID/PASS)
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Pins
#define DHT_PIN 15
#define SOIL_PIN 34
#define RELAY_PIN 17
#define TRIG_PIN 26
#define ECHO_PIN 27
DHTesp dht;
WebServer server(80);
// Modes & states
bool autoMode = true;
bool pumpOn = false;
int currentCrop = 0;
// Crop database
struct Crop { const char* name; int minMoisture; };
Crop crops[] = {
{"Potato", 45},
{"Tomato", 40},
{"Maize", 35}
};
// Relay control
void pumpControl(bool state) {
pumpOn = state;
digitalWrite(RELAY_PIN, state ? LOW : HIGH); // active low relay
}
// Calculate soil % (use calibration in real hardware)
int getSoilMoisture() {
int raw = analogRead(SOIL_PIN);
int dry = 3000, wet = 1100;
int percent = map(raw, dry, wet, 0, 100);
if (percent < 0) percent = 0;
if (percent > 100) percent = 100;
return percent;
}
// Tank level (mock in Wokwi, works with ultrasonic)
int getTankLevel() {
digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
float dist = duration / 58.0; // cm
float tankHeight = 100.0; // adjust to real tank
float pct = (1.0 - (dist / tankHeight)) * 100.0;
if (pct < 0) pct = 0;
if (pct > 100) pct = 100;
return (int)pct;
}
// Web page
void handleRoot() {
int soil = getSoilMoisture();
float temp = dht.getTemperature();
float hum = dht.getHumidity();
int tank = getTankLevel();
String html = "<html><head><meta name='viewport' content='width=device-width, initial-scale=1'>";
html += "<style>body{font-family:sans-serif;} button{padding:10px;margin:5px;}</style></head><body>";
html += "<h2>🌱 AgroSmart Dashboard</h2>";
html += "<p><b>Temperature:</b> " + String(temp) + " °C</p>";
html += "<p><b>Humidity:</b> " + String(hum) + " %</p>";
html += "<p><b>Soil Moisture:</b> " + String(soil) + " %</p>";
html += "<p><b>Tank Level:</b> " + String(tank) + " %</p>";
html += "<p><b>Mode:</b> " + String(autoMode ? "AUTO" : "MANUAL") + "</p>";
html += "<p><b>Pump:</b> " + String(pumpOn ? "ON" : "OFF") + "</p><hr>";
// Crop selector
html += "<form action='/setcrop'>";
html += "Crop: <select name='c'>";
for (int i=0;i<3;i++) {
html += "<option value='" + String(i) + "'";
if (i == currentCrop) html += " selected";
html += ">" + String(crops[i].name) + "</option>";
}
html += "</select><input type='submit' value='Set'></form><br>";
// Buttons
html += "<a href='/toggle'><button>Toggle Auto/Manual</button></a>";
html += "<a href='/pump?on=1'><button>Pump ON</button></a>";
html += "<a href='/pump?on=0'><button>Pump OFF</button></a>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void handleSetCrop() {
if (server.hasArg("c")) {
currentCrop = server.arg("c").toInt();
}
server.sendHeader("Location", "/");
server.send(302, "text/plain", "");
}
void handleToggle() {
autoMode = !autoMode;
server.sendHeader("Location", "/");
server.send(302, "text/plain", "");
}
void handlePump() {
if (server.hasArg("on")) {
pumpControl(server.arg("on") == "1");
}
server.sendHeader("Location", "/");
server.send(302, "text/plain", "");
}
void setup() {
Serial.begin(115200);
dht.setup(DHT_PIN, DHTesp::DHT22);
pinMode(RELAY_PIN, OUTPUT);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pumpControl(false);
WiFi.begin(ssid, password);
Serial.print("Connecting WiFi");
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println(" Connected! IP=" + WiFi.localIP().toString());
server.on("/", handleRoot);
server.on("/setcrop", handleSetCrop);
server.on("/toggle", handleToggle);
server.on("/pump", handlePump);
server.begin();
}
void loop() {
server.handleClient();
if (autoMode) {
int soil = getSoilMoisture();
int tank = getTankLevel();
if (soil < crops[currentCrop].minMoisture && tank > 10) {
pumpControl(true);
} else {
pumpControl(false);
}
}
}