image_pdfimage_print

نظام مسح الفضاء المحيط

في هذا المشروع سنتعلم كيفية استخدام حساس الموجات الفوق صوتية (Ultrasonic) مع الأردوينو في عمل مسح للفضاء المحيط

استخدام DS3231 RTC Module مع الاردوينو

سنتعلم في هذا المشروع كيفية إستخدام وحدة RTC “Real Time Clock” وعرض التوقيت على شاشة LCD

استخدام-ds3231-rtc-module-مع-الاردوينو

المكونات المطلوبة

arduino uno r3

Arduino Uno

 

rtc ds3231

RTC – Real Time Clock

 

2×16 LCD

Push Buttons

potentiometer 10k

Potentiometer 10K Ω

10k Ohm Resistors

Full size breadboard 830

Breadboard

Breadboard Jumper Wire 65 pcs

Wires

الشاشة LCD

تعمل الشاشة في أحد الحالات التالية:

1- ان تستقبل امر من الارودوينو و تقوم بتنفيذة مثلا: امر مسح الشاشة و امر التهيئة 

lcd.begin(16,2);
lcd.clear();

2- ان تستقبل معلومات من الاردوينو و تقوم بعرضها مثلا : كتابة جملة معينة  

lcd.print("Hello");

استخدام-ds3231-rtc-module-مع-الاردوينو

DS3231 RTC Module

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

استخدام-ds3231-rtc-module-مع-الاردوينو

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

استخدام-ds3231-rtc-module-مع-الاردوينو

 

توصيل الدارة

قم بتوصيل الدارة كما هو موضح بالصورة التالية :

استخدام-ds3231-rtc-module-مع-الاردوينو

توصيل وحدة DS3231 RTC :

RTC ModuleArduino
5vVcc
GNDGnd
SCLA5
SDAA4

تقوم وحدة الRTC بحساب التوقيت و ارساله الى الاردوينو ليتم عرضه على شاشة LCD ، المفاتيح تستخدم لضبط التوقيت في البداية فقط.

استخدام-ds3231-rtc-module-مع-الاردوينو

البرمجة

قم بتنزيل الكود البرمجي كاملا من خلال الرابط هنـا .

شرح البرمجة :

حتى نتمكن من التواصل مع RTC Module بإستخدام الاردوينو، نحتاج الى إستخدام بروتوكول I2C و الذي تتيحه لنا المكتبة Wire.h.

لذلك في البداية نقوم بإدراج مكتبة Wire.h ، التي تحتوى على الدوال اللازمة للتواصل بين الاردوينو و الـ RTC Module .كما نقوم أيضا بإدراج مكتبة LiquidCrystal.h التي تحتوي على الدوال الخاصة بشاشة الـ LCD، و التي سيتم إستخدمها لعرض التوقيت.

#include <Wire.h>
#include <LiquidCrystal.h>

نقوم بعد ذلك بتسمية منافذ الأردوينو التي تم استخدامها في المشروع والخاصة بالـ Push Buttons.

#define ENTER A2
#define UP A1
#define DOWN A0

بعد ذلك قمنا بتحديد عنوان خاص بالRTC Module و هو 0x68 و قمنا بتعيين متغير له :

#define DS3231_I2C_ADDRESS 0x68

أي وحدة تستخدم برتوكول I2C تمتلك عنوان معين ليتمكن الاردوينو من التواصل معه. لان هذا البرتوكول يستطيع التواصل مع عدد كبير من الاجهزة على نفس الـProtocol Bus . لذلك كل واحد منها يمتلك عنوان معين ليستطيع الاردوينو التواصل معه بدون التأثير على باقي الاجهزة الموصلة على الـ Busـ

يتم الحصول على العنوان الخاص بكل موديول من الـ Datasheet  الخاصه به :

استخدام-ds3231-rtc-module-مع-الاردوينو

 

 ثم نقوم بإنشاء المتغير الخاص بشاشة الـ LCD، وتحديد الـ Pins الموصوله بينها وبين الأردوينو :

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

 ونقوم بالإعلان عن المتغيرات المستخدمه في تخزين حالة الـ Push Buttons، والتي ستيم استخدامها في البداية لضبط التوقيت فقط. كما نقوم أيضا بالإعلان عن متغيرات لحفظ التوقيت الذي سنقوم بضبطه مثل متغير SetM و SetH .

//variables for button states
int enterState = 0, enterStateLast = 0, upState = 0, upStateLast = 0, downState = 0, downStateLast = 0;

//variables for ui
boolean blinkOn = true; //visibility of ':' between hour and minutes
boolean setVisible = false; //visibility of the set time ui

//variables for new time
int setM = 0; //users new minute value
int setH = 0; //users new hour value

هذا الموديول يتعامل مع الارقام على النظامBinary Coded Decimal . أي اننا سوف نحتاج لضبط التوقيت في البداية إلى تحويل الأعداد من الصورة Decimal إلى الصورة BCD . لذلك نستخدم الدالة ()decToBcd.

//convert normal decimal numbers to binary coded decimals
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}

 وعند قراءة قيمة الوقت من الموديول نستخدم الدالة ()bcdToDec ، لتحويل التوقيت المرسل من الموديول من الصورة BCD الى الصورة Decimal ، لنتمكن من عرضها على الشاشة LCD.

//convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}

 

 الدالة ()setup نقوم بضبط الإعدادات اللازمة للمشروع، مثل تشغيل بروتوكول I2C و شاشةالـ  LCD و قمنا بضبط المفاتيح المستخدمة في ضبط التوقيت كمدخل.

//code that runs once at setup
void setup() {
  //start wire and lcd
  Wire.begin();
  lcd.begin(16,2); //(col, rows)

  //intialize buttons as inputs
  pinMode(ENTER, INPUT);
  pinMode(UP, INPUT);
  pinMode(DOWN, INPUT);
}

 الدالة ()loop نقوم بقراءة الـPush Buttons لضبط التوقيت في البداية ثم نقوم بالتواصل مع الـRTC Module و نعرض التوقيت على الشاشة LCD .

void loop() {
  checkButtons();
  printTime();
}

الدالة ()setRTCTime تقوم بإنشاء اتصال بين الأردوينو و الـ RTC Module بإستخدام مكتبة Wire.  وظيفة هذه الداله هو ضبط التوقيت الذي سنقوم بإدخاله بإستخدام الـ Push Buttons. في البداية تقوم بإرسال عنوان الجهاز الذي تريد الإتصال معه وفي حالتنا هنا هو RTC Module و الذي قمنا بتحديده في بداية الكود.

//set the time and date to the RTC
void setRTCTime(byte second, byte minute, byte hour, byte dayOfWeek, byte
                dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}

بعد ذلك تقوم بإرسال التوقيت الذي تم ضبطه مع ملاحظة أننا عندما نرسل البيانات الى الموديول نقوم بتحويلها الى الصورة BCD .

 Wire.write(decToBcd(minute));

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

الدالة ()readRTCTime تقوم بعمل إتصال مع الموديول و قراءة معلومات التوقيت منه.  وسيتم استخدامها في الحصول على التوقيت وعرضه.
وهي تعمل بنفس اسلوب الداله السابقة مع اختلاف اننا نقوم بقراءة البيانات من الموديول بدلا من إرسالها له، مع ملاحظة اننا في هذه الحاله نقوم بتحويلها من الصورة BCD الى الصورة Decimal .

//read the time and date from the RTC
void readRTCTime(byte *second, byte *minute, byte *hour, byte *dayOfWeek,
                 byte *dayOfMonth, byte *month, byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}

الدالة ()printTime تقوم بقراءة قيمة التوقيت من الموديول بإستخدام الدالة ()readRTCTime ثم تقوم بعرضها على الشاشة LCD مع اضافة كود مهمته عرض التوقيت على الصورة  HH : MM .

//reads the RTC time and prints it to the top of the LCD
void printTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  
  //retrieve time
  readRTCTime(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  
  //print to lcd top
  lcd.setCursor(0,0);
  lcd.print(" Current: ");
  if (hour<10)
  {
    lcd.print("0");
  }
  lcd.print(hour, DEC);
  if (blinkOn == true)
  {
    lcd.print(" ");
    blinkOn = false;
  }
  else if (blinkOn == false)
  {
    lcd.print(":");
    blinkOn = true;
  }
  if (minute<10)
  {
    lcd.print("0");
  }
  lcd.print(minute, DEC);
  
  delay(100);
}

الجزء السابق مختص بقراءة قيمة التوقيت الذي يقوم الRTC Module بحسابه بدون تدخل من المستخدم . الجزء التالي من الكود مختص بقراءة حالة المفاتيح لضبط التوقيت و ارسالة الى الRTC Module.

الدالة ()checkButtons تقوم بقراءة حالة المفاتيح و التي تعمل كالتالي :

المفتاح المسمى UP يقوم بزيادة عداد الدقائق والساعات.
المفتاح المسمى DOWN يقوم بإنقاص عداد الدقائق والساعات.
المفتاح المسمى ENTER يقوم بتطبيق التوقيت الذي تم ضبطه وإرساله الى الـRTC Module.

//checks if buttons are pressed and responds accordingly
void checkButtons()
{
  //check enter
  enterState = digitalRead(ENTER);
  if (enterState != enterStateLast)
  {
    if (enterState == HIGH)
    {
      if (setVisible == true)
      {
        byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
        readRTCTime(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
        
        setRTCTime(0, setM, setH, dayOfWeek, dayOfMonth, month, year);
      }
      else if (setVisible == false)
      {
        showSet();
      }
    }
  }
  enterStateLast = enterState;
  
  //check up
  upState = digitalRead(UP);
  if (upState != upStateLast)
  {
    if (upState == HIGH)
    {
      if (setVisible == true)
      {
        addMin();
        printSetTime();
      }
      else if (setVisible == false)
      {
        showSet();
      }
    }
  }
  upStateLast = upState;

  //check down
  downState = digitalRead(DOWN);
  if (downState != downStateLast)
  {
    if (downState == HIGH)
    {
      if (setVisible == true)
      {
        subMin();
        printSetTime();
      }
      else if (setVisible == false)
      {
        showSet();
      }
    }
  }
  downStateLast = downState;
}

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

//displays the new time interface in the bottom of the LCD
void showSet ()
{
  //update new time variables to current RTC values
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  readRTCTime(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
    setH = hour, DEC;
    setM = minute, DEC;

  //pints to the LCD
  lcd.setCursor(0,1);
  lcd.print("   New: ");
  printSetTime();
  setVisible = true;
}

الدالة ()printSetTime تستخدمها الدالة ()showSet لعرض التوقيت الذي تم ضبطه في اسفل الشاشة LCD .

//prints the new time values on the bottom of the LCD
void printSetTime()
{
 lcd.setCursor(8,1); 
 if (setH<10)
  {
    lcd.print("0");
  }
  lcd.print(setH);
  lcd.print(":");
  if (setM<10)
  {
    lcd.print("0");
  }
  lcd.print(setM); 
}

الدوال التالية مستخدمة في الجزء السابق من الكود وهي تقوم بضبط المتغيرات التي تستخدم في تخزين قيم الدقائق والساعه التي يقوم المستخدم بضبطها بواسطة الPush Buttons .

الدالة ()addMin تقوم بزياد عداد الدقائق عند الضغط على المفتاح UP و تقوم أيضا بعمل اختبار لعداد الدقائق فإذا وصل العدد الى 59 تقوم بزيادة عداد الساعات .

//adds a minute to new time
void addMin()
{
  if (setM < 59)
  {
    setM++;
  }
  else if (setM == 59)
  {
    setM = 0;
    addHr();
  }
}

الدالة ()subMin تعمل عكس عمل الدالة السابقة وهي تقوم بإنقاص عداد الدقائق عند الضغط على المفتاح DOWN وتقوم أيضا باختبار عداد الدقائق فإذا وصل الى 0 تقوم بإنقاص عداد الساعات.

//subtracts a minute from new time
void subMin()
{
  if (setM > 0)
  {
    setM--;
  }
  else if (setM == 0)
  {
    setM = 59;
    subHr();
  }
}

الدالة ()addHr نقوم بإستدعائها الدالة ()addMin عندما يصل عداد الدقائق الى 59 لتقوم بزيادة عداد الساعات بمقدار واحد.

//adds an hour to new time
void addHr ()
{
  if (setH < 23)
  {
    setH++;
  }
  else if (setH == 23)
  {
    setH = 0;
  }
}

الدالة ()subHr تقوم باستدعائها الدالة ()subMin عندما يصل عداد الدقائق الى 0 لتقوم بإنقاص عداد الساعات بمقدار واحد.

//subtracts an hour from new time
void subHr ()
{
  if (setH > 0)
  {
    setH--;
  }
  else if (setH == 0)
  {
    setH = 23;
  }
}

التحكم في مصفوفة ليدات (LED Matrix)

في هذا المشروع سنتعلم كيف يمكننا التحكم في تشغيل مصفوفة الليدات LED Matrix بإستخدام الاردوينو ولتقليل عدد المخارج المستخدمة سيتم إستخدام الدارة المتكاملة MAX7219 .

 

المكونات المطلوبة

 

arduino uno r3

Arduino Uno

 

8×8 LED Matrix

 

MAX7219

Potentiometer 10K Ω

Full size breadboard 830

Breadboard

Breadboard Jumper Wire 65 pcs

Wires

مصفوفة الليدات LED Matrix :

هي عبارة عن 64 LEDs موصلين معا على شكل مصفوفة مكونة من صفوف وأعمدة.

كل عامود يتصل بالـ cathode الخاص بمجموعة الـ LEDs لهذا العامود، وكل صف يتصل بالـ Anode الخاص بمجموعة الـ LEDs لهذا الصف.

كي نقوم بتشغيل LED معين، نضع الجهد الموجب على الصف الموجود به الـ LED والجهد السالب على العامود الموجود به. كما هو موضح بالصورة التالية: عند وضع جهد موجب على الصف A وأرضي على العامود 2 تعمل الـ LED رقم L2 وهكذا.

التحكم فى مصفوفة ليدات Led Matrix باستخدام الاردوينو

الهدف من توصيلها بهذا الشكل هو توفير عدد المخارج المطلوبة من الاردوينو لتشغيل الـ64 ليد.فإذا كانت موصله بشكل غير المصفوفة فسنحتاج إلى 64 مخرج من الأردوينو لتشغيل 64 LEDs . أما عند توصيلها على شكل مصفوفة فإن عدد المخارج المطلوبة يقل ليصبح 16 مخرج فقط.

التحكم فى مصفوفة ليدات Led Matrix باستخدام الاردوينو

كي نتمكن من توصيل مصفوفة الليد (LED Matrix)، نحتاج إلى معرفة اين مواقع الصفوف والأعمدة، انظر الصورة أدناه :

التحكم فى مصفوفة ليدات Led Matrix باستخدام الاردوينو

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

التحكم فى مصفوفة ليدات Led Matrix باستخدام الاردوينو

MAX7219 :

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

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

توصيلها :

توصيلها مع الاردوينو و الLED Matrix من الداتا شيت

led-matrix

الجدول التالي يوضح كيفية التوصيل مع الأردوينو :

MAX7219التوصيل
اى رجل تسمى SEGمع الصفوف
اى رجل تسمى DIGمع الاعمدة
24Not Connected
19Vcc
1810K Ohm to VCC
13Arduino Pin 9
12Arduino Pin 10
9Ground
4Ground
1Arduino Pin 8

الجدول أعلاه يوضح أن الأرجل ذو الإسم SEG توصل مع الصفوف، والأرجل ذو الإسم DIG يتم توصيلها مع الأعمدة. على سبيل المثال: SEG A يتم توصيلها مع الصف الأول و SEG B يتم توصيلها مع الصف الثاني، وهكذا. اما DIG0 يتم توصيلها مع العامود الأول، و DIG1 يتم توصيلها مع العامود الثاني وهكذا.. .

لاحظ:

بداية الاعمدة فى الدارة MAX7219 من DIG 0. لذلك اول عمود يتصل مع DIG 0 و ليس DIG 1

توصيل الدارة

قم بتوصيل الدارة كما هو موضح بالصورة التالية :

التحكم فى مصفوفة ليدات Led Matrix باستخدام الاردوينو

 

يقوم البرنامج بقراءة قيمة مقاومة متغيرة و على حسب القيمة يقوم برسم شكل وجه مبتسم على الLED Matrix

التحكم فى مصفوفة ليدات Led Matrix باستخدام الاردوينو

البرمجة :

يعتمد الكود على بعض المكتبات التى نحتاج الى اضافتها الى Arduino IDE يمكنك تحميلها من هنا

#include <binary.h>
#include <Sprite.h>
#include <Matrix.h>

#define POT 0 

Matrix Leds = Matrix(8, 9, 10);

Sprite smile[3] = {
  Sprite(8, 8,  B01000000, B01000110, B01000110, B01000000, B01000000, B01000110, B01000110, B01000000),
  Sprite(8, 8,  B00100000, B01000110, B01000110, B01000000, B01000000, B01000110, B01000110, B00100000),
  Sprite(8, 8,  B00010000, B00100110, B01000110, B01000000, B01000000, B01000110, B00100110, B00010000)
};

void setup() {
  Leds.clear(); // turn off all diodes
}

void loop() {
  
  int pot = analogRead(POT); 
  pot = min(2, map(potData, 0, 1023, 0, 3)); // which smile
  
  // display face
  Leds.write(0, 0, smile[pot]);

}

شرح الكود :

في البداية نقوم بإدراج المكتبات التي نحتاجها في المشروع. وهم عبارة عن مكتبات للتعامل مع الـ LED Matrix والدارة MAX7219 :

#include <binary.h>
#include <Sprite.h>
#include <Matrix.h>

نقوم بتسمية منافذ الأردوينو التي سنقوم بتوصيلها مع المقاومة المتغيرة :

#define POT 0

ثم نقوم بإنشاء متغير مسؤول عن الـ LED Matrix .  و يتم تعريف الارجل التي يتم توصيلها بين الاردوينو و الدارة MAX7219 في هذا المتغير

Matrix Leds = Matrix(8, 9, 10);

بعد ذلك نقوم بإنشاء متغير يحتوي على تفاصيل الأشكال التي سنقوم برسمها على الـ LED Matrix . في هذا المشروع سنقوم بعمل ثلاث أشكال وهي لوجه مبتسم بدرجة تتناسب مع قيمة المقاومة المتغيرة. يتغير الوجه بين ثلاث حالات ، لذلك المتغير الذي سنقوم بإنشاءه هو عبارة عن مصفوفة ذو ثلاث صفوف.
كل صف عبارة عن متغير يحتوي على عدد الصفوف والأعمدة للـ LED Matrix ، والشكل الذي يراد عمله بإستخدام الـ LEDs ممثل بعدد على الصورة الثنائية.

Sprite smile[3] = {
  Sprite(8, 8,  B01000000, B01000110, B01000110, B01000000, B01000000, B01000110, B01000110, B01000000),
  Sprite(8, 8,  B00100000, B01000110, B01000110, B01000000, B01000000, B01000110, B01000110, B00100000),
  Sprite(8, 8,  B00010000, B00100110, B01000110, B01000000, B01000000, B01000110, B00100110, B00010000)
};

فى الدالة ()setup نقوم بوضع الاعدادات اللازمة للمشروع مثل اطفاء جميع الليدات فى البداية .

void setup() {
  Leds.clear(); // turn off all diodes
}

و في الدالة ()loop نقوم بقراءة قيمة المقاومة المتغيرة و بإستخدام الدالة map نقوم بتحويل القيمة التي تمت قرائتها وتتراوح بين 0 الى 1023 الى رقم بين 0 الى 2
ونستخدم الرقم الناتج في تشغيل وعرض الشكل المقابل له في مصفوفة الأشكال على الـ LED Matrix

void loop() {
  
  int pot = analogRead(POT); 
  pot = min(2, map(potData, 0, 1023, 0, 3)); // which smile
  
  // display face
  Leds.write(0, 0, smile[pot]);

}

جهاز تنبيه لوصول رسائل بريد إلكتروني

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

Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

المكونات المطلوبة

arduino uno r3

Arduino Uno

serial port bluetooth module hc-06

Bluetooth Module HC-06

blue led 5mm

LED

220 Ω resistor

220 Ohm Resistor

 

Full size breadboard 830

Breadboard

Breadboard Jumper Wire 65 pcs

Wires

 

توصيل الدارة

قم بتوصيل الدارة كما هو موضح بالصورة التالية :

Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

قمنا بتوصيل وحدة البلوتوث كما هو موضح بالجدول أدناه :
موديول البلوتوثالاردوينو
VCC5 v
GNDGND
TXDRX (Pin 0)
RXDTX (Pin 1)

 

سنقوم بضبط البرمجيات اللازمة، بحيث يصدر تنبيه بإستخدام الـ LED عند وصول رسالة إلكترونية جديدة على البريد الإلكتروني. سيتم إضاءة الـ LED الموصوله بالاردوينو عند اصدار التنبيه.

Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

 

البرامج المطلوبة

نحتاج لتجهيز بعض البرمجيات كي يعمل منبة الرسائل الإلكترونية بشكل صحيح :

  1. Microsoft Outlook
  2. Script File “.vbs”
  3. Bluetooth
  4. Putty

Script File

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

مثلا بدلا من أن نضغط بأنفسنا مفتاح Enter يمكننا

x.sendkeys "{ENTER}"

عند تنفيذه سيحاكي مفتاح Enter كما لو ان أحد ما ضغط عليه.

 

لانشاء هذا الملف

  1. نفتح ملف جديد باستخدام برنامج Notepad
  2. اضف السطور التالية للملف، لاحظ الحروف يجب ان تكون بنفس الشكل
    set ghost = wscript.CreateObject("WScript.Shell")
    ghost.sendkeys "a"
    
  3. قم بحفظ الملف عن طريق :
    save as –> Email.vbs
    و تأكد من إختيار  Save as Type : All Files

Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

 

Microsoft Outlook

هنا سنقوم بضبط بعض الإعدادات بحيث عندما يصلنا رسالة إلكترونية جديدة يقوم برنامج Outlook بتنفيذ ملف الScript الذي قمنا بتجهيزه.

  1. قم بفتح برنامج Outlook بعدها قم بالضغط على ‘Rules’ ثم إختار ‘Manage Rules & Alerts’

    Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

  2. بعد ذلك إضغط على ‘New Rule’ تحت التوبيب في أعلى يسار النافذة

    Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

  3. اضغط ‘Apply on messages I receive’، بعد ذلك اضغط ‘Next’

    Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

  4. اختار ‘Where my name is in the To Box’، ثم اضغط ‘Next’

    Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

  5. اختار ‘Start application’،بعد ذلك في اسفل النافذة اضغط على كلمة ‘application’

    Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

  6. في النافذة الجديدة، قم بتغيير نوع الملفات من ‘(Executable Files (EXE’، الى ‘All files’.بعد ذلك اذهب الى المكان الموجود به الملف الذي قمنا بإنشاءة سابقا وقم باختياره، ‘Email.vbs’، ثم اضغط ‘Open’

    Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

  7. قم بإعطاء اسم ما لهذا الـRule ثم قم بالضغط على  ‘Finish’

    Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

  8. اضغط على  ‘Apply’ ثم  ‘Ok’

    Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

Bluetooth

سنحتاج لعمل إقتران لوحدة البلوتوث على الحاسوب من أجل إمكانية الإرسال و الإستقبال بين الأردوينو والحاسوب :

  1. قم بالتوجه الى Control Panel
  2. اضغط على ‘Hardware and Sound’
  3. تأكد من توصيل موديول البلوتوث بالاردوينو ثم قم بتوصيل الاردوينو الى جهاز الحاسوب ستلاحظ ان ضوء الليد على موديول البلوتوث يضىء و يطفىء بسرعه
  4. ثم بعد ذلك اختار ‘Add a Device’
  5. انتظر حتى يظهر موديول البلوتوث على الحاسوب بإسم ‘HC-06’ ثم اضغط عليه
  6. ستظهر نافذة أخرى تطلب ادخال كود مرور، قم بكتابة ‘1234’
  7. انتظر حتى تظهر رساله انه تم الاتصال

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

في أعلى النافذة ستجد ‘COM Ports’ قم بالضغط عليها و ستجد رقم فيOutgoing port تذكره جيدا

Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

ملاحظة

لمزيد من المعلومات عن وحدة البلوتوث وكيفية ضبطة، يرجى الإطلاع على مشروع نظام التحكم في الإضاءة عبر البلوتوث.

 

Putty

  1. أولا، قم بتنزيله من الرابط هنـا   Putty
  2. نقوم بفتحه من Putty.exe
  3. نختار Serial
  4. نقوم بتغير COM1 الى رقم الـPort الذي حصلنا عليه من خطوة البلوتوث
  5. نضغط Open
  6. سنرى شاشة سوداء مما يعنى اننا نجحنا في عمل إتصال مع البلوتوث

 

البرمجة :

#define LED 13

int state;

void setup() {
 Serial.begin(9600);
 pinMode(LED, OUTPUT);
}

void loop() {
 if (Serial.available() > 0) {
  state = Serial.read();
 }

 if (state == 'a') {
  digitalWrite(LED, HIGH);
 }
}

شرح الكود :

في البداية نقوم بتسمية منافذ الأردوينو التي تم استخدامها في المشروع. اي منفذ 13 الذي تم توصيل الـ LED عليه. ثم نقوم بالإعلان عن المتغيرات التي سنحتاج إليها.

متغير state لتسجيل القيمة المستقبلية عن طريق البلوتوث في حالة وصول رسالة جديدة.

#define LED 13

int state;

في الدالة ()setup، نقوم بضبط الإعدادات اللازمة. وهي تشغيل بروتوكول Serial المستخدم بواسطة البلوتوث، وتعيين الـ LED كمخرج.

void setup() {
 Serial.begin(9600);
 pinMode(LED, OUTPUT);
}

في الدالة ()loop، نقوم بقراءة الـ Serial وفي حال وصول قيمة جديدة، نقوم بمقارنتها بقيمة ‘a’ التي تم ضبطها سابقا في ملف الـ Script. إذا كانت القيمة التي تم إستقبالها هي ‘a’ أي انه تم وصول رسالة جديدة.

void loop() {
 if (Serial.available() > 0) {
  state = Serial.read();
 }

 if (state == 'a') {
  digitalWrite(LED, HIGH);
 }
}

ملخص للدارة كاملة

قمنا بضبط برنامج Outlook بحيث عندما تصل رسالة جديدة يقوم بفتح ملف الscript الذي قمنا بتسميته Email.vbs و الذي يحتوى على بعض الأوامر التي يقوم الحاسوب بتنفيذها .

يقوم بكتابة حرف ‘a’  على شاشة برنامج Putty الذي يقوم بإرسالها إلى البلوتوث فيستقبلها الأردوينو ويقوم الحاسوب بتشغيل الـ LED

ملاحظة هامة

لكي يعمل كل شيء بشكل صحيح يحب أن يكون برنامج Outlook مفتوح و ايضا برنامج Putty مفتوح و يكون التركيز على الشاشة السوداء لبرنامج Putty
اي أن يكون كما في الصورة

Email Alert: استخدام الاردوينو مع البلوتوث لعمل تنبية لرسائل البريد

استخدام شاشة Nokia 5110 مع الاردوينو

في هذا المشروع سنتعلم كيفية استخدام شاشة Nokia 5110 مع الأردوينو لعرض صور ثابتة ومتحركة، وأيضا عرض الكلمات التي يتم ارسالها عن طريق الحاسوب.

استخدام شاشة جرافيك مع الاردوينو (Nokia 5110)

 

المكونات المطلوبة

arduino uno r3

Arduino Uno

nokia screen 5110

Nokia Screen 5110

220 Ω resistor

220 Ohm Resistor

 

Full size breadboard 830

Breadboard

Breadboard Jumper Wire 65 pcs

Wires

Nokia Screen 5110

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

nokia screen 5110

كما يمكننها التحكم بها على مستوى الـ Pixels، اي انها تعطي مرونة عالية للكتابة أو الرسم عليها.

توصيلها مع الأردوينو :

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

توصيل الدارة

نقوم بتوصيل الشاشة بالاردوينو باستخدام برتوكول الـ SPI ، ثم نقوم بإرسال الاوامر والبيانات اللازمة لعرض الصور بالشكل الذي نريده عن طريق الاردوينو.

قم بتوصيل الدارة كما هو موضح بالصورة التالية :

استخدام شاشة جرافيك مع الاردوينو (Nokia 5110)

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

الطرف (بداية من اليسار)التوصيل
1Arduino Pin 6
2Arduino Pin 7
3Arduino Pin 5
4 Arduino Pin 11
5 Arduino Pin 13
6 3.3v
7 Arduino Pin 4
8 GND

سنقوم بعمل برنامج يقوم في البداية بتشغيل الصور الثابتة والمتحركة، ثم يتوقف على صورة معينة منتظرا ادخال المستخدم لرسالة ما من خلال الشاشة التسلسلية (Serial Monitor)، ليقوم بعرضها على الشاشة.

استخدام شاشة جرافيك مع الاردوينو (Nokia 5110)

البرمجة

في البداية، نقوم بإدراج المكتبة الخاصة بالـ SPI حتى نتمكن من استخدامه :

#include <SPI.h>

ثم نقوم بتسمية بعض الثوابت المستخدمة في إرسال الأوامر إلى الشاشة :

#define LCD_COMMAND  0 
#define LCD_DATA     1
#define LCD_WIDTH   84 
#define LCD_HEIGHT  48 
#define WHITE       0 
#define BLACK       1 

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

const int scePin = 7;   // SCE - Chip select, pin 3 on LCD.
const int rstPin = 6;   // RST - Reset, pin 4 on LCD.
const int dcPin = 5;    // DC - Data/Command, pin 5 on LCD.
const int sdinPin = 11;  // DN(MOSI) - Serial data, pin 6 on LCD.
const int sclkPin = 13;  // SCLK - Serial clock, pin 7 on LCD.
const int blPin = 9;    // LED - Backlight LED, pin 8 on LCD.

بعد ذلك قمنا بعمل مصفوفة تحتوي على قيم الحروف والرموز والأرقام الممثلة بصيغة الـ ASCII ، وهي طريقة قياسية لتمثيل الحروف والأقام وبعض الرموز. فعند عرض الحرف a فإن القيمة المكافئة له تساوي 0x16 وهكذا.

static const byte ASCII[][5] = {
   {0x00, 0x00, 0x00, 0x00, 0x00} // 0x20  
  ,{0x00, 0x00, 0x5f, 0x00, 0x00} // 0x21 !
  ,{0x00, 0x07, 0x00, 0x07, 0x00} // 0x22 "
  ,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 0x23 #
  ,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 0x24 $
  ,{0x23, 0x13, 0x08, 0x64, 0x62} // 0x25 %
  ,{0x36, 0x49, 0x55, 0x22, 0x50} // 0x26 &
  ,{0x00, 0x05, 0x03, 0x00, 0x00} // 0x27 '
  ,{0x00, 0x1c, 0x22, 0x41, 0x00} // 0x28 (
  ,{0x00, 0x41, 0x22, 0x1c, 0x00} // 0x29 )
  ,{0x14, 0x08, 0x3e, 0x08, 0x14} // 0x2a *
  ,{0x08, 0x08, 0x3e, 0x08, 0x08} // 0x2b +
  ,{0x00, 0x50, 0x30, 0x00, 0x00} // 0x2c ,
  ,{0x08, 0x08, 0x08, 0x08, 0x08} // 0x2d -
  ,{0x00, 0x60, 0x60, 0x00, 0x00} // 0x2e .
  ,{0x20, 0x10, 0x08, 0x04, 0x02} // 0x2f /
  ,{0x3e, 0x51, 0x49, 0x45, 0x3e} // 0x30 0
  ,{0x00, 0x42, 0x7f, 0x40, 0x00} // 0x31 1
  ,{0x42, 0x61, 0x51, 0x49, 0x46} // 0x32 2
  ,{0x21, 0x41, 0x45, 0x4b, 0x31} // 0x33 3
  ,{0x18, 0x14, 0x12, 0x7f, 0x10} // 0x34 4
  ,{0x27, 0x45, 0x45, 0x45, 0x39} // 0x35 5
  ,{0x3c, 0x4a, 0x49, 0x49, 0x30} // 0x36 6
  ,{0x01, 0x71, 0x09, 0x05, 0x03} // 0x37 7
  ,{0x36, 0x49, 0x49, 0x49, 0x36} // 0x38 8
  ,{0x06, 0x49, 0x49, 0x29, 0x1e} // 0x39 9
  ,{0x00, 0x36, 0x36, 0x00, 0x00} // 0x3a :
  ,{0x00, 0x56, 0x36, 0x00, 0x00} // 0x3b ;
  ,{0x08, 0x14, 0x22, 0x41, 0x00} // 0x3c 
  ,{0x02, 0x01, 0x51, 0x09, 0x06} // 0x3f ?
  ,{0x32, 0x49, 0x79, 0x41, 0x3e} // 0x40 @
  ,{0x7e, 0x11, 0x11, 0x11, 0x7e} // 0x41 A
  ,{0x7f, 0x49, 0x49, 0x49, 0x36} // 0x42 B
  ,{0x3e, 0x41, 0x41, 0x41, 0x22} // 0x43 C
  ,{0x7f, 0x41, 0x41, 0x22, 0x1c} // 0x44 D
  ,{0x7f, 0x49, 0x49, 0x49, 0x41} // 0x45 E
  ,{0x7f, 0x09, 0x09, 0x09, 0x01} // 0x46 F
  ,{0x3e, 0x41, 0x49, 0x49, 0x7a} // 0x47 G
  ,{0x7f, 0x08, 0x08, 0x08, 0x7f} // 0x48 H
  ,{0x00, 0x41, 0x7f, 0x41, 0x00} // 0x49 I
  ,{0x20, 0x40, 0x41, 0x3f, 0x01} // 0x4a J
  ,{0x7f, 0x08, 0x14, 0x22, 0x41} // 0x4b K
  ,{0x7f, 0x40, 0x40, 0x40, 0x40} // 0x4c L
  ,{0x7f, 0x02, 0x0c, 0x02, 0x7f} // 0x4d M
  ,{0x7f, 0x04, 0x08, 0x10, 0x7f} // 0x4e N
  ,{0x3e, 0x41, 0x41, 0x41, 0x3e} // 0x4f O
  ,{0x7f, 0x09, 0x09, 0x09, 0x06} // 0x50 P
  ,{0x3e, 0x41, 0x51, 0x21, 0x5e} // 0x51 Q
  ,{0x7f, 0x09, 0x19, 0x29, 0x46} // 0x52 R
  ,{0x46, 0x49, 0x49, 0x49, 0x31} // 0x53 S
  ,{0x01, 0x01, 0x7f, 0x01, 0x01} // 0x54 T
  ,{0x3f, 0x40, 0x40, 0x40, 0x3f} // 0x55 U
  ,{0x1f, 0x20, 0x40, 0x20, 0x1f} // 0x56 V
  ,{0x3f, 0x40, 0x38, 0x40, 0x3f} // 0x57 W
  ,{0x63, 0x14, 0x08, 0x14, 0x63} // 0x58 X
  ,{0x07, 0x08, 0x70, 0x08, 0x07} // 0x59 Y
  ,{0x61, 0x51, 0x49, 0x45, 0x43} // 0x5a Z
  ,{0x00, 0x7f, 0x41, 0x41, 0x00} // 0x5b [
  ,{0x02, 0x04, 0x08, 0x10, 0x20} // 0x5c \
  ,{0x00, 0x41, 0x41, 0x7f, 0x00} // 0x5d ]
  ,{0x00, 0x41, 0x41, 0x7f, 0x00} // 0x5d ]
  ,{0x04, 0x02, 0x01, 0x02, 0x04} // 0x5e ^
  ,{0x40, 0x40, 0x40, 0x40, 0x40} // 0x5f _
  ,{0x00, 0x01, 0x02, 0x04, 0x00} // 0x60 `
  ,{0x20, 0x54, 0x54, 0x54, 0x78} // 0x61 a
  ,{0x7f, 0x48, 0x44, 0x44, 0x38} // 0x62 b
  ,{0x38, 0x44, 0x44, 0x44, 0x20} // 0x63 c
  ,{0x38, 0x44, 0x44, 0x48, 0x7f} // 0x64 d
  ,{0x38, 0x54, 0x54, 0x54, 0x18} // 0x65 e
  ,{0x08, 0x7e, 0x09, 0x01, 0x02} // 0x66 f
  ,{0x0c, 0x52, 0x52, 0x52, 0x3e} // 0x67 g
  ,{0x7f, 0x08, 0x04, 0x04, 0x78} // 0x68 h
  ,{0x00, 0x44, 0x7d, 0x40, 0x00} // 0x69 i
  ,{0x20, 0x40, 0x44, 0x3d, 0x00} // 0x6a j 
  ,{0x7f, 0x10, 0x28, 0x44, 0x00} // 0x6b k
  ,{0x00, 0x41, 0x7f, 0x40, 0x00} // 0x6c l
  ,{0x7c, 0x04, 0x18, 0x04, 0x78} // 0x6d m
  ,{0x7c, 0x08, 0x04, 0x04, 0x78} // 0x6e n
  ,{0x38, 0x44, 0x44, 0x44, 0x38} // 0x6f o
  ,{0x7c, 0x14, 0x14, 0x14, 0x08} // 0x70 p
  ,{0x08, 0x14, 0x14, 0x18, 0x7c} // 0x71 q
  ,{0x7c, 0x08, 0x04, 0x04, 0x08} // 0x72 r
  ,{0x48, 0x54, 0x54, 0x54, 0x20} // 0x73 s
  ,{0x04, 0x3f, 0x44, 0x40, 0x20} // 0x74 t
  ,{0x3c, 0x40, 0x40, 0x20, 0x7c} // 0x75 u
  ,{0x1c, 0x20, 0x40, 0x20, 0x1c} // 0x76 v
  ,{0x3c, 0x40, 0x30, 0x40, 0x3c} // 0x77 w
  ,{0x44, 0x28, 0x10, 0x28, 0x44} // 0x78 x
  ,{0x0c, 0x50, 0x50, 0x50, 0x3c} // 0x79 y
  ,{0x44, 0x64, 0x54, 0x4c, 0x44} // 0x7a z
  ,{0x00, 0x08, 0x36, 0x41, 0x00} // 0x7b {
  ,{0x00, 0x00, 0x7f, 0x00, 0x00} // 0x7c |
  ,{0x00, 0x41, 0x36, 0x08, 0x00} // 0x7d }
  ,{0x10, 0x08, 0x08, 0x10, 0x08} // 0x7e ~
  ,{0x78, 0x46, 0x41, 0x46, 0x78} // 0x7f DEL
};

بعد ذلك نقوم بالإعلان عن المصفوفة displayMap ، وهي تمثل الـ Pixels الموجودة في الشاشة. فعند وضع قيمة 0 في إحدى قيم المصفوفة، نقوم بذلك بإطفاء الـ Pixel المكافئة له على الشاشة. وعند وضع قيمة 255 نقوم بإضاءة الـ Pixel المكافئة :

byte displayMap[LCD_WIDTH * LCD_HEIGHT / 8] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0,
  0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0x1E, 0x0E, 0x02, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xF8,
  0xF8, 0xF0, 0xF8, 0xFE, 0xFE, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xF3, 0xE0, 0xE0, 0xC0, 
  0xC0, 0xC0, 0xE0, 0xE0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 
  0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03,
  0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
};

نقوم بإنشاء مصفوفة xkcdSandwich التي يقوم الأردوينو بإرسالها إلى الشاشة فتقوم برسم صورة معينة سنراها عندما نكمل كتابة الكود ويتم رفعه إلى الأردوينو :

char xkcdSandwich[504] = {
0xFF, 0x8D, 0x9F, 0x13, 0x13, 0xF3, 0x01, 0x01, 0xF9, 0xF9, 0x01, 0x81, 0xF9, 0xF9, 0x01, 0xF1,
0xF9, 0x09, 0x09, 0xFF, 0xFF, 0xF1, 0xF9, 0x09, 0x09, 0xF9, 0xF1, 0x01, 0x01, 0x01, 0x01, 0x01,
0xF9, 0xF9, 0x09, 0xF9, 0x09, 0xF9, 0xF1, 0x01, 0xC1, 0xE9, 0x29, 0x29, 0xF9, 0xF1, 0x01, 0xFF,
0xFF, 0x71, 0xD9, 0x01, 0x01, 0xF1, 0xF9, 0x29, 0x29, 0xB9, 0xB1, 0x01, 0x01, 0x01, 0xF1, 0xF1,
0x11, 0xF1, 0xF1, 0xF1, 0xE1, 0x01, 0xE1, 0xF1, 0x51, 0x51, 0x71, 0x61, 0x01, 0x01, 0xC1, 0xF1,
0x31, 0x31, 0xF1, 0xFF, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x01, 0x60, 0xE0, 0xA0, 0x01, 0x01, 0x81,
0xE1, 0x61, 0x60, 0xC0, 0x01, 0xE1, 0xE1, 0x21, 0x21, 0xE0, 0xC1, 0x01, 0xC1, 0xE1, 0x20, 0x20,
0xFC, 0xFC, 0xE0, 0xE0, 0xC1, 0xE1, 0xE0, 0xC1, 0xE0, 0xE1, 0x01, 0xFC, 0xFC, 0x21, 0x21, 0xE1,
0xC1, 0xE5, 0xE4, 0x01, 0xC1, 0xE0, 0x20, 0x21, 0x20, 0x00, 0x01, 0xFD, 0xFD, 0x21, 0x20, 0xE0,
0x00, 0x00, 0x01, 0x01, 0xC0, 0x61, 0x31, 0x31, 0x21, 0x20, 0xC0, 0x81, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x02,
0x03, 0x01, 0x00, 0x01, 0x03, 0xF2, 0x1A, 0x0B, 0x08, 0x0B, 0x1B, 0x10, 0x60, 0xE3, 0x03, 0x00,
0x01, 0x03, 0x02, 0x02, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x03,
0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x01, 0x03, 0x02, 0x02, 0x03, 0x01, 0x00, 0x03,
0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3E, 0x63, 0x80, 0x80, 0x80, 0x80, 0x60, 0x3F, 0x07,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x01, 0x01, 0x02, 0x03, 0x3E, 0xE8, 0xF8, 0xF0, 0xD0, 0x90,
0x18, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x38, 0xFF,
0x0C, 0x38, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
0x5F, 0x8F, 0x84, 0x05, 0x07, 0x06, 0x0C, 0x0E, 0x0E, 0x0C, 0x14, 0x34, 0x68, 0x88, 0xD8, 0x70,
0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0xE0, 0x00, 0xF0, 0xF0, 0x00, 0x80,
0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x20, 0x38,
0x0E, 0x01, 0xC0, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0x0E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xB6, 0xED, 0xC0, 0xC0,
0xC0, 0xE0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xE1, 0xE1, 0xC1,
0xEF, 0xBB, 0x83, 0x86, 0x88, 0xB0, 0x80, 0x80, 0x80, 0x8F, 0x90, 0x90, 0x90, 0x9F, 0x8F, 0x80,
0x9F, 0x9F, 0x87, 0x8D, 0x98, 0x80, 0x8C, 0x9E, 0x92, 0x92, 0x9F, 0xC0, 0xC7, 0xFF, 0xB8, 0x8F,
0x80, 0x90, 0x90, 0xC0, 0xF0, 0x8E, 0x81, 0x80, 0x81, 0x8F, 0xB8, 0xE0, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 
};

في الدالة ()setup، نقوم بوضع الإعدادات اللازمة للمشروع مثل تشغيل الشاشة وضبط إعداداتها اللازمة مثل الوضوح وإظهار بعض الصور المتحركة.
وايضا نقوم بتشغيل الشاشة التسلسلية (Serial Monitor) التي سنستخدمها في إرسال الأحرف والكلمات لعرضها على الشاشة لاحقا. حيث سنقوم بالككتابه على الشاشة بعد أن تنتهي من عرض الصور المتحركة.

void setup()
{
  Serial.begin(9600);

  lcdBegin(); // This will setup our pins, and initialize the LCD
  setContrast(55); // Pretty good value, play around with it

  updateDisplay(); // with displayMap untouched, SFE logo
  delay(2000);

  lcdFunTime(); // Runs a 30-second demo of graphics functions

  // Wait for serial to come in, then clear display and go to echo
  while (!Serial.available())
    ;
  clearDisplay(WHITE);
  updateDisplay();
}

في الدله ()loop، تقوم بإنتظار المستخدم إدخال الحروف أو الكلمات إلى الشاشة التسلسلية (Serial Monitor) ، ليقوم الأردوينو بإرسالها إلى الشاشة ليتم كتابتها. نقوم بعمل إختبار على ماتم ادخاله من قبل المستخدم. فمثلا إذا ادخل المستخدم الرمز ~ فإنه عبارة عن أمر لمسح الشاشة.

void loop()
{
  static int cursorX = 0;
  static int cursorY = 0;

  if (Serial.available())
  {
    char c = Serial.read();

    switch (c)
    {
    case '\n': // New line
      cursorY += 8;
      break;
    case '\r': // Return feed
      cursorX = 0;
      break;
    case '~': // Use ~ to clear the screen.
      clearDisplay(WHITE);
      updateDisplay();
      cursorX = 0; // reset the cursor
      cursorY = 0;
      break;
    default:
      setChar(c, cursorX, cursorY, BLACK);
      updateDisplay();
      cursorX += 6; // Increment cursor
      break;
    }
    // Manage cursor
    if (cursorX >= (LCD_WIDTH - 4)) 
    { // If the next char will be off screen...
      cursorX = 0; // ... reset x to 0...
      cursorY += 8; // ...and increment to next line.
      if (cursorY >= (LCD_HEIGHT - 7))
      { // If the next line takes us off screen...
        cursorY = 0; // ...go back to the top.
      }
    }
  }
}

باقي الدوال المستخدمة متقدمة بعض الشئ، يكفي فقط أن تعرف أنها تقوم بإرسال البيانات إلى الشاشة بشكل معين لتتمكن من عرض الصور أو الكلمات. وهي الدوال المستخدمة داخل الدالتين ()setup، و ()loop .

إذا كنت تريد تغيير ما يظهر على الشاشة، فلا حاجة إلى تغيير هذه الدوال، فقط قم بعمل التغير الذي تريده داخل الداليتين ()loop، و ()setup.

void lcdFunTime()
{
  clearDisplay(WHITE); 
  randomSeed(analogRead(A0));
  const int pixelCount = 100;
  for (int i=0; i<pixelCount; i++)
  {
    setPixel(random(0, LCD_WIDTH), random(0, LCD_HEIGHT));
    updateDisplay();
    delay(10);
  }
  setStr("full of stars", 0, LCD_HEIGHT-8, BLACK);
  updateDisplay();
  delay(1000);
  for (int i=0; i<5; i++)
  {
    invertDisplay(); 
    delay(200);
    invertDisplay();
    delay(200);
  }
  delay(2000);
  clearDisplay(WHITE); 
  int x0 = LCD_WIDTH/2;
  int y0 = LCD_HEIGHT/2;
  for (float i=0; i<2*PI; i+=PI/8)
  {
    const int lineLength = 24;
    int x1 = x0 + lineLength * sin(i);
    int y1 = y0 + lineLength * cos(i);
    setLine(x0, y0, x1, y1, BLACK);
    updateDisplay();
    delay(100);
  }
  for (int j=0; j<2; j++)
  {
    for (int i=255; i>=0; i-=5)
    {
      analogWrite(blPin, i);
      delay(20);
    }
    for (int i=0; i<256; i+=5)
    {
      analogWrite(blPin, i);
      delay(20);
    }
  }
  clearDisplay(WHITE); 
  for (int x=0; x<LCD_WIDTH; x+=8)
  { 
    setRect(0, 0, x, LCD_HEIGHT, 1, BLACK);
    updateDisplay();
    delay(10);
  }
  for (int x=0; x<LCD_WIDTH; x+=8)
  { 
    setRect(0, 0, x, LCD_HEIGHT, 1, WHITE);
    updateDisplay();
    delay(10);
  }
  for (int x=0; x<12; x++)
  { 
    setRect(0, 0, x, LCD_HEIGHT, 1, 1);
    setRect(11, 0, x+12, LCD_HEIGHT, 1, BLACK);
    setRect(23, 0, x+24, LCD_HEIGHT, 1, BLACK);
    setRect(35, 0, x+36, LCD_HEIGHT, 1, BLACK);
    setRect(47, 0, x+48, LCD_HEIGHT, 1, BLACK);
    setRect(59, 0, x+60, LCD_HEIGHT, 1, BLACK);
    setRect(71, 0, x+72, LCD_HEIGHT, 1, BLACK);
    updateDisplay();
    delay(10);
  }
  setRect(25, 10, 45, 30, 0, WHITE);
  setRect(35, 20, 55, 40, 0, WHITE);
  setLine(25, 10, 35, 20, WHITE);
  setLine(45, 30, 55, 40, WHITE);
  setLine(25, 30, 35, 40, WHITE);
  setLine(45, 10, 55, 20, WHITE);
  updateDisplay();
  delay(2000);
  clearDisplay(WHITE);
  for (int i=0; i<20; i++)
  {
    int x = random(0, LCD_WIDTH);
    int y = random(0, LCD_HEIGHT);
    setCircle(x, y, i, BLACK, 1);
    updateDisplay();
    delay(100);
  }
  delay(2000);
  setStr("Modern Art", 0, 10, WHITE);
  updateDisplay();
  delay(2000);
  setBitmap(xkcdSandwich);
  updateDisplay();
}

void setPixel(int x, int y)
{
  setPixel(x, y, BLACK); 
}

void clearPixel(int x, int y)
{
  setPixel(x, y, WHITE); 
}

void setPixel(int x, int y, boolean bw)
{
  if ((x >= 0) && (x < LCD_WIDTH) && (y >= 0) && (y < LCD_HEIGHT))
  {
    byte shift = y % 8;

    if (bw) 
      displayMap[x + (y/8)*LCD_WIDTH] |= 1<<shift;
    else   
      displayMap[x + (y/8)*LCD_WIDTH] &= ~(1<<shift);
  }
}

void setLine(int x0, int y0, int x1, int y1, boolean bw)
{
  int dy = y1 - y0; // Difference between y0 and y1
  int dx = x1 - x0; // Difference between x0 and x1
  int stepx, stepy;
  if (dy < 0)
  {
    dy = -dy;
    stepy = -1;
  }
  else
    stepy = 1;

  if (dx < 0)
  {
    dx = -dx;
    stepx = -1;
  }
  else
    stepx = 1;

  dy <<= 1; 
  dx <<= 1; 
  setPixel(x0, y0, bw); 
  if (dx > dy) 
  {
    int fraction = dy - (dx >> 1);
    while (x0 != x1)
    {
      if (fraction >= 0)
      {
        y0 += stepy;
        fraction -= dx;
      }
      x0 += stepx;
      fraction += dy;
      setPixel(x0, y0, bw);
    }
  }
  else
  {
    int fraction = dx - (dy >> 1);
    while (y0 != y1)
    {
      if (fraction >= 0)
      {
        x0 += stepx;
        fraction -= dy;
      }
      y0 += stepy;
      fraction += dx;
      setPixel(x0, y0, bw);
    }
  }
}

void setRect(int x0, int y0, int x1, int y1, boolean fill, boolean bw)
{
  if (fill == 1)
  {
    int xDiff;

    if(x0 > x1)
      xDiff = x0 - x1; 
    else
      xDiff = x1 - x0;

    while(xDiff > 0)
    {
      setLine(x0, y0, x0, y1, bw);

      if(x0 > x1)
        x0--;
      else
        x0++;

      xDiff--;
    }
  }
  else 
  {
    setLine(x0, y0, x1, y0, bw);
    setLine(x0, y1, x1, y1, bw);
    setLine(x0, y0, x0, y1, bw);
    setLine(x1, y0, x1, y1, bw);
  }
}

void setCircle (int x0, int y0, int radius, boolean bw, int lineThickness)
{
  for(int r = 0; r < lineThickness; r++)
  {
    int f = 1 - radius;
    int ddF_x = 0;
    int ddF_y = -2 * radius;
    int x = 0;
    int y = radius;

    setPixel(x0, y0 + radius, bw);
    setPixel(x0, y0 - radius, bw);
    setPixel(x0 + radius, y0, bw);
    setPixel(x0 - radius, y0, bw);

    while(x < y)
    {
      if(f >= 0)
      {
        y--;
        ddF_y += 2;
        f += ddF_y;
      }
      x++;
      ddF_x += 2;
      f += ddF_x + 1;

      setPixel(x0 + x, y0 + y, bw);
      setPixel(x0 - x, y0 + y, bw);
      setPixel(x0 + x, y0 - y, bw);
      setPixel(x0 - x, y0 - y, bw);
      setPixel(x0 + y, y0 + x, bw);
      setPixel(x0 - y, y0 + x, bw);
      setPixel(x0 + y, y0 - x, bw);
      setPixel(x0 - y, y0 - x, bw);
    }
    radius--;
  }
}

void setChar(char character, int x, int y, boolean bw)
{
  byte column; 
  for (int i=0; i<5; i++) 
  {
    column = ASCII[character - 0x20];
    for (int j=0; j<8; j++) 
    {
      if (column & (0x01 << j)) 
        setPixel(x+i, y+j, bw);
      else
        setPixel(x+i, y+j, !bw);
    }
  }
}

void setStr(char * dString, int x, int y, boolean bw)
{
  while (*dString != 0x00) 
  {
    setChar(*dString++, x, y, bw);
    x+=5;
    for (int i=y; i<y+8; i++)
    {
      setPixel(x, i, !bw);
    }
    x++;
    if (x > (LCD_WIDTH - 5)) 
    {
      x = 0;
      y += 8;
    }
  }
}

void setBitmap(char * bitArray)
{
  for (int i=0; i<(LCD_WIDTH * LCD_HEIGHT / 8); i++)
    displayMap = bitArray;
}

void clearDisplay(boolean bw)
{
  for (int i=0; i<(LCD_WIDTH * LCD_HEIGHT / 8); i++)
  {
    if (bw)
      displayMap = 0xFF;
    else
      displayMap = 0;
  }
}

void gotoXY(int x, int y)
{
  LCDWrite(0, 0x80 | x);  
  LCDWrite(0, 0x40 | y);  
}

void updateDisplay()
{
  gotoXY(0, 0);
  for (int i=0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++)
  {
    LCDWrite(LCD_DATA, displayMap);
  }
}

void setContrast(byte contrast)
{  
  LCDWrite(LCD_COMMAND, 0x21);
  LCDWrite(LCD_COMMAND, 0x80 | contrast); 
  LCDWrite(LCD_COMMAND, 0x20);
}

void invertDisplay()
{
  
  LCDWrite(LCD_COMMAND, 0x20);
  LCDWrite(LCD_COMMAND, 0x08 | 0x05); 
  LCDWrite(LCD_COMMAND, 0x20); 
  for (int i=0; i < (LCD_WIDTH * LCD_HEIGHT / 8); i++)
  {
    displayMap = ~displayMap & 0xFF;
  }
  updateDisplay();
}

void LCDWrite(byte data_or_command, byte data) 
{
  digitalWrite(dcPin, data_or_command); 
  digitalWrite(scePin, LOW);
  SPI.transfer(data); //shiftOut(sdinPin, sclkPin, MSBFIRST, data);
  digitalWrite(scePin, HIGH);
}

void lcdBegin(void) 
{
  pinMode(scePin, OUTPUT);
  pinMode(rstPin, OUTPUT);
  pinMode(dcPin, OUTPUT);
  pinMode(sdinPin, OUTPUT);
  pinMode(sclkPin, OUTPUT);
  pinMode(blPin, OUTPUT);
  analogWrite(blPin, 255);

  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
  digitalWrite(rstPin, LOW);
  digitalWrite(rstPin, HIGH);

  LCDWrite(LCD_COMMAND, 0x21); 
  LCDWrite(LCD_COMMAND, 0xB0); 
  LCDWrite(LCD_COMMAND, 0x04); 
  LCDWrite(LCD_COMMAND, 0x14);
  LCDWrite(LCD_COMMAND, 0x20); 
  LCDWrite(LCD_COMMAND, 0x0C);
}

 

مشغل موسيقى بإستخدام الأردوينو

سنقوم في هذا المشروع بعمل مشغل موسيقى mp3 باستخدام الاردوينو و موديول DFPlayer Mini الذي يستخدم كارت ذاكرة يمكننا من وضع الموسيقى التي نريد تشغيلها .

Mp3 Player: مشغل اغانى باستخدام الاردينو

 

المكونات المطلوبة

arduino uno r3

Arduino Uno

 

 

Full size breadboard 830

Breadboard

Breadboard Jumper Wire 65 pcs

Wires

 

DFPlayer Mini MP3 Module :

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

Mp3 Player: مشغل اغانى باستخدام الاردينو

سنقوم بتحميل ملفات الصوتيات على بطاقة الذاكرة (SD Card) ، ثم نقوم بوضعه داخل الموديول واعتمادا على الكود البرمجي الذي يتم رفعه على الأردوينو سنتحكم بتشغيل هذه الملفات.

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

Mp3 Player: مشغل اغانى باستخدام الاردينو
ملاحظة : الملفات الصوتية ذات الإمتداد mp3 هي التي تعمل فقط مع هذا الموديول.

يجب ان نقوم باعادة تسمية الملفات الصوتية بالشكل التالى :

0001.mp3 – 0002.mp3 – ……….. – 0100.mp3

 

Mp3 Player: مشغل اغانى باستخدام الاردينو

توصيل الدارة :

قم بتوصيل الدارة كما هو موضح بالصورة التالية :

Mp3 Player: مشغل اغانى باستخدام الاردينو

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

Mp3 Player: مشغل اغانى باستخدام الاردينو

الكود البرمجي :

قم برفع الكود التالي إلى الأردوينو :

#include <DFPlayer_Mini_Mp3.h>
#include <SoftwareSerial.h>


void setup () {
 Serial.begin (9600);
 mp3_set_serial (Serial); //set Serial for DFPlayer-mini mp3 module 
 mp3_set_volume (10);
}

void loop () {        

 mp3_play (1); //play 0001.mp3
 delay (10000); //10 sec, time delay to allow 0001.mp3 to finish playing

 mp3_play (2);
 delay (5000);

 mp3_play (5);
 delay (5000);

 mp3_play (20); //play 0020.mp3
 delay (9000);
}

 

شرح الكود البرمجى

في البداية سنحتاج الى تحميل مكتبة الموديول من الرابط .
ثم نقوم باضافتة الى مكتبات الاردوينو :

#include <DFPlayer_Mini_Mp3.h>
#include <SoftwareSerial.h>

في الدالة ()setup، نقوم بتشغيل بروتوكول التسلسلي، الذي سيتم استخدامه لإرسال الأوامر بين الأردوينو وموديول الـ Mp3 .

void setup () {
 Serial.begin (9600);
 mp3_set_serial (Serial); //set Serial for DFPlayer-mini mp3 module 
 mp3_set_volume (10);
}

في الدالة ()loop، نقوم بإعطاء ترتيب الملفات الصوتية المراد تشغيلها. فمثلا، نبدأ بتشغيل الملف الصوتي  0001.mp3 وننتظر 10 ثوان قبل البدء في الملف التالي وهكذا.

void loop () {        

 mp3_play (1); //play 0001.mp3
 delay (10000); //10 sec, time delay to allow 0001.mp3 to finish playing

 mp3_play (2);
 delay (5000);

 mp3_play (5);
 delay (5000);

 mp3_play (20); //play 0020.mp3
 delay (9000);
}

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

بث فيديو مباشر عبر شبكة الإنترنت

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

raspberry-pi-webcam-server

القطع المطلوبة :

raspberry-pi-iot-intruder-alert-system

 كاميرا للراسبري باي (raspberry pi camera module) أو USB webcam

8Gb Microsd 

 راسبيري باي (Raspberry Pi 3 Model B)

كيفية إعداد خادم كاميرا الويب :

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

في هذا المشروع سنقوم باستخدام حزمة الحركة (Motion) .

للبدء، سنقوم بإستخدام الـ Termial  لتحديث الراسبيري باي إلى أحدث إصدار.

sudo apt-get update
sudo apt-get upgrade

إعتمادا على إصدار الـ Raspbian الذي تستخدمه سوف تحتاج إلى القيام ببعض الخطوات المختلفة.

إصدار  Raspbian Jessie :

نبدأ بإزالة المكتبات التي قد تتعارض مع الحزم الأحدث. قد تكون موجودة أو غير موجودة على نسختك من الراسبيان.

sudo apt-get remove libavcodec-extra-56 libavformat56 libavresample2 libavutil54

قم بتنزيل وتثبيت الحزم التالية عن طريق إدخال الأوامر التالية  على الـ Terminal

wget https://github.com/ccrisan/motioneye/wiki/precompiled/ffmpeg_3.1.1-1_armhf.deb
sudo dpkg -i ffmpeg_3.1.1-1_armhf.deb

الآن نحن بحاجة إلى تثبيت الحزم التالية :

sudo apt-get install curl libssl-dev libcurl4-openssl-dev libjpeg-dev libx264-142 libavcodec56 libavformat56 libmysqlclient18 libswscale3 libpq5

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

wget https://github.com/Motion-Project/motion/releases/download/release-4.0.1/pi_jessie_motion_4.0.1-1_armhf.deb
sudo dpkg -i pi_jessie_motion_4.0.1-1_armhf.deb

إصدار Raspbian Stretch :

أولا قم بتثبيت الحزم التالية. الأمر التالي يعمل على الإصدارين من Raspbian Stretch .

sudo apt-get install libmariadbclient18 libpq5 libavcodec57  libavformat57 libavutil55 libswscale4

بعد ذلك، قم بتنزيل ملف motion deb من GitHub وتثبيته بإستخدام dpkg.

sudo wget https://github.com/Motion-Project/motion/releases/download/release-4.0.1/pi_stretch_motion_4.0.1-1_armhf.deb
sudo dpkg -i pi_stretch_motion_4.0.1-1_armhf.deb

هذا كل ماعليك القيام به للإنتقال إلى إعداد motion بحيث يتم تشغيلها على الراسبيري باي الخاص بك.

إعداد Motion :

الآن نحن بحاجة إلى إجراء بعض التعديلات على ملف motion.conf ، قم بفتح الملف عبر الأمر التالي :

sudo nano /etc/motion/motion.conf

قم بالبحث عن الأسطر التالية، ثم قم بتغييرها إلى ما يلي :

daemon on
stream_localhost off
output_pictures off
ffmpeg_output_movies off
stream_maxrate 100
framerate 100
width 640
height 480

الآن نحن بحاجة إلى إعداد الـ daemon، أولا نحن بحاجة إلى تحرير ملف الـ Motion.

sudo nano /etc/default/motion

ابحث عن السطر التالي وقم بتغييره إلى ما يلي :

start_motion_daemon=yes

بمجرد الإنتهاء من ذلك، قم بحفظ الملف والخروج منه عن طريق الضعط على ctrl+x ثم Y

تأكد الآن من توصيل الكاميرا، وتشغيلها عبر الأمر التالي:

sudo service motion start

إذا كنت بحاجة إلى إيقاف البث، ببساطة قم بتشغيل الأمر التالي:

sudo service motion stop

الآن يمكنك مشاهدة البث المباشر عبر صفحة الويب بإستخدام عنوان الـ IP Address الخاص بالراسبيري باي. قم بفتح المتصفح واستخدام IP address للراسبيري باي كما يلي :

YourIPAddress:8081

إذا لم يتم تحميل صفحة الويب حاول إعادة تشغيل الخدمة عبر الأمر التالي :

sudo service motion restart

 

raspberry-pi-webcam-server

إذا كنت تستخدم كاميرا الراسبيري باي، ستحتاج إلى القياب ببعض الخطوات الإضافية المذكورة بالقسم القادم.

خطوات إضافية لمستخدمي كاميرا الراسبيري باي

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

تثبيت الجهاز :

أولا قم بتوصيل الكاميرا إلى لوحة الراسبيري باي بالطريقة الصحيحة كما هو موضح بالصورة التالية :

raspberry-pi-webcam-server

إعداد البرنامج :

لجعل كاميرا الراسبيري باي تعمل، ستحتاج للقيام ببعض الخطوات الإضافية.

تأكد من تفعيل كاميرا الراسبيري باي. بعد توصيل الكاميرا إلى لوحة الراسبيري باي ، من قائمة البدء ثم preferences قم بفتح Raspberry Pi Configuration Tool

raspberry-pi-webcam-server

تأكد من أن الكاميرا مفعلة كما هو موضح بالصوة أدناه :

raspberry-pi-webcam-server

إذا لم تكن مفعلة قم بتفعيلها عن طريق اختيار (Enable) ،   ثم قم بإعادة تشغيل نظام الراسبيري باي.

الآن قم بفتح ملف modules عن طريق إدخال الأمر التالي عبر الـ Terminal.

sudo nano /etc/modules

قم بإدخال السطر التالي في الجزء السفلي من الملف إذا لم يكن موجودا بالفعل، وبمجرد الإنتهاء قم بحفظ والخروج من الملف عبر الضغط على ctrl+x ثم y .

bcm2835-v4l2

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

YourIPAddress:8081

 

raspberry-pi-webcam-server

 

هنا خادم كاميرا الراسبيري باي يمكن الوصول إليها داخل الشبكة المحلية. إذا كنت ترغب في السماح بالوصول الخارجي إليها قم بتباع التعليمات الموجودة في القسم التالي .

الإعدادات للوصول من خارج الشبكة  للبث :

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

ملاحظة: فتح منفذ (Port) على شبكة الإنترنت يمكن أن يتسبب في مخاطر أمنية .

 – أولا ، انتقل إلى صفحة router adimn (بالعادة يكون العنوان 192.168.1.1 أو 192.168.1.254)

raspberry-pi-webcam-server

 – بعد ذلك، قم بإدخال اسم المستخدم وكلمة المرور. الإفتراضي تكون admin , adimn.

– ثم قم بالذهاب إلى Advanced ، ثم Nat ، ثم قم بالضغط على Port Mapping .

– هنا قم بإدخال التالي :

Protocol : TCP/UDP ■
External start port: 8081 ■
External end port: 8081 ■
(Internal host: (Address of your Pi ■
Internal port: 8081 ■
Enable: Enable ■

raspberry-pi-webcam-server

يجب أن تكون الآن قادر على الإتصال ببث الـ webcam على الراسبيري باي من خارج الشبكة. قد تحتاج إلى إعادة تشغيل الـ Router لتصبح التغييرات مفعلة.

إذا لم تتمكن من الإتصال من خارج الشبكة المحلية، يمكنك تجربة ما يلي :

– تحقق من إعدادات جهاز router الخاص بك وتأكد من صحتها.
– تحقق من عنوان الـ IP انه لم يتغير . يمكنك إعداد Dynamic dns لمواجهة هذا.
– إعادة تشغيل الـ router .

جهاز للتحكم وقياس درجة الحرارة

 في هذا المشروع سنقوم بعمل جهاز لمراقبة وقياس درجة الحرارة . سيتم قياس درجة الحرارة بإستخدام حساس درجة الحرارة LM35، وعرض درجة الحرارة الحالية والمطلوبة من خلال شاشة العرض.

جهاز لقياس و التحكم فى درجة الحرارة باستخدام LM35

المكونات المطلوبة

arduino uno r3

Arduino Uno

LM35 Temperature Sensor

LM35

HD44780

LCD 16×2

220 Ω resistor

مقاومة 220 اوم

10K Ohms Resistors

Push Buttons

Full size breadboard 830

Breadboard

Breadboard Jumper Wire 65 pcs

Wires

الشاشة LCD

استخدام-حساس-الموجات-فوق-الصوتية-مع-ال
تعمل الشاشة في احد الحالات التالية:

استقبال أمر من الأردوينو وتنفيذه، على سبيل المثال : أمر التهيئة ومسح الشاشة:

lcd.begin(16,2);
lcd.clear();

استقبال معلومات من الأردوينو وعرضها، على سبيل المثال : كتابة جملة معينة :

lcd.print("Hello");
 للإطلاع على المزيد حول شاشة الـ LCD قم بالإطلاع على درس التحكم بشاشة LCD

حساس الحرارة LM35

LM35 Temperature Sensor

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

توصيله في الدارة :

مُخرج هذا الحساس يكون قيمة تناظرية (Analog) ، اي نحتاج إلى توصيله على أحد المنافذ التناظرية (Analog) في الأردوينو. الأطراف التناظرية في الأردوينو من A0 إلى A5 .

جهاز لقياس و التحكم فى درجة الحرارة باستخدام LM35

الطرف (بداية من اليسار)التوصيل
1Vcc
2Output To Arduino
3Ground

ملاحظة هامة :

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

شرح الدارة

قم بتوصيل الدارة كما هو موضح بالصورة التالية :

جهاز لقياس و التحكم فى درجة الحرارة باستخدام LM35

سيقوم الحساس LM35 بقياس درجة الحرارة بإستمرار وعرضها على شاشة الـ LCD وبإستخدام مفتاح التحكم (Push Buttons) يمكننا التحكم في رفع أو خفض درجة الحرارة المطلوبة في المكان.

جهاز لقياس و التحكم فى درجة الحرارة باستخدام LM35

الكود البرمجي :

قم بكتابة الكود التالي ورفعه على الأردوينو :

#include <LiquidCrystal.h>
#define tempPin A0 
#define tup 10 
#define tdown 9
 
float temp; 
int defC = 23; 
int upstate = 0; 
int downstate = 0; 

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

void setup() {
  lcd.begin(16, 2); 
  lcd.setCursor(0, 0); 
  lcd.print("Config.."); 
  delay(900);
  lcd.clear(); 
  pinMode(tup, INPUT); 
  pinMode(tdown, INPUT); 
}

void loop() {
  upstate = digitalRead(tup); 
  downstate = digitalRead(tdown); 
  int tvalue = analogRead(tempPin);  
  
  if (upstate == HIGH) { 
    defC = defC + 1; 
  }
  if (downstate == HIGH) { 
    defC = defC - 1; 
  }
  temp = tvalue * 0.48828;

  lcd.setCursor(0, 0);
  lcd.print("Current ");
  lcd.print (temp);  
  lcd.print ('C');
  
  lcd.setCursor (0, 1); 
  lcd.print ("Desired "); 
  lcd.print (defC);
  lcd.print ('C');

  delay(200);
}

شرح الكود :

في البداية، نقوم بإضافة المكتبة الخاصة بشاشة الـ LCD :

#include <LiquidCrystal.h>

ثم نقوم بتسمية منافذ الأردوينو المستخدمة في المشروع :

#define tempPin A0 
#define tup 10 
#define tdown 9

بعد ذلك، نقوم بالإعلان عن المتغيرات التي سيتم استخدامها في البرنامج لتسجيل قيم درجات الحرارة :

float temp; 
int defC = 23; 
int upstate = 0; 
int downstate = 0;

يتم تسجيل درجة الحرارة الناتجة من حساس الحرارة على المتغير temp. واستخدام المتغير defC لتسجيل درجة الحرارة المطلوبة. والمتغير upstate لتسجيل حالة المفتاح الأول الخاص برفع درجة الحرارة المطلوبة. والمتغير downstate لتسجيل حالة المفتاح الثاني الخاص بخفض درجة الحرارة المطلوبة.

ثم نقوم بإنشاء المتغير الخاص بشاشة الـ LCD وتحديد الأرجل التي سيتم توصيلها مع الأردوينو :

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

في الدالة ()setup، نقوم بضبط الإعدادات اللازمة، كإعدادات شاشة الـ LCD وضبط المفاتيح (Push Buttons) كمخرج :

void setup() {
  lcd.begin(16, 2); 
  lcd.setCursor(0, 0); 
  lcd.print("Config.."); 
  delay(900);
  lcd.clear(); 
  pinMode(tup, INPUT); 
  pinMode(tdown, INPUT); 
}

في الدالة ()loop، نقوم بقراءة المفاتيح (Push Buttons) ، وقراءة قيمة الجهد الناتج من الحساس :

  upstate = digitalRead(tup); 
  downstate = digitalRead(tdown); 
  int tvalue = analogRead(tempPin);

ثم نقوم بإختبار ما إذا تم الضغط على المفاتيح. فعند الضغط على مفتاح زيادة درجة الحرارة المطلوبة نقوم بإضافة 1 إلى درجة الحرارة المسجلة في المتغير defC. ويتم العكس عند الضغط على مفتاح خفض درجة الحرارة المطلوبة :

   if (upstate == HIGH) { 
    defC = defC + 1; 
  }
  if (downstate == HIGH) { 
    defC = defC - 1; 
  }

ونقوم بإستخدام قيمة الجهد الناتج من الحساس لإيجاد قيمة درجة الحرارة عن طريق المعادلة التالية :

   temp = tvalue * 0.48828;

وأخيرا، يتم عرض درجة الحرارة الحالية وأيضا درجة الحرارة المطلوبة على شاشة الـ LCD :

  lcd.setCursor(0, 0);
  lcd.print("Current ");
  lcd.print (temp);  
  lcd.print ('C');
  
  lcd.setCursor (0, 1); 
  lcd.print ("Desired "); 
  lcd.print (defC);
  lcd.print ('C');

  delay(200);

نظام الدخول الآمن بإستخدام RFID

في السنوات الأخيرة، أصبحت إجراءات التعرف الآلي  (Auto-ID)منتشرة فى العدید من القطاعات مثل الصناعات، الخدمات، ومجال الشراء والتوزيع وأنظمة الحماية. حيث تستخدم هذه التقنية لتأمين معلومات كافية ومستمرة عن المنتجات الصناعية أو هوية الأشخاص.

في هذا المشروع، سيتم التعرف على هذه التكنولوجيا والتي تعتمد على تقنية بدأت بالإنتشار تسمى RFID. فما هذه التقنية، وماهو مبدأ عملها، وكيف يتم استخدامها ؟

security-access-using-rfid-reader

القطع المطلوبة

الأدوات التي سيتم استخدامها لهذا المشروع :

security-access-using-rfid-reader

MFID-RC522 module

Half-size Breadboard

لوح تجارب حجم متوسط (Half size breadboard )

arduino uno r3

Arduino Uno R3

Jumper Wires Male/Male

 اسلاك توصيل ذكر/ذكر (Jumper Wires Male Male)

تقنية RFID :

هي إختصار لمصطلح radio frequency identification وهو تعبيرعام للتقنيات التي تستخدام ترددات الراديو لأغراض تحديد وتتبع الهوية . حيث أنها تستخدم المجالات الكهرومغناطيسية لتحديد وتتبع العلامات (tags) المرفقة بالأشياء تلقائيا. حيث تحتوي هذه العلامات على معلومات مخزنة إلكترونيا.

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

في هذا المشروع سيتم استخدام نظام RFID   لفتح الباب. على سبيل المثال، السماح لأشخاص معينين بالدخول.

يستخدم نظام RFID :

العلامات (Tags) التي يتم تعليقها بالكائنات أو الأشياء . في هذا المثال، لدينا سلسلة المفاتيح والبطاقة الكهرومغناطيسية. كل علامة tag له هوية خاصه به (UID).

security-access-using-rfid-reader

القارئ، جهاز ارسال وإستقبال، فهو يقوم بإرسال إشارات إلى الـ tag  ثم يقوم بقراءة ردها.

security-access-using-rfid-reader

 

المواصفات الأساسية للقارئ و بطاقات الـ tag :

مدخل الجهد :3.3v
التردد : 13.56MHz

تصميم لوح التجارب :

قم بتوصيل الدائرة كما هو موضح بالصورة التالية :

security-access-using-rfid-reader

تم توصيل القارئ بالأردوينو كما يلي :

قارئ RFIDالأردوينو
SDAمنفذ 10
SCKمنفذ 13
MOSIمنفذ 11
MISOمنفذ 12
IRQلا يتم توصيله
GNDGND
 RSTمنفذ 9
 3.3v3.3v (لاتقم بتوصيله إلى 5v)

قراءة البيانات من RFID tag :

قبل كتابة التعليمات البرمجية اللازمة، تحتاج إلى تحميل المكتبة الازمة لهذا المستشعر من هنـا.

ثم قم بفك الضغط عن المجلد المضغوط “rfid-master” وإضافة هذه المكتبة إلى المكتبات الموجودة ببرنامج الاردوينو. بعد القيام بذلك، قم بإعادة تشغيل برنامج الاردوينو الخاص بك.

بعد أن تم توصيل الدائرة، انتقل إلى ملف (File) >  أمثلة (DumpInfo < MFRC522 < (Examples ثم قم بتحميل التعليمات البرمجية.  هذا الكود سوف يكون متاح في واجهة الاردوينو (بعد تثبيت مكتبة RFID).

ثم قم بفتح الشاشة التسلسلية، يجب أن ترى شيئا مثل الشكل أدناه :

security-access-using-rfid-reader

قم بتقريب بطاقة أو سلسلة المفاتيح RFID إلى القارئ. قم بجعلها أقرب حتى يتم عرض كافة المعلومات.

security-access-using-rfid-reader

كما هو موضح بالصورة السابقة، هذه المعلومات التي يمكنك قراءتها من البطاقة، بما في ذلك UID الخاص بالبطاقة والذي تم تمييزه باللون الأصفر. حيث يتم تخزين المعلومات في الذاكرة التي يتم تقسيمها إلى segments  و blocks . لديك 1024 بايت من تخزين البيانات مقسمة إلى 16sectors.

قم بكتابة UID الخاص ببطاقتك لأنك ستحتاج إليه لاحقا.

البرمجة

في هذا المشروع سنقوم بقراءة  بطاقتين مختلفتين، فإذا كانت البطاقة تحمل UID  المسموح له بالدخول سيتم قبولها، وإلا سيتم رفضها.

قم بتحميل الكود التالي إلى الأردوينو :

#include <SPI.h> 
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
 
void setup() 
{
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  Serial.println("Approximate your card to the reader...");
  Serial.println();

}
void loop() 
{
  
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
 
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
  
  Serial.print("UID tag :");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte, HEX);
     content.concat(String(mfrc522.uid.uidByte < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte, HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();
  if (content.substring(1) == "1A 3A 3F D5") 
  {
    Serial.println("Authorized access");
    Serial.println();
    delay(3000);
  }
 
 else   {
    Serial.println("Access denied");
    delay(3000);
  }
} 

لمحة عن الكود :

اولا يتم تعريف منافذ الأردوينو اعتمادا على ما تم توصيله بالقارئ، ثم يتم إنشاء كائن MFRC522 :

#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);

في دالة ()setup ، يتم تهيئة شاشة الإتصال التسلسلي، والبروتوكول SPI المستخدم لنقل البيانات وتبادلها مع المتحكمات.

void setup() 
{
  Serial.begin(9600);   
  SPI.begin();      
  mfrc522.PCD_Init();   
  Serial.println("Approximate your card to the reader...");
  Serial.println();

}

في دالة ()loop، نقوم بقراءة قيمة الـ UID تدريجيا بإستخدام For loop، وطباعة القيمة بنظام الست عشر (Hex)، ويتم في كل مرة تحويل هذه القيمة إلى string وتخزينها في متغير concat لإستخدامه لاحقا في عملية المقارنة.

 for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte, HEX);
     content.concat(String(mfrc522.uid.uidByte < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte, HEX));
  }

ثم نقوم بعملية التحقق ما إذا كانت قيمة الـ UDI  التي تم قراءتها تساوي قيمة الـ UID المسموح لها بالدخول أو لا .
يجب تغيير الـ UID في الشرط (if (content.substring(1) == “Your UID” حسب ما تم كتابته سابقا في مرحلة قراءة البيانات.

if (content.substring(1) == "1A 3A 3F D5")
  {
    Serial.println("Authorized access");
    Serial.println();
    delay(3000);
  }
 
 else   {
    Serial.println("Access denied");
    delay(3000);
  }

وأخيرا، تم إنشاء نظام يتحكم بنظام الدخول من البوابة الإلكترونية حسب صلاحيات البطاقة الممنوحة للمستخدم بإستخدام تقنية الـ RFID .

روبوت الانقاذ

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

rescue-robot

 

الأدوات المطلوبة:

 

rescue-robot

Ultimate 2.0 Kit

مستشعر التسارع Accelerometer

 

مستشعر التسارع عبارة عن جهاز كهروميكانيكي صغير يقوم بقياس القوة الناتجة عن تسارع الجسم نتيجة الحركة أو الاهتزاز ويمكن لمقياس التسارع تحليل حركة الجهاز وتحديد الاتجاه الذي يميل فيه من خلال مقارنة تسارع الجهاز بالنسبة للأرض.

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

rescue-robot

سنقوم باستخدام جهاز محمول أو لوحي يحتوي على مستشعر التسارع للتحكم بالروبوت عبر البلوتوث
بحيث يتحرك الروبوت تبعا لحركة الهاتف أو الجهاز اللوحي.

البرمجة باستخدام التطبيق

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

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

للتحكم في حركة الروبوت سنقوم ببرمجته بحيث يتحرك في نفس الاتجاه الذي يميل فيه الهاتف المحمول
من خلال واجهة التطبيق سنقوم باختيار الروبوت Ultimate  واختيار إضافة مشروع جديد New Project

rescue-robot

 

سنقوم بإضافة مفتاح Switch ونسميه Tilt

rescue-robot

 

rescue-robot

تحت أمر تشغيل المفتاح سنضيف كود تحكم الحركة بإضافة أوامر شرطية
بحيث إذا تم توجيه الهاتف للأمام يتحرك الروبوت للأمام

rescue-robot

وكذلك بالنسبة للخلف واليمين واليسار

rescue-robot
rescue-robot
rescue-robot

تحت أمر إغلاق المفتاح نضع أمر توقف الحركة

rescue-robot

يتم وضع الأوامر البرمجية داخل أمر Repeat Forever

 

الكود البرمجي للحركة

rescue-robot

 

 


برمجة ذراع الروبوت

ينقسم التحكم بذراع الروبوت إلى قسمين : حركة الذراع للأعلى والأسفل وحركة المقبض للإمساك بالأشياء وإفلاتها
سنقوم بإضافة 4 أزرار تحكم
لتحرك الذراع للأعلى سوف نسمي الزر الأول Up بالنقر عليه واختيار علامة تعديل الاسم
عند  ضغط الزر سنضيف الأمر البرمجي المتعلق بتحريك محرك التشفير encoder motor  المسؤول عن تحريك الذراع واختيار رقم المنفذ الذي تم توصيله به
وعند ترك الزر نضع السرعة صفر للتوقف

rescue-robot

لتحريك الذراع للأسفل سوف نسمي الزر الآخر Down
ونضيف نفس الكود البرمجي لمحرك التشفير لكن بوضع قيمة السرعة سالبة ( – ) لعكس اتجاه الحركة

rescue-robot

 

برمجة القابض Gripper

لتحريك القابض للإمساك بالأشياء، سوف نسمي الزر الثالث Grip
عند ضغط الزر سنضيف الأمر المتعلق بحركة محرك DC المسؤول عن حركة القابض
وتحديد منفذ التوصيل

rescue-robot

الزر الرابع سوف نسميه Un-Grip،  لتحريك القابض لإفلات الأشياء
سنضيف نفس الكود البرمجي لكن بوضع السرعة بعلامة سالبة ( – ) لعكس اتجاه حركة المحرك وبالتالي عكس حركة القابض

rescue-robot

 

الواجهة النهائية للتطبيق

rescue-robot

لمزيد من المعلومات عن الأوامر البرمجية الأخرى يمكنك الرجوع لدرس جولة حول الأوامر البرمجية

نقوم بعد ذلك بحفظ المشروع Save وتحديث البرامج الثابتة من واجهة التطبيق Firmware  لتتمكن من تجربة المشروع.

بث  الفيديو على الحاسوب

عند إرسال الروبوت في مهام مختلفة قد نحتاج لمتابعة المحيط الذي يتحرك فيه الروبوت
ستقوم في هذه الخطوة بالاستفادة من كاميراة الهاتف الذكي لبث الفيديو على الحاسوب
باستخدام القطع الملحقة بروبوت Ultimate  يمكن بناء مسند لهاتف محمول بالمقياس المناسب لحجم الهاتف

rescue-robot

قم بتنزيل تطبيق Droidcam   من Google Play  على هاتف محمول أندرويد

سيظهر عند فتح التطبيق عنوان IP الخاص بهاتفك
ورقم المنفذ Port وعنوان المتصفح

rescue-robot

 

قم بفتح الكاميرا من خلال التطبيق

rescue-robot

على جهاز الحاسوب قم بفتح المتصفح وإدخال عنوان المتصفح Browser IP Cam Access بهذا الشكل

http://192.168.11.118 :4747/

يمكنك الآن متابعة البث لمباشر من كاميرا الهاتف المحمول على صفحة الويب

rescue-robot

مشروع آلة التبريد

 

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

makeblock-cooling-machine

 

الأدوات المطلوبة

makeblock-cooling-machine

Inventor Kit

القطع المطلوبة

makeblock-cooling-machine

 

طريقة التوصيل

 

نقوم بتوصيل مستشعر الحرارة إلى اللوحة الرئيسية عبر محول Rj25

makeblock-cooling-machine

 

المنفذالقطعة الالكترونية
منفذ4 وحدة 7-segment
منفذ6محول RJ25
منفذ8المقاومة المتغيرة
منفذ المحركات M1المروحة Me 130 dc motor

 

 

برمجة المشروع

 

سنقوم ببرمجة المشروع بحيث يتيح لنا تعيين درجة الحرارة التي نرغب في تبريد العصير إليها عبر المقاومة المتغيرة ويتم عرضها على وحدة 7-segment

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

makeblock-cooling-machine

ننشئ متغيرًا باسم temperature ونقوم بتعيينه لقراءة قيمة المقاومة المتغيرة

makeblock-cooling-machine

نقوم بتعيين وحدة 7-segment لعرض درجة الحرارة temperature

makeblock-cooling-machine

نستخدم الأمر التالي لقراءة مستشعر درجة الحرارة

makeblock-cooling-machine

باستخدام حلقة Repeat until
نضع أمر المحرك M1  المتعلق بالمروحة ليتحرك بسرعة 100 إلى أن تصبح درجة الحرارة التي اخترناها أكبر من الحرارة التي يقرأها المستشعر

makeblock-cooling-machine

عند تبريد الكوب إلى درجة الحرارة المطلوبة تتوقف المروحة

makeblock-cooling-machine

الكود البرمجي

 

makeblock-cooling-machine

للمزيد من المعلومات حول الكود يمكنك مراجعة درس جولة حول الأوامر البرمجية.

 

التحكم بالروبوت عبر الأوامر الصوتية

سنقوم في هذا المشروع باستخدام مستشعر الصوت الموجود في اللوحة الرئيسية Auriga لروبوت Ranger
لبرمجة روبوت يستجيب للأوامر الصوتية

 

voice-control-robot

 

الأدوات المطلوبة

voice-control-robot

mBot Ranger Kit

 Sound Sensor مستشعر الصوت

 

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

voice-control-robot

 

تحديد مدى قراءة المستشعر

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

قم بانشاء متغير Sound
اختيار الأمر say وتعيينه على مستشعر الضوء
ووضع الأمر داخل حلقة forever

voice-control-robot

 

ستظهر قراءة المستشعر على الشاشة

voice-control-robot

نلاحظ أن القيمة تتغير بسرعة كبيرة جدا وبهذا يصعب تحديد أعلى قيمة وأقل قيمة،  لذا سنضيف متغيرين آخرين
Max ليمثل أعلى قيمة،  و Min ليمثل أقل قيمة

voice-control-robot

سنقوم بتعيين المتغيرين على قراءة مستشعر الصوت

voice-control-robot

ونقوم كذلك بتعيين المتغير Sound لقراءة مستشعر الصوت

voice-control-robot

في البداية ستكون Max = Min
داخل حلقة forever  ستتغير قيمة المتغير Sound
ولتحديد أعلى وأقل قيمة نستخدم if ..then
بحيث إذا كانت قيمة sound أكبر من قيمة max
يتم إعادة تعيين قيمة max إلى هذه القيمة كأعلى قيمة
ويتم إعادة تعيين قيمة min إلى أقل قيمة تمت قراءتها في المتغير Sound

 

voice-control-robot

 

 

الكود البرمجي

سنقوم ببرمجة الروبوت بحيث يتراجع للوراء عند التصفيق أو إعطاءه أي أمر صوتي

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

نقوم بفتح صفحة جديدة في برنامج mBlock
وانشاء متغير Sound  وتعيينه لقراءة مستشعر الصوت في اللوحة الرئيسية

voice-control-robot

 

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

voice-control-robot

نلاحظ في الصورة أن قيمة max = 184 وهذه القيمة تم تسجيلها قبل إصدار أي صوت
مما يعني أنه عند التصفيق مثلا ستكون قيمة المستشعر أكبر من هذه القيمة

 

voice-control-robot

 

إذا كانت قيمة القراءة أقل،  يتم تنفيذ الأوامر بعد else وهو التحرك للأمام

 

الكود البرمجي:

 

voice-control-robot

 

قم  بتجربة إضافة أوامر برمجية تقوم بإضاءة LED عند التصفيق

لمزيد من المعلومات حول الأوامر البرمجية الأخرى قم بالرجوع لدرس جولة حول الأوامر البرمجية