تعلم الوحدات · الدرس 2.2
الصمام متعدد الألوان (RGB LED)
العودة إلى الدروسنظرة عامة ومكونات LED
يضيف RGB LED ألوانًا للمشروعات بسهولة، لأنه يجمع ثلاثة LEDs في حزمة واحدة. يوجد نوعان شائعان: المصعد المشترك (Common Anode) ويتصل طرفه المشترك بـ 5V، والمهبط المشترك (Common Cathode) ويتصل بالأرضي. نحتاج ثلاث مقاومات على التوالي، واحدة لكل لون، لتحديد التيار.
يبدأ البرنامج بالأحمر ثم ينتقل تدريجيًا إلى الأخضر فالأزرق ثم يعود إلى الأحمر، مارًا بأغلب الألوان الممكنة.
المكونات المطلوبة
- لوحة أردوينو (ELEGOO UNO R3).
- لوحة تجارب (Breadboard) ذات 830 نقطة.
- أربعة أسلاك ذكر إلى ذكر (Male to Male Jumper Wires).
- الصمام متعدد الألوان (RGB LED) واحد.
- ثلاث مقاومات (Resistor) 220Ω.
بنية RGB
يشبه LED عاديًا، لكن بداخله ثلاثة صمامات: أحمر وأخضر وأزرق. التحكم في سطوع كل منها يتيح مزج الألوان. يمكن تغيير المقاومات كما في درس LED، لكن ذلك يتطلب عملاً أكثر؛ وتتيح analogWrite() على منافذ UNO ذات العلامة ~ التحكم في القدرة المرسلة لكل لون.
للحزمة أربع أرجل: موجب لكل لون وطرف سالب مشترك. الطرف المشترك هو الثاني من جهة الحافة المسطحة، وهو الأطول ويوصل بالأرضي. يحتاج كل موجب مقاومة 220Ω مستقلة بينه وبين منفذ خرج UNO.

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

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

نبضة تنتج تقريبًا كل 1/500 ثانية. تتحكم analogWrite() في طولها؛ القيمة 0 تعني عدم وجود نبضة، و 255 تعني بقاء الخرج مفعّلًا طوال الفترة حتى النبضة التالية. القيم بينهما تعطي عرض نبضة متوسطًا. عند HIGH لمدة 5% يصل نحو 5% من القدرة، وعند 5V لمدة 90% يصل نحو 90%. سرعة التشغيل والإطفاء أعلى من قدرة العين على التمييز، فتبدو كاختلاف في السطوع.
توصيل الدائرة
المخطط الكهربائي

مخطط الأسلاك

فتح البرنامج وتعريف المنافذ
افتح ملف البرنامج RGB_LED.ino من ملفات الدرس في بيئة Arduino IDE. بعد إتمام التوصيلات، وصّل لوحة أردوينو (UNO R3 Board) بالحاسوب بكابل توصيل (USB Cable)، ثم اضغط زر Upload (رفع) لنقل البرنامج إلى اللوحة وتشغيله عليها.
إذا تعذر نقل البرنامج إلى اللوحة، فراجع قسم «رفع البرنامج ومعالجة خطأ الاتصال» في الدرس 1.5 «وميض LED وإضافة المكتبات» للتحقق من اتصال USB واختيار نوع اللوحة والمنفذ التسلسلي في بيئة Arduino IDE.
يبدأ البرنامج بتحديد منافذ الألوان:
#define BLUE 3
#define GREEN 5
#define RED 6#define
تتيح تسمية قيمة ثابتة قبل الترجمة. يستبدل المترجم الاسم بالقيمة المحددة، فلا يحتاج تعريف الماكرو نفسه إلى مساحة ذاكرة برنامج على الشريحة. يشرح الدرس أن الاستبدال النصي قد يسبب آثارًا غير مرغوبة عند تداخل الأسماء.
الصيغة #define constantName value، حيث constantName اسم الماكرو و value قيمته. لا تضع فاصلة منقوطة أو علامة =؛ فهما قد يسببان أخطاء ترجمة تظهر في مواضع لاحقة:
#define ledPin 3; // this is an error
#define ledPin = 3 // this is also an errorsetup() و pinMode()
تعمل setup() مرة بعد إعادة الضبط. تهيئ هنا المنافذ الثلاثة OUTPUT، وتشغل الأحمر وتطفئ الأخضر والأزرق. تضبط pinMode(pin, mode) المنفذ دخلًا أو خرجًا. منذ Arduino 1.0.1 يدعم INPUT_PULLUP تفعيل مقاومة السحب الداخلية، بينما INPUT يعطلها صراحة.
المتغيرات والتحكم في السطوع
معاملا pinMode() هما pin، رقم المنفذ، و mode، أحد INPUT أو OUTPUT أو INPUT_PULLUP. يشير الدرس إلى صفحة Digital Pins للتفصيل.
النوع int
الأعداد الصحيحة نوع أساسي لتخزين الأرقام. على UNO ولوحات ATmega يخزن int مقدارًا من 16 بت، أي بايتين، بمدى -32768 إلى 32767، أي من -2^15 إلى 2^15-1. على Due ولوحات SAMD مثل MKR1000 و Zero يكون 32 بت، أي أربعة بايتات، بمدى -2147483648 إلى 2147483647، أي من -2^31 إلى 2^31-1.
تُمثَّل الأعداد السالبة بمتمم الاثنين؛ يدل البت الأعلى على الإشارة. للحصول على تمثيل عدد سالب، اعكس جميع بتات العدد الموجب المقابل ثم أضف 1.
الصيغة int var = val، حيث var اسم المتغير و val قيمته. يعرف البرنامج redValue و greenValue و blueValue من النوع int.
تبدأ القيم بـ redValue = 255 و greenValue = 0 و blueValue = 0. يمكن تحديد ثلاث قيم سطوع، واحدة لكل لون، بين 0 للإطفاء و 255 لأقصى سطوع، ثم استدعاء analogWrite() لكل لون. جرّب إضافة ألوان خاصة بك.
في حلقة الانتقال من الأحمر إلى الأخضر، ينخفض redValue بمقدار 1 ويرتفع greenValue بمقدار 1، وتكتب القيمتان باستخدام analogWrite() ثم ينتظر البرنامج delayTime.
الحلقات والمعاملات
for
تكرر كتلة داخل أقواس معقوفة. يستخدم عداد عادة للتدرج وإنهاء الحلقة؛ وتفيد للعمليات المتكررة والعمل على مصفوفات البيانات أو المنافذ.
for (initialization; condition; increment) {
// statement(s);
}تحدث initialization أولًا مرة واحدة. تختبر condition في كل دورة: إذا كانت صحيحة تنفذ الكتلة ثم increment ويعاد الاختبار؛ وإذا صارت خطأ تنتهي الحلقة. ينفذ increment بعد كل دورة يكون شرطها صحيحًا.
الإسناد =
علامة = المفردة معامل إسناد في C++؛ تقيم التعبير يمينها وتحفظ نتيجته في المتغير يسارها. ليست معادلة أو اختبار مساواة كما في الجبر.
+= و -=
صيغة مختصرة لجمع قيمة مع متغير أو طرحها منه. يمكن أن تكون x متغيرًا، و y متغيرًا أو ثابتًا، ومن الأنواع int أو float أو double أو byte أو short أو long.
x += y; // equivalent to x = x + y
x -= y; // equivalent to x = x - yالكود
RGB_LED/RGB_LED.ino
//www.elegoo.com
//2016.12.8
// define pins
#define BLUE 3
#define GREEN 5
#define RED 6
void setup()
{
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
digitalWrite(RED, HIGH);
digitalWrite(GREEN, LOW);
digitalWrite(BLUE, LOW);
}
// define variables
int redValue;
int greenValue;
int blueValue;
// main loop
void loop()
{
#define delayTime 10 // fading time between colors
redValue = 255; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 0;
// this is unnecessary as we've either turned on RED in SETUP
// or in the previous loop ... regardless, this turns RED off
// analogWrite(RED, 0);
// delay(1000);
for (int i = 0; i < 255; i += 1) // fades out red bring green full when i=255
{
redValue -= 1;
greenValue += 1;
// The following was reversed, counting in the wrong directions
// analogWrite(RED, 255 - redValue);
// analogWrite(GREEN, 255 - greenValue);
analogWrite(RED, redValue);
analogWrite(GREEN, greenValue);
delay(delayTime);
}
redValue = 0;
greenValue = 255;
blueValue = 0;
for (int i = 0; i < 255; i += 1) // fades out green bring blue full when i=255
{
greenValue -= 1;
blueValue += 1;
// The following was reversed, counting in the wrong directions
// analogWrite(GREEN, 255 - greenValue);
// analogWrite(BLUE, 255 - blueValue);
analogWrite(GREEN, greenValue);
analogWrite(BLUE, blueValue);
delay(delayTime);
}
redValue = 0;
greenValue = 0;
blueValue = 255;
for (int i = 0; i < 255; i += 1) // fades out blue bring red full when i=255
{
// The following code has been rearranged to match the other two similar sections
blueValue -= 1;
redValue += 1;
// The following was reversed, counting in the wrong directions
// analogWrite(BLUE, 255 - blueValue);
// analogWrite(RED, 255 - redValue);
analogWrite(BLUE, blueValue);
analogWrite(RED, redValue);
delay(delayTime);
}
}