اصنع عيون روبوت متحركة باستخدام ESP32 وشاشة OLED
في الحلقة الحادية عشرة من سلسلة ESP32 من الصفر سنتعرف على شاشة OLED وطريقة توصيلها بلوحة ESP32 باستخدام بروتوكول I2C. سنبدأ بعرض نص بسيط، ثم نستخدم نفس الدائرة لإنشاء عينين متحركتين لروبوت تستطيعان الرمش والنظر إلى اليمين واليسار.
فيديو المشروع
يمكنكم مشاهدة الشرح والتجربة العملية كاملة في الفيديو رقم 11 من سلسلة ESP32 من الصفر على قناة Naadi Tech – نادي الابتكار.
فكرة المشروع
سنستخدم شاشة OLED بدقة 128×64 بكسل مع ESP32. في التجربة الأولى سنتعلم أساسيات التحكم في الشاشة وعرض النصوص، ثم سنرسم عينين لروبوت ونحركهما برمجيًا باستخدام نفس التوصيلات.
التعرف على شاشة OLED
تتميز شاشة OLED بأن كل بكسل يصدر الضوء بنفسه، ولذلك لا تحتاج إلى إضاءة خلفية تقليدية وتوفر تباينًا جيدًا. تستخدم الوحدة في المشروع متحكم العرض SSD1306 وتتواصل مع ESP32 بواسطة واجهة I2C.
ملاحظة: ورد في الشرح الصوتي تعبير قريب من “I2C 1306”، والمقصود هو متحكم الشاشة SSD1306 مع بروتوكول الاتصال I2C.
ما هو بروتوكول I2C؟
يسمح I2C بتبادل البيانات بين المتحكم والمكونات الإلكترونية باستخدام خطين رئيسيين للاتصال، بالإضافة إلى التغذية والأرضي.
| المنفذ | الوظيفة |
|---|---|
| SDA | نقل البيانات |
| SCL | إشارة التوقيت |
| VCC | التغذية |
| GND | الأرضي |
المكونات المطلوبة
- لوحة ESP32.
- شاشة OLED بدقة 128×64 تعتمد على SSD1306 وI2C.
- لوحة تجارب عند الحاجة.
- أسلاك توصيل.
- كابل USB.
- Arduino IDE.
مخطط توصيل OLED مع ESP32
نغذي الشاشة من خرج 3.3V للوحة ESP32، ثم نوصل خطي I2C إلى GPIO21 وGPIO22.

| OLED | ESP32 | الوظيفة |
|---|---|---|
| VCC | 3.3V | التغذية |
| GND | GND | الأرضي |
| SDA | GPIO21 | البيانات |
| SCL | GPIO22 | التوقيت |
مهم: اتبع جهد التشغيل المدعوم من وحدة OLED التي لديك. في هذا المشروع تم توصيل VCC مع 3.3V للـ ESP32.
تثبيت مكتبات شاشة OLED
من مدير المكتبات في Arduino IDE ابحث عن Adafruit SSD1306 وثبت مكتبة Adafruit. نحتاج أيضًا إلى Adafruit GFX Library التي توفر دوال رسم النصوص والخطوط والأشكال الهندسية. وافق على تثبيت التبعيات إذا طلب Arduino IDE ذلك.
التجربة الأولى: عرض نص على شاشة OLED
نبدأ باستدعاء Wire وAdafruit_GFX وAdafruit_SSD1306، ثم نحدد أبعاد الشاشة 128×64 وننشئ عنصر التحكم في الشاشة.
تهيئة I2C والشاشة
داخل setup() نستخدم Wire.begin() مع GPIO21 للبيانات وGPIO22 للتوقيت، ثم display.begin() لتهيئة الشاشة. يستخدم المشروع عنوان I2C بقيمة 0x3C، وهو عنوان شائع في وحدات SSD1306.
كتابة النص وإظهاره
نمسح الذاكرة الرسومية باستخدام clearDisplay()، ثم نحدد لون النص وحجمه وموضعه. بعد كتابة النص نستدعي display.display() لإرسال محتوى الذاكرة إلى الشاشة.
كود التجربة الأولى: عرض النص
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(
SCREEN_WIDTH,
SCREEN_HEIGHT,
&Wire,
OLED_RESET
);
void setup() {
Serial.begin(115200);
// I2C pins: SDA = 21, SCL = 22
Wire.begin(21, 22);
// Initialize OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED not found");
while (true);
}
// Clear the screen
display.clearDisplay();
// Text color and size
display.setTextColor(SSD1306_WHITE);
display.setTextSize(2);
// Text position
display.setCursor(0, 10);
display.println("Naadi");
display.setCursor(0, 35);
display.println("Tech");
// Show on OLED
display.display();
}
void loop() {
}
بعد رفع البرنامج ظهر اسم نادي تك على شاشة OLED، وبذلك نتأكد من نجاح التوصيل والاتصال.
التجربة الثانية: عيون روبوت متحركة
نستخدم نفس المكتبات ونفس الدائرة، لكن بدل عرض الحروف سنستخدم الدوال الرسومية لإنشاء عينين وتحريكهما.
رسم العينين
نحدد عرض العين وارتفاعها والمسافة بين العينين، ثم ننشئ دالة drawEyes(). يتم رسم كل عين باستخدام fillRoundRect() لرسم مستطيل ممتلئ بحواف دائرية.
تحريك العينين يمينًا ويسارًا
تقوم دالة lookAround() بتغيير إحداثيات العينين تدريجيًا لتحريكهما إلى اليسار ثم اليمين وإعادتهما إلى الوسط.
إنشاء حركة الرمش
تقوم دالة blinkEyes() بتقليل ارتفاع العينين تدريجيًا حتى تبدوا شبه مغلقتين، ثم تعيد فتحهما للحصول على تأثير الرمش.
تشغيل الحركات
داخل setup() تتم تهيئة الشاشة ورسم العينين لأول مرة. أما داخل loop() فتتكرر حركات الرمش والنظر إلى اليسار واليمين ثم العودة إلى الوسط.
كود التجربة الثانية: عيون الروبوت المتحركة
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(
SCREEN_WIDTH,
SCREEN_HEIGHT,
&Wire,
OLED_RESET
);
// Eye dimensions
const int eyeWidth = 34;
const int eyeHeight = 44;
const int eyeSpacing = 12;
// Draw both eyes
void drawEyes(int offsetX, int height) {
display.clearDisplay();
int totalWidth = 2 * eyeWidth + eyeSpacing;
int startX = (SCREEN_WIDTH - totalWidth) / 2;
int y = (SCREEN_HEIGHT - height) / 2;
int radius = min(10, height / 2);
display.fillRoundRect(
startX + offsetX,
y,
eyeWidth,
height,
radius,
SSD1306_WHITE
);
display.fillRoundRect(
startX + eyeWidth + eyeSpacing + offsetX,
y,
eyeWidth,
height,
radius,
SSD1306_WHITE
);
display.display();
}
// Blink animation
void blinkEyes() {
for (int h = eyeHeight; h >= 4; h -= 4) {
drawEyes(0, h);
delay(20);
}
delay(100);
for (int h = 4; h <= eyeHeight; h += 4) {
drawEyes(0, h);
delay(20);
}
}
// Move eyes horizontally
void lookAround() {
// Look left
for (int x = 0; x >= -12; x -= 2) {
drawEyes(x, eyeHeight);
delay(40);
}
delay(500);
// Look right
for (int x = -12; x <= 12; x += 2) {
drawEyes(x, eyeHeight);
delay(40);
}
delay(500);
// Return to center
for (int x = 12; x >= 0; x -= 2) {
drawEyes(x, eyeHeight);
delay(40);
}
}
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED not found");
while (true);
}
display.clearDisplay();
drawEyes(0, eyeHeight);
}
void loop() {
// Eyes open
drawEyes(0, eyeHeight);
delay(1000);
// Blink
blinkEyes();
delay(400);
// Look left and right
lookAround();
delay(700);
// Blink again
blinkEyes();
delay(1500);
}
كيف تعمل الحركة على شاشة OLED؟
الشاشة لا تحرك الأشكال فعليًا. يرسم البرنامج الشكل في موضع، ثم يعيد رسمه في موضع مختلف. عند تكرار العملية بسرعة مناسبة نرى سلسلة الرسومات كأنها حركة مستمرة.
مشاكل شائعة وحلولها
| المشكلة | الحل |
|---|---|
| الشاشة لا تعرض شيئًا | تحقق من VCC وGND وSDA وSCL. |
| البرنامج لا يجد الشاشة | تحقق من عنوان I2C؛ يستخدم المشروع 0x3C وقد تختلف بعض الوحدات. |
| خطأ أثناء Compilation | تأكد من تثبيت Adafruit SSD1306 وAdafruit GFX والتبعيات. |
| الرسم لا يظهر | تأكد من استدعاء display.display() بعد أوامر الرسم. |
| الحركة سريعة أو بطيئة | عدّل التأخير ومقدار تغير الإحداثيات بين الإطارات. |
ماذا تعلمنا؟
- توصيل OLED مع ESP32.
- فهم SDA وSCL في I2C.
- استخدام Adafruit SSD1306 وAdafruit GFX.
- عرض النصوص.
- رسم الأشكال الهندسية.
- إنشاء حركة بتغيير الإحداثيات.
- محاكاة رمش وحركة عيني روبوت.
أفكار لتطوير المشروع
يمكن إضافة تعابير مثل الدهشة والغضب والنعاس والسعادة، أو ربط الحركات بحساسات وأزرار لتتغير تعابير الروبوت حسب ما يحدث حوله. ويمكن استخدام OLED أيضًا لعرض درجات الحرارة وحالة الحساسات والرسائل والقوائم.
الخلاصة
تعلمنا تشغيل شاشة OLED باستخدام ESP32 وI2C، ثم انتقلنا من عرض نص بسيط إلى إنشاء رسوم متحركة لعيني روبوت. يوضح المشروع كيف يمكن لشاشة صغيرة وأشكال هندسية بسيطة إضافة شخصية وتفاعل بصري إلى مشاريع الروبوتات.
تابعوا باقي حلقات سلسلة ESP32 من الصفر على Naadi Tech – نادي الابتكار للمزيد من المشاريع والتجارب العملية.
