قياس رطوبة التربة، و إرسال إنذار صوتي عند حاجة النبتة للسقي

الأحد, أغسطس 21, 2016


قمت بهذا المشروع منذ مدة طويلة جدا، و نشرته على حسابي على أنستغرام، و لم أرى أنه يستحق النشر على المدونة لبساطته الشديدة، و لكن خلف تلك البساطة كانت تختفي كارثة برمجية، بعد إعادة النظر في الكود بدى لي غبيا نوع ما و مكررا، في السابق كنت قبل البدأ بأي مشروع من الضروري أن أتصفح Tutorial ما، أقوم بالبناء عليه، والقيام بما يتطلب من تعديلات تناسب مشروعي، و هذا ما قمت به مع هذا المشروع في السابق،لكن الآن قررت أن أتشجع و أفتح صفحة جديدة و أكتب الكود من الصفر دون الاستعانة بأي مصدر.

النتيجة كانت هي كود من 4 أسطر عوض 16 سطرا أو أكثر، كود مرتب و أكثر منطقية من السابق، أحد أهم القواعد البرمجية هي "Don't repeat yourself" أي لا تكرر نفسك، دع الحاسوب يقوم بالعمل المكرر، فهذا ما اخترعت الحواسيب للقيام به، أم أنت فركز على ما هو أهم، التفكيير في كيف تختصر الكود :v

أحد المشاكل التي يوجهها المزارعين هي معرفة الموعد المناسب للسقي، مع تغير المناخ و اختلاف حاجيات النبات من وقت لآخر قد لا تكون معرفة الوقت المناسب للسقي مهمة سهلة، حتى لو تفقدت التربة، قد تبدو جافة من على السطح، بينما هي رطبة في الجوف، و لا تحتاج للسقي، لكن باستعمال مستشعر يقيس رطوبة التربة، يمكن معرفة مدى رطوبة التربة أو جفافها، و من ثم برمجة لوحة أردوينو لإرسال إنذار صوتي كلما وصلت التربة لدرجة معينة من الجفاف.

ما الذي ستحتاجه لهذا المشروع:

- لوحة أردوينو (Arduino board): هي اللوحة التي سنقوم ببرمجتها للقيام بكل شيء، أي لوحة أردوينو ستفي بالغرض لا يوجد أي فرق تقريبا.
- خمسة مصابيح  LED (اسمها الفعلي هو صمام ثنائي باعث للضوء)
- buzzer المسؤول عن إن إطلاق الصوت.
- لوحة الخبز Breadboard + أسلاك للتوصيل ( اسمها الفعلي لوحة التجارب)

ما هي الفكرة ؟

مستشعر الرطوبة، يقوم بإرجاع قيمة من 0 إلى 5 فولت، 0 تعني أن التربة رطبة جدا و 5 تعني ان التربة جافة جدا، و حسب هذه القيمة نقوم بتشغيل المصابيح الخمسة، مثلا:
- إذا كانت القيمة ما بين 0 و 1 نقوم بتشغيل مصباح واحد
- إذا كانت القيمة ما بين 1 و 2 نقوم بتشغيل مصباحين.
- إذا كانت القيمة ما بين 4 و 5 نقوم بتشغيل المصابيح الخمسة بالإضافة إلى الإنذار الصوتي.
لفهم الأمور بشكل جيد، سنعمل كل جزء على حدة، ثم نجمع الأجزاء تدريجيا، هكذا ستكون فكرة واضحة على كيفية عمل جميع القطع و كل جزء من الكود، على أي حال إن لم تكن مهتما بهذا، ستجد الكود كاملا و طريقة التركيب في الأسفل.

الجزء الأول: مستشعر الرطوبة.

توجد أنواع عديدة من المستشعرات، إلا أن أغلبها تعمل بنفس المبدأ، مهما كان النوع الذي لديك، سنستعمل فقط ثلاث مرابط، مربطين للطاقة VCC و GND، و المربط الثالث A0 أو Sig، إذا كان لديك مربط رابع فقط تجاهله.
كيفية ربط مستشعر الرطوبة Moisture sensor مع أردوينو
نمر الآن لكتابة الكود، أولا نقوم بما هو اعتيادي من تعريف للمتغيرات، ثم قراءة قيمة المستشعر عبر دالة ()analogRead و طباعة قيمتها عن طريق ()Serial.println
int sensor = A0;
    
void setup() {
// put your setup code here, to run once:
pinMode(sensor, INPUT);
serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
sensorValue = analogRead(sensor);
Serial.print("sensor value is: ");
Serial.println(sensorValue)
}
الآن بعد رفع الكود و تشغيل Serial monitor (ستجدها في الأعلى على اليمين)، نلاحظ أن قيم المستشعر تصل إلى 1024، و هذا غير منطقي كون أن المستشعر يرجع قيمة من 0 حتى 5V، السبب في هذا هو أن دالة ()AnalogRead تعبر عن قيمة المستشعر بعدد أكبر بحيث أن 5 فولت تصبح 1024.
تحديث: أغفلت شيئا مهما هنا، فنتخلص من هاتها الفقرة.
لكن نحتاج في هذا المشروع إلى أعداد أصغر من 0 حتى 5، لذلك سنقوم بقسمة قيمة المستشعر على 204، سنحصل على أعداد بها فاصلة مثل 4.6 أو 2.3، للتخلص من الفاصلة و تحويل هاته القيم إلى قيم أعداد صحيحة طبيعية (دون فاصلة)، سنستعمل دالة 
()float

نحتاج في مشروعنا هذا أعداد أصغر من 0 حتى 5 فقط، لذلك سنقوم بقسمة قيمة المستشعر على 204، لكن يجب الانتباه إلى أن خارج القسمة هو عدد صحيح طبيعي دون فاصلة، لماذا ؟؟حسنا بما أننا قسمنا عدد صحيح طبيعي على عدد صحيح طبيعي فالخارج يكون عدد صحيح طبيعي أيضا.
int sensor = A0;
    
void setup() {
// put your setup code here, to run once:
pinMode(sensor, INPUT);
serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
SensorValue = analogRead(sensor)/204
Serial.print("sensor value is: ");
Serial.println(sensorValue)
}
هكذا نكون أنهينا أول جزء، و حصلنا على قيمة المستشعر التي سنقوم بناء عليها بتشغيل مصابيح LED، القيم الآن ستكون محصورة بين 0 و 5، لكن دون فاصلة، إذن ستكون إما 0 أو 1 أو 2 أو 3 أو  4 غالبا لن تصل إلى 5.

الجزء الثاني: تشغيل مصابيح LED

نقوم الآن بإضافة المصابيح و buzzer  إلى التركيب، سنستعمل pins من 2 إلى 7
ما ستفكر فيه الآن و ما فكرت فيه أنا أيضا هو استعمال if else، نتيجة هذا ستكون كود به 16 سطرا، لكن يمكننا القيام بنفس الشيء و بعدد أسطر أقل بكثير باستعمال for loop، الكود التالي يجب إضافته إلى دالة ()void setup حيث تقوم بتعريف جميع المنافذ من 1 إلى 7 على أنها OUTPUT.
for(int i = 2; i <= 7; i++){
pinMode(i, OUTPUT);
};
ثم الكود التالي يجب إضافته إلى ()void loop، سيقوم بتشغيل المصابيح من 2 حتى 6 حسب قيمة المستشعر sensorValue، فمثلا إذا كان قيمة sensorValue = 0 تقوم بتشغيل مصباح واحد في المنفذ 2، و إذا كانت قيمة sensorValue = 4 تقوم بالتشغيل المصابيح من المنفذ 2 حتى المنفذ رقم 6

for(int j = 2; j <=(sensorValue + 2)); j++){
  digitalWrite(j, HIGH);
}
الآن قم برفع الكود إلى أردوينو و اضغط على Serial monitor، من المفترض أن تشتغل المصابيح كلها بما أن قيمة المستشعر مرتفعة، ضع المستعشر في كأس ماء، و لاحظ أن قيمة المستشعر تنخفض، من المفترض أن يشتغل عدد أقل من المصابيح، بما أن قيمة المستشعر انخفضت، لكن هذا لن يحصل !! لماذا ؟
عندما تقوم الأردوينو بتشغيل المصابيح لأول مرة، ستبقى مشتغلة، ثم تقوم أردوينو بقياس قيمة المستشعر لثاني مرة، ستجد الأردوينو أن المصابيح تم تشغيلها من قبل، و بالتالي ستقوم بتشغيلها مرة أخرى، ما يجب أن نقوم به إذن هو بعد كل عملية قياس و تشغيل للمصابيح ننتظر مدة زمنية ثم نقوم بإطفاء المصابيح، نضيف الكود التالي:
delay(1000);
for(int i = 2; i <= 6; i++){
  digitalWrite(i, LOW);
}
لاحظ أنه بدون التاخير الزمني delay ستقوم أردوينو بتشغيل المصابيح و إطفائها على الفور، لذا ستشتغل المصابيح و لكن بإضاءة خافتة، التأخير يعطي المصابيح مهلة كافية حتى تشتغل ثم يقوم بإطفائها. ثم يقوم فورا بتشغيلها مجددا لذلك لن تلاحظ أنها انطفأت إطلاقا.
من المفترض أن المصابيح تعمل الآن بشكل ممتاز، لنمر الآن لتشغيل buzzer.

الجزء الثالث: تشغيل buzzer

تشغيل buzzer ليس بتلك الصعوبة، سنستعمل if else، بحيث يشتغل buzzer فقط عند وصول قيمة المستشعر إلى أعلى قيمة هي 4، بما أنها ستحتوي على تأخير أيضا (delay(1000، فسنحذف التأخير الذي وضعناه سابقا و نضيفه إلى else بحيث يشتغل هذا التأخير فقط إذا لم يتشغل buzzer.
طبعا سنقوم بهذا قبل عملية إطفاء المصابيح، لا يعقل أن تنطفئ المصابيح ثم يشتغل buzzer.
و الكود النهائي سيكون على هذا الشكل، مع بعض الإضافات البسيطة، أتمنى أن أكون قد توفقت في الشرح، إذا كان لديك أي سؤال ضعه في تعليق و لن أتردد في إجابتك :)
int sensor = A0;
int sensorValue;
int alert = 7;

void setup() {
  // put your setup code here, to run once:
pinMode(sensor, INPUT);
Serial.begin(9600);
for(int i = 2; i <= 7; i++){
  pinMode(i, OUTPUT);
}
}

void loop() {
  // put your main code here, to run repeatedly:
sensorValue = float(analogRead(sensor) / 204);
Serial.print("sensor val is: ");
Serial.println(sensorValue);

for(int j = 2; j <= (sensorValue+2); j++){
  digitalWrite(j, HIGH);
}

if (sensorValue == 4){
  Serial.println("give me water plzz");
  digitalWrite(alert, HIGH);
  delay(500);
  digitalWrite(alert, LOW);
  delay(500);
} else {
  Serial.println("i'm good");
  delay(1000);
}
Serial.println("----------------------------");
for(int i = 2; i <= 7; i++){
  digitalWrite(i, LOW);
}
}

مقالات مشابهة

0 comments