اهلا بك

الكاتب

مرحبا بكم

البحث فى المدونه

اشترك ليصلك كل جديد

احصل على كل جديد فى عالم التدوين لحظه بلحظه اشترك الان

السبت، 28 فبراير 2015

الروبوت المستكشف للضوء

الروبوت المستكشف للضوء
00
بعدما قدمنا عدة روبوتات بسيطة يمكن البدء بها بدون برمجة ولا اليكترونيك صعبة
نستعرض في هذه المرة أول روبوت يمكن القول عنه أنه البداية الفعلية في صناعة روبوتات متقدمة شيئا ما
مستكشف الضوء هو مَركبة يمكنها التجوال بنفسها باحثة عن الضوء.


انتباه

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

إليك استعراضا للروبوت الباحث عن الضوء:
00.jpg









الأجزاء الرئيسية  
00.jpg






l         بطاريات فولط
l          بطاريتين أو بطاريات عادية للمحرك
l         مستشعرين للضوء من نوعCdS
l         ترنزستورين NPN
l         مقاومتين (1 كيلوأوم) (ستسعملان لأجل الترنزستورين)
l         لوحة Arduino الاليكترونية (سنستعمل في مثالنا هذا النوع Duemilinove لكن يمكنك أن تستعمل أيضا الانواع اﻷخرى كـUno و Diecimila و NG ….)
l         قاعدة الروبوت (سنتكلم عنها فيما يلي) 


قاعدة الروبوت

01
تم استعمال عجلات مسننة (أو قل مدببة). لكن ليس مهما استعمال هذا النوع من العجلات.اذ لم تكن متواجدة عندك فاحرى أن تحاول صنعها بنفسك أو تستبدلها بعجلات عادية وهذا هو اسهل.
لكن دعنا نفترض أنه بإمكانك الحصول عليها إما عن طريق شرائها من خلال الانترنت أو محلات الاليكترونيك في بلدك.
نقول هنا أنك تحتاج قاعدة مزودة بمحركين وعلبة الدوائر المسننة (gearboxوحاملة بطاريات وقاعدة.

من الاحسن إضافة طبقة أخرى على القاعدة الرئيسية للروبوت من أجل حمل لوحة Arduinoهذه الطبقة عبارة عن  خُشيبة أو قطعة بلاستيكية مربعة الشكل.

إذا افترضنا أنك ستستعمل هذا النموذج بحذافره فدعني أقول لك أنه تم شراء علبة الدوائر المسننة مصحوبة بمحركين DC.
  

تركيب مستشعرات الضوء

02
تعمل المستشعرات CdS على استكشاف درجة سطوع الضوء حيث تتغير مقاومتهما الداخلية اعتمادا على كمية الضوء المستقبَلةطريقة تركيب هذه المستشعرات تتمثل كالتالي:

يجب أن يوصل أحد مربطي كل مستشعر على حدى  بالمدخل الأرضي (GNDلبطاقة Arduino.
ويوصل الطرف الآخر بالمدخل التناظري (analog input pinللوحة Arduino.
  
 غير أنه يبقى للشخص أن يُعَرف pin كمدخل (أي INPUT ) باستعمال الدالة pinMode ثم يستعمل الدالة digitalWire لتهيئة المدخل بالقيمةHIGH كالتالي:

void setup()
{
  pinMode("analog pin", INPUT);
  digitalWrite("analog pin", HIGH);
}

باستعمال هذه  الشيفرة يمكنك قراءة قيمة المقاومة المولدة من طرف كل مستشعر ضوئي واستعراضها على شاشة اليكترونيةهذا هو الجزء الاول من الروبوتسنناقش فيما يلي كيفية استعمال هذه القيم من أجل التحكم بالمحركات.

طريقة تركيب هذه المستشعرات تتمثل كالتالي:
طريقة التركيب سهلةجداقم فقط بإيصال مربط واحد لكل مستشعر بالارضية (ground pin). أما بالنسبة للمربطين المتبقين فيتم وصلهما بالمدخلين و للوحة Arduino أي (pin 1 وpin 2بحيث يكون pin 1 موصلا بالمستشعر ايمن بينما يوصل pin 2 بالمستشعر ايسر.

ملاحظة
يوجد ترنزستورات داخلية (في البطاقة Arduinoتسمى بترنزستورات (pullup transistors). مرابط البطاقة البرمجية (مداخل أو مخارجتطون مدعومة بهذا النوع من الترنستوراتسيتم التعامل معهم في شيفرة الروبوت بالفقرة التالية. 


برمجة مستشعرات الضوء

 03

// قم بنسخ هذه الشفرة انطلاقا من هذا السطر

/
***********************
شيفرة للتعامل مع المستشعرين
 Anuj 
تم انجازه من طرف
حقوق الطبع محفوظة
التركيب على أرض الواقع
Arduino 
مستشعرين متصلين بالأرضية والمدخل 1 (يساراوالمدخل 2 (يمينالبطاقة *******************************************************/
// Arduino Duemilinove استعمال لوحة

/**************************تعريف الثوابت***************************/
/* سيستعمل هذا المتغير لتنشيط أو إقفال عمل المحرك ايمنموصول بقاعدة الترنزستور */
const int RightMotor = 2;
/* سيستعمل هذا المتغير لتنشيط أو إقفال عمل المحرك ايمنموصول بقاعدة الترنزستور */
const int LeftMotor = 3;
const int RightSensor = 1;
 //سيستعمل هذا المتغير لقراءة قيمة المستشعر ايمن
const int LeftSensor = 2; //يستعمل هذا المتغير لقراءة قيمة المستشعر ايسر
تعريف المتغيرات//

int SensorLeft
// يستعمل للاحتفاظ بقيمة المستشعر ايسر للاستعمال فيما بعد
int SensorRight
// يستعمل للاحتفاظ بقيمة المستشعر ايمن للاستعمال فيما بعد
int SensorDifference
// يستعمل لاحتفاظ بالفارق بين قيمة اليمين واليسار

void setup()  
// ستنفذ هذه الدالة مرة واحدة فقط لتهيئة البطاقة البرمجية
{
/* سنعرف المتغير LeftSensor كـ "مدخل" ليتم القراءة من خلاله فيما بعد*/
  pinMode(LeftSensor, INPUT);
/* سنعرف المتغير RightSensor كـ "مدخلليتم القراءة من خلاله فيما بعد*/
  pinMode(RightSensor, INPUT);
/* تفعيل ترانزستور pull-up  داخلي*/
  digitalWrite(A1, HIGH);
/* تفعيل ترانزستور pull-up  داخلي ثاني*/
  digitalWrite(A2, HIGH);
/*  نعرف سرعة تحويل المعلومات*/
  Serial.begin(9600);
/* إظهار رسالةلا غير بعد تنفيذ هذه الدالة*/
  Serial.println(" \nReading Light sensors.");
}

void loop()    
// ستنفذ هذه الدالة إلى ما لانهاية حتى يتم ايقاف الروبوت
{
 SensorLeft = analogRead(LeftSensor);   //
       قراءة قيمة المستشعر ايسر والاحتفاظ بها
 delay(1);  //
    انتظار 1 ميكروثانية وهي مهمة لجعل البطاقة تأخذ أنفاسها بعدما تنفيذ امر السابق
 SensorRight = analogRead(RightSensor); //
 قراءة قيمة المستشعر ايمن والاحتفاظ بها
 delay(1); //
    انتظار ميكروثانية وهي مهمة لجعل البطاقة تأخذ أنفاسها بعدما تنفيذ امر السابق
 // لحساب القيمة المطلقة للفارق بين قيمة المستشعر ايمن وقيمة المسشعر ايسر
 
SensorDifference = abs(SensorRight – SensorLeft);

/**************************************************************
سيستعمل المقطع التالي من الشيفرة لإظهار بعض الجمل والقيم العددية للمتغيرات على الشاشة
أثناء البرمجة فقط لتتأكد من عمل هذه الشيفرة بشكل جيد لا غير.
هل تعرف ما يسمى هذا المقطع البسيط في عالم البرمجة؟
انه يسمى debugging
****************/

 Serial.print("Left Sensor = ");              //   لإظهار الجملة بين اشارتي الاقتباس
 Serial.print(SensorLeft);                      //
              لإظهار قيمة المتغير
 Serial.print("\t");                                 //
                         إظهار فراغ متوسط
 Serial.print("Right Sensor = "); 
           //لإظهار الجملة بين اشارتي الاقتباس
 Serial.print(SensorRight);                    //
           لإظهار قيمة المتغير
 Serial.print("\t");                                 //
                       إظهار فراغ متوسط
 Serial.print("Sensor Difference = ");  
  //لإظهار الجملة بين اشارتي الاقتباس
 Serial.print(SensorDifference);            //
           لإظهار قيمة المتغير
 Serial.print("\n");                                //
                                 للرجوع الى السطر
}

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

بالنسبة لي شخصيا، أحب أن ترجع الدالة analogRead القيمة كأدنى قيمة عندما يكون الضوء مظلما، والقيمة 1023كأقصى قيمة عندما يكون الضوء ساطعا.
بهذا، سيسهل علي التعامل مع قيم عددية محصورة في مجال معين وبالتالي أسهل علي تحريك الروبوت فيما بعد بدون جهد أو تكلف.
لن أحتاج هنا لتعديل شيئا ما في الدارة الكهربائية  بل فقط بعض التعديلات الطفيفة على الشيفرة.

سنغير المقطع التالي فقط في الشيفرة:

SensorLeft = analogRead(LeftSensor);
delay(1);
SensorRight = analogRead(RightSensor);
delay(1);

قم بتغييره كالتالي:

SensorLeft = 1023 - analogRead(LeftSensor);
delay(1);
SensorRight = 1023 - analogRead(RightSensor);
delay(1);

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

تحليل واستفسار
كما ترى أن لنا ثلاث قيم متغيرات أساسية في برنامجنا هذاقيمة المستشعر ايمن و قيمة المستشعر ايسر وقيمة الفارق بينهمافكيف يا ترى يمكننا التعامل مع هذه القيم للتحكم بحركة محركات الروبوت؟؟؟؟

جواب واستبشار
الطريقة بسيطة فابشر:
إذا كان الفارق بينهما أصغر من عتبة محددة (قيمة عددية ثابتة) -->  على الروبوت أن يتجه أماما.
إذا كانت قيمة المستشعر ايمن أكبر من قيمة المستشعر ايسر -->  على الروبوت أن يتجه يمينا.
إذا كانت قيمة المستشعر ايسر أكبر من قيمة المستشعر ايمن -->  على الروبوت أن يتجه يسارا.

برمجيا
نترجم الكلام السابق كما يلي برمجيا:
if(SensorDifference <= 75)    // تم اعتبار 75 كعتبة عددية محددة
{  // اتجه أماما
}

else if (RightSensor > Left sensor)
{
 
 // اتجه يمينا
}

else if (LeftSensor > RightSensor)
{  // اتجه يسارا
}

لماذا تم اختيار 75 كعتبة محددة؟؟
الجواب، اذا لم تعجبك فاختر أي قيمة صغيرة كما تحب وارحنا من كثرة التفسير.

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


تركيب المحركات والبقية 
00.jpg





قم بتركيب جميع المركبات الاليكترونية كما هو مبين في الدارة الكهربائية البسيطة في الصورة أعلاه.

ستقوللم أفهم هذه الدارة الكهربائية جيدا؟؟؟
وسأقولوأنا مالي!!!! اجحظ عينيك وحملق فيها بقوة ولا تنفك حتى تفهمها ودعني أكمل الباقي.

آه، غيرت رأيي، سأشرح لك قليلا فلا تحزن:

تثبيت المقاومة (1 كيلوأوموالمحرك ايمن والترنستور المساعد له:
1.        قم بإيصال إحدى طرفي المقاومة بالمدخل للبطاقة Arduino (وهو المدخل الذي يمثل المحرك ايمن).
2.        ثم صل الطرف الآخر للمقاومة بأي ثقب في اللوحة البلاستيكية المثقبة.
3.        لإضافة الترنزستور، قم بتثبيت قاعدة الترنزستور في الثقب المجاور أي المحادي تماما لمربط المقاومة.
4.        بعدها قم بتثبيت جامع الترنزستور  بحيث يكون محاديا لمربط المحرك ايمن على اللوحة البلاستيكية.
5.        وسيبقى طرف واحد للترنستور والمسمى بالباعث فصله بارضية (أعني أحد مداخل البطاقة Arduino المرموز له بـ GND).
6.        صل طرف المتبقي للمحرك الأيمن بالقطب الموجب للبطارية.

تثبيت المقاومة (1 كيلوأوموالمحرك ايسر والترنستور المساعد له:
1.        قم بنفس العمل بالنسبة للمحرك ايسر بشرط أن تستعمل المدخل 3 (عوض 2) للبطاقة Arduino.
2.        لا تنسى أن تصل القطب السالب للبطارية بارضية (أعني مرة أخرى مدخل البطاقة Arduino المرموز له بـ GND). 


برمجة المحركات

04

ما زلت تتذكر أننا عرفنا متغييرين سميناهماRightMotor و LeftMotor، أليس كذلك؟؟؟
يجب أن تعرف أو تتذكر أنه لإرسال أوامر التحكم الى المركبات الاليكترونية نستعمل الدالة digitalWrite والتي يمكن استخدامها بإعطاءها قيميتنرقم المدخل الموصول به المركب الاليكتروني و الحالة التي نريد بها أن يتصرف المركب الاليكتروني.

في حالتنا هذه:
المركب الاليكتروني هوالمحرك.
والحالة هي:إما HIGH أي مشتغل أو LOW أي منطفئ.

هاكم ان توجيه المحركات برمجيا:

if(SensorDifference <= 75)  // اتجه أماما
{
digitalWrite(RightMotor, HIGH);
digitalWrite(LeftMotor, HIGH);
}
else if (RightSensor > Left sensor)  
 // اتجه يمينا
{
digitalWrite(RightMotor, LOW);
digitalWrite(LeftMotor, HIGH);
}
else if (LeftSensor > RightSensor
  // اتجه يسارا
{digitalWrite(RightMotor, HIGH);
digitalWrite(LeftMotor, LOW);
}


الشيفرة الكاملة

حسنا، وصلنا الى الحلقة اخيرةإذا تم وفهمت ما تم شرحه أعلاه فهاهي الشيفرة كاملة وما عليك إلا أن تنسخها عندك وامتحن روبوتك: 

// قم بنسخ هذه الشفرة انطلاقا من هذا السطر

/********************
شيفرة للتعامل مع المستشعرين
 Anuj 
تم انجازه من طرف
تعديل الشيفرة: محمد السهلي
حقوق الطبع محفوظة
التركيب على أرض الواقع
Arduino 
مستشعرين متصلين بالأرضية والمدخل 1 (يسارا) والمدخل 2 (يمينا) لبطاقة
********************************************************/

// Arduino Duemilinove استعمال لوحة
/*تعريف الثوابت*/
/* سيستعمل هذا المتغير لتنشيط أو إقفال عمل المحرك اﻷيمن. موصول بقاعدة الترنزستور */
const int RightMotor = 2;
/* سيستعمل هذا المتغير لتنشيط أو إقفال عمل المحرك اﻷيمن. موصول بقاعدة الترنزستور */
const int LeftMotor = 3;
const int RightSensor = 1;
 // سيستعمل هذا المتغير لقراءة قيمة المستشعر اﻷيمن
const int LeftSensor = 2;  
 //سيستعمل هذا المتغير لقراءة قيمة المستشعر اﻷيسر 
/*تعريف المتغيرات*/

int SensorLeft;             
// يستعمل للاحتفاظ بقيمة المستشعر اﻷيسر للاستعمال فيما بعد
int SensorRight;           
// يستعمل للاحتفاظ بقيمة المستشعر اﻷيمن للاستعمال فيما بعد
int SensorDifference;   
// يستعمل لاحتفاظ بالفارق بين قيمة اليمين واليسار

void setup()  
// ستنفذ هذه الدالة مرة واحدة فقط لتهيئة البطاقة البرمجية
{
/* سنعرف المتغير LeftSensor كـ "مدخل" ليتم القراءة من خلاله فيما بعد*/
  pinMode(LeftSensor, INPUT);
/* سنعرف المتغير RightSensor كـ "مدخل" ليتم القراءة من خلاله فيما بعد*/
  pinMode(RightSensor, INPUT);
/* تفعيل ترانزستور pull-up  داخلي*/
  digitalWrite(A1, HIGH);
/* تفعيل ترانزستور pull-up  داخلي ثاني*/
  digitalWrite(A2, HIGH);
/*  نعرف سرعة تحويل المعلومات*/
  Serial.begin(9600);
/* إظهار رسالة*/
  Serial.println(" \nReading Light sensors.");
}

void loop()    
// ستنفذ هذه الدالة إلى ما لانهاية حتى يتم ايقاف الروبوت
{
 SensorLeft = 1023 - analogRead(LeftSensor); 
// قراءة قيمة المستشعر اﻷيسر والاحتفاظ بها
 delay(1);     
// انتظار 1 جزء من الثانية وهي مهمة لجعل البطاقة تأخذ أنفاسها بعدما تنفيذ اﻷمر السابق
 SensorRight = 1023 - analogRead(RightSensor); 
// قراءة قيمة المستشعر اﻷيمن والاحتفاظ بها
 delay(1);     
// انتظار 1 جزء من الثانية وهي مهمة لجعل البطاقة تأخذ أنفاسها بعدما تنفيذ اﻷمر السابق
 // لحساب القيمة المطلقة للفارق بين قيمة المستشعر اﻷيمن وقيمة المسشعر اﻷيسر
 
SensorDifference = abs(SensorRight – SensorLeft);

/************************************************************
سيستعمل المقطع التالي من الشيفرة لإظهار بعض الجمل والقيم العددية للمتغيرات على الشاشة
أثناء البرمجة فقط لتتأكد من عمل هذه الشيفرة بشكل جيد لا غير.
هل تعرف ما يسمى هذا المقطع البسيط في عالم البرمجة؟
انه يسمى debugging
****************/

 Serial.print("Left Sensor = ");    // لإظهار الجملة بين اشارتي الاقتباس
 Serial.print(SensorLeft);             
// لإظهار قيمة المتغير
 Serial.print("\t");                         
// إظهار فراغ متوسط
 Serial.print("Right Sensor = "); 
 // لإظهار الجملة بين اشارتي الاقتباس
 Serial.print(SensorRight);           
// لإظهار قيمة المتغير
 Serial.print("\t");                         
// إظهار فراغ متوسط
 Serial.print("Sensor Difference = ");  
 // لإظهار الجملة بين اشارتي الاقتباس
 Serial.print(SensorDifference);             
// لإظهار قيمة المتغير
/**********************
هذا المقطع الرئيسي لتحرك الروبوت.
هنا نقوم بمعالجة وتحليل القيم وتوجيه الروبوت من خلالها
**************************************/

 if(SensorDifference <= 75)  // اتجه أماما
 {
 digitalWrite(RightMotor, HIGH);
 digitalWrite(LeftMotor, HIGH);
 Serial.print(“Forward”);  // فقط لإظهار رسالة مفادها أنه يتجه أماما
 }
 else if (RightSensor > Left sensor)  
 // اتجه يمينا
 {
 digitalWrite(RightMotor, LOW);
 digitalWrite(LeftMotor, HIGH);
 Serial.print(“Right”);  // فقط لإظهار رسالة مفادها أنه يتجه يمينا
 }
 else if (LeftSensor > RightSensor
  // اتجه يسارا
 {
 
digitalWrite(RightMotor, HIGH);
 digitalWrite(LeftMotor, LOW);
 Serial.print(“Left”);  // فقط لإظهار رسالة مفادها أنه يتجه يسارا
 }
 Serial.print("\n"); // للرجوع الى السطر
}

التعليقات
0 التعليقات

0 التعليقات:

إضغط هنا لإضافة تعليق

إرسال تعليق

Blogger Widgets