#define BLYNK_TEMPLATE_ID "TMPL6eA5vitLk"
#define BLYNK_TEMPLATE_NAME "Smart Plant Monitor"
#define BLYNK_AUTH_TOKEN "ernP2NKW_nRuQdrz4BN4lWvCof6ngNX9"
#include <WiFi.h>
#include <HTTPClient.h>
#include <BlynkSimpleEsp32.h>
#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP32Servo.h> // مكتبة السيرفو الخاصة بالـ ESP32
// ========================== WiFi و Blynk ==========================
char ssid[] = "Wokwi-GUEST";
char password[] = "";
BlynkTimer timer;
// ThingSpeak
const char* TS_WRITE_KEY = "JPSQG4NM9MZQJKS9";
// ========================== تعريف الحساسات والمخرجات ==========================
// Potentiometers
#define POT_SOIL 34
#define POT_WATER 32
#define POT_FLOW 35
// DHT22
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// DS18B20
#define ONE_WIRE_BUS 13
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature soilTemp(&oneWire);
// LDR
#define LDR_PIN 27
// LEDs
#define LED_SERVO 26
#define LED_PUMP 0
#define LED_FAN 2
// RGB LED
#define RGB_R 12
#define RGB_G 33
#define RGB_B 25
// Buzzer
#define BUZZER 14
int buzzerVolume = 50; // مستوى الصوت الافتراضي (0-100)
// PIR + Servo
#define PIR_PIN 16
Servo myServo;
// ========================== متغيرات التحكم اليدوي ==========================
bool manualPump = false;
bool manualFan = false;
bool manualServo = false;
bool manualBuzzer = false;
// ========================== متغيرات حركة السيرفو مع PIR ==========================
bool motionActive = false;
int servoAngle = 0;
bool servoGoingUp = true;
// ========================== BLYNK WRITE للتحكم اليدوي ==========================
// مضخة
BLYNK_WRITE(V7) {
int value = param.asInt();
manualPump = (value != 0);
digitalWrite(LED_PUMP, manualPump ? HIGH : LOW);
}
// مروحة
BLYNK_WRITE(V8) {
int value = param.asInt();
manualFan = (value != 0);
digitalWrite(LED_FAN, manualFan ? HIGH : LOW);
}
// سيرفو
BLYNK_WRITE(V9) {
int value = param.asInt();
manualServo = (value != 0);
digitalWrite(LED_SERVO, manualServo ? HIGH : LOW);
if (manualServo) myServo.write(90); // زاوية تحريك
else myServo.write(0);
}
// Buzzer - التحكم بمستوى الصوت عبر سلايدر
BLYNK_WRITE(V14) {
buzzerVolume = param.asInt();
manualBuzzer = (buzzerVolume > 0);
}
// ========================== Setup ==========================
void setup() {
Serial.begin(115200);
// اتصال WiFi
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected!");
// بدء Blynk
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, password);
// تهيئة المخرجات
pinMode(LED_SERVO, OUTPUT);
pinMode(LED_PUMP, OUTPUT);
pinMode(LED_FAN, OUTPUT);
pinMode(RGB_R, OUTPUT);
pinMode(RGB_G, OUTPUT);
pinMode(RGB_B, OUTPUT);
pinMode(BUZZER, OUTPUT);
pinMode(PIR_PIN, INPUT);
// بدء الحساسات
dht.begin();
soilTemp.begin();
// السيرفو
myServo.attach(17); // البن المتصل بالسيرفو في Wokwi
myServo.write(0); // البداية صفر درجة
// Timer لقراءة الحساسات كل 2 ثانية
timer.setInterval(2000L, readSensors);
}
// ========================== Loop ==========================
void loop() {
if (motionActive) {
// حركة السيرفو خطوة بخطوة كل 20ms
static unsigned long lastMove = 0;
if (millis() - lastMove >= 20) {
lastMove = millis();
if (servoGoingUp) {
servoAngle += 2; // صعود تدريجي
if (servoAngle >= 180) {
servoAngle = 180;
servoGoingUp = false; // ابدأ النزول
}
} else {
servoAngle -= 2; // نزول تدريجي
if (servoAngle <= 0) {
servoAngle = 0;
motionActive = false; // انتهت اللفة
Serial.println("Servo sweep completed.");
}
}
myServo.write(servoAngle);
Serial.print("Servo angle: ");
Serial.println(servoAngle);
}
}
Blynk.run();
timer.run();
}
// ========================== قراءة الحساسات والتحكم ==========================
void readSensors() {
// قراءة المقاومات
int rawSoil = analogRead(POT_SOIL);
int rawWater = analogRead(POT_WATER);
int rawFlow = analogRead(POT_FLOW);
int soilHumidity = map(rawSoil, 0, 4095, 0, 100);
int waterLevel = map(rawWater, 0, 4095, 0, 100);
int flowRate = map(rawFlow, 0, 4095, 0, 100);
// باقي الحساسات
float lightLevel = analogRead(LDR_PIN);
float airTemp = dht.readTemperature();
float airHumidity = dht.readHumidity();
soilTemp.requestTemperatures();
float soilTemperature = soilTemp.getTempCByIndex(0);
Serial.print("Soil: "); Serial.print(soilHumidity);
Serial.print(" | Water: "); Serial.print(waterLevel);
Serial.print(" | Flow: "); Serial.print(flowRate);
Serial.print(" | Light: "); Serial.print(lightLevel);
Serial.print(" | Air Temp: "); Serial.print(airTemp);
Serial.print(" | Air Hum: "); Serial.print(airHumidity);
Serial.print(" | Soil Temp: "); Serial.println(soilTemperature);
// ----------- التحكم بالمخرجات -----------
// فحص PIR وتشغيل السيرفو لمرة واحدة
if (!manualServo && digitalRead(PIR_PIN) == HIGH && !motionActive) {
motionActive = true;
servoAngle = 0;
servoGoingUp = true;
Serial.println("Motion detected! Starting one servo sweep.");
}
// مضخة
int pumpState = 0;
if (!manualPump) {
if (soilHumidity < 30 && waterLevel > 20) {
digitalWrite(LED_PUMP, HIGH);
pumpState = 1;
setRGB(0, 0, 255);
} else {
digitalWrite(LED_PUMP, LOW);
pumpState = 0;
if (soilHumidity < 30) setRGB(255, 0, 0);
else setRGB(0, 255, 0);
}
}
// مروحة
int fanState = 0;
if (!manualFan) {
if (airTemp > 30 || lightLevel > 700) {
digitalWrite(LED_FAN, HIGH);
fanState = 1;
} else {
digitalWrite(LED_FAN, LOW);
fanState = 0;
}
}
// سيرفو (عند التدفق العالي)
int servoState = 0;
if (!manualServo && !motionActive) {
if (flowRate > 30) {
digitalWrite(LED_SERVO, HIGH);
myServo.write(90);
servoState = 1;
} else {
digitalWrite(LED_SERVO, LOW);
myServo.write(0);
servoState = 0;
}
}
// Buzzer
int buzzerState = 0;
if (manualBuzzer || pumpState == 1) {
int duration = map(buzzerVolume, 0, 100, 50, 500);
tone(BUZZER, 1000, duration);
buzzerState = 1;
} else {
noTone(BUZZER);
buzzerState = 0;
}
// ----------- إرسال إلى Blynk -----------
Blynk.virtualWrite(V0, soilHumidity);
Blynk.virtualWrite(V1, waterLevel);
Blynk.virtualWrite(V2, flowRate);
Blynk.virtualWrite(V3, lightLevel);
Blynk.virtualWrite(V4, airTemp);
Blynk.virtualWrite(V5, airHumidity);
Blynk.virtualWrite(V6, soilTemperature);
Blynk.virtualWrite(V10, pumpState);
Blynk.virtualWrite(V11, fanState);
Blynk.virtualWrite(V12, servoState);
Blynk.virtualWrite(V30, buzzerState);
// ----------- إرسال إلى ThingSpeak -----------
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String tsURL = String("http://api.thingspeak.com/update?api_key=") + TS_WRITE_KEY +
"&field1=" + String(soilHumidity) +
"&field2=" + String(waterLevel) +
"&field3=" + String(flowRate) +
"&field4=" + String(lightLevel) +
"&field5=" + String(airTemp) +
"&field6=" + String(airHumidity) +
"&field7=" + String(soilTemperature);
http.begin(tsURL);
int httpCode = http.GET();
http.end();
Serial.println("ThingSpeak Update: " + String(httpCode));
}
}
// ========================== RGB ==========================
void setRGB(int r, int g, int b) {
analogWrite(RGB_R, r);
analogWrite(RGB_G, g);
analogWrite(RGB_B, b);
}
رطوبة التربة
شدة الماء
الماء في الخزان
حالة النبات
طربال
صوت تفاعلي
حساس رطوبة وحرارة الجو
تشغيل المضخة
تشغيل المروحة
حرارة التربة
شدة الاضاءة
حساس الحركة
فزاعة