هذا الدليل جزء من: مصفوفة مصابيح LED RGB من نوع ESP32-S3
مشروع رائع يمكنك تنفيذه لأغراض ترفيهية وعملية باستخدام وحدة ESP32-S3 RGB Matrix. تجد روابط لفيديوهات أخرى أسفل هذه المقالة.
مشروع مصفوفة LEDs RGB ESP32-S3 6 - لعبة Cible
المشروع 6 - لعبة الهدف (ميل اللوحة لضرب الدائرة)
المشروع 6 هو المشروع النهائي والأكثر تفاعلية في سلسلة مصفوفة LED RGB ESP32-S3. باستخدام مستشعر الحركة QMI8658C المدمج، يمكنك إمالة اللوحة لتحريك نقطة حول المصفوفة 8×8. توجد "منطقة هدف" دائرية في منتصف الشاشة. عندما تلمس نقطتك الدائرة، يتغير اللون و(اختياريًا) يصدر جرس صوتيًا. وهذا يخلق لعبة بسيطة ولكنها ممتعة بشكل مدهش لتوازن/تنسيق الحركة.
تظهر جميع المشاريع الستة في فيديو واحد على يوتيوب (مضمن في هذه الصفحة). يتم تحميل كود اللعبة الكامل تلقائيًا أسفل هذه المقالة، وتظهر روابط الشراء التابعة للوحدة تحت قسم الكود.

نظرة عامة على وحدة مصفوفة LEDs RGB ESP32-S3
تتضمن هذه الوحدة:

- مت controlador ESP32-S3(Wi-Fi + BLE)
- مصفوفة LED RGB بحجم 8×8(64 مصباح LED قابلة للع address)
- مقياس تسارع QMI8658Cلإحساس الميل والتوجيه
- يو إس بي-سيمنفذ للطاقة والبرمجة
- إعادة تشغيل / إعادة تعيينأزرار
- متوفردبابيس GPIOلملحقات مثل الصفارات أو المستشعرات
بالنسبة لهذه اللعبة، فإن مقياس التسارع ضروري - فهو يُبلغ باستمرار عن ميل X/Y، مما يسمح للنقطة بالتحرك بسلاسة بناءً على زاوية اللوحة. تُظهر قسم الفيديو لهذا المشروع بوضوح كيف تنزلق النقطة وتستجيب أثناء ميولك للوحدة لليسار/اليمين/الأمام/الخلف.:contentReference[oaicite:0]{index=0}

المشاريع التي تم تغطيتها في الفيديو (الطوابع الزمنية)
- 00:00- مقدمة
- 02:01- تثبيت لوحات ESP32
- 03:32- تثبيت المكتبات
- 05:32- المشروع 1: النقطة المتحركة
- 11:11- المشروع 2: تمرير النص
- 12:59- المشروع 3: نص HTTP
- ١٦:٤١- المشروع 4: نقطة الميل
- ١٨:٥٥- المشروع 5: سهم لأعلى
- ٢٠:٠٢-المشروع 6: لعبة الهدف (هذا المشروع)
تظهر هذه الجزء من الفيديو كل من حركة النقطة ومنطق اكتشاف الدائرة في العمل، مما يسهل فهم كيفية تصرف الإحداثيات.:contentReference[oaicite:1]{index=1}

تثبيت لوحات ESP32 في بيئة تطوير أريدوينو
إذا كنت قد أتممت المشاريع السابقة، فإن تركيب اللوحة قد تم. خلاف ذلك اتبع:
File > Preferences→ أضف رابط لوحة ESP32.Tools > Board > Boards Manager…قم بتثبيت "ESP32".- اختر لوحة ESP32-S3 تحت
Tools > Board. - حدد منفذ COM الصحيح تحت
Tools > Port.
تثبيت المكتبات المطلوبة
هذه اللعبة تستخدم:
Adafruit NeoMatrixAdafruit NeoPixelAdafruit GFXQMI8658حساس الحركة
قم بتثبيتها عبر:
Sketch > Include Library > Manage Libraries…- بحث:نيو مَاتريكس→ تثبيت
- تثبيت الاعتمادات (جرافيكس+نيوبكسل)
- بحث وتثبيتQMI8658
كيف تعمل لعبة الهدف
يقدم مقياس التسارع QMI8658C قيم ميل المحور X و Y. هذه القيم مرتبطة بإحداثيات LED (من 0 إلى 7 في كلا الاتجاهين). تتحرك النقطة الخاصة بك عبر المصفوفة بناءً على زاوية اللوحة.
دائرة (أو حلقة) مرسومة على الشاشة كـ "منطقة الهدف." تفوز بـ "ضربة" كلما تداخل النقطة مع الدائرة. في تلك اللحظة:
- تغير لون الهدف (عشوائي أو محدد مسبقًا)
- يصدر جهاز التنبيه الاختياري صوت صفير (إذا كان متصلاً)
نظرًا لصغر المصفوفة، يتم رسم الدائرة باستخدام فحص بسيط لنصف القطر. اللعبة تعمل بشكل مستمر، لذا يمكنك الميل للأمام والخلف لضرب الدائرة مرارًا وتكرارًا.
المشروع 6 - إعدادات الكود (التحكم في اللعبة)
فيما يلي الإعدادات الرئيسية القابلة للتعديل من قبل المستخدم والمتواجدة في أعلى الرسم التخطيطي. يتم تضمين الشيفرة الكاملة تلقائيًا أسفل هذه المقالة.
تهيئة المصفوفة
// Matrix configuration
const int MATRIX_PIN = 14;
const int MATRIX_WIDTH = 8;
const int MATRIX_HEIGHT = 8;
مصفوفة RGB متصلة بشكل مباشر بـ GPIO 14 - لا تغير هذا.
سطوع
uint8_t matrixBrightness = 40; // 0–255
للاستخدام الداخلي، 30-60 هو المثالي.
لون النقطة
// Dot color (R, G, B)
uint8_t dotRed = 255;
uint8_t dotGreen = 255;
uint8_t dotBlue = 255;
هذه هي النقطة التي تتحرك من خلالها عند إمالة اللوحة.
لون الدائرة (عشوائي أو ثابت)
// Circle (target) color
uint8_t circleRed = 0;
uint8_t circleGreen = 0;
uint8_t circleBlue = 255;
// If true, choose a new random color each time the dot hits
bool randomCircleColor = true;
مجموعةrandomCircleColor = false;إذا كنت تريد لونًا ثابتًا.
نصف قطر الدائرة
// Target size (radius)
int targetRadius = 3; // 3 fits well on 8×8 matrix
تجعل الأقطار الأكبر اللعبة أسهل؛ بينما تجعل الأقطار الأصغر اللعبة أكثر صعوبة.
حساسية الميل
// Sensitivity of tilt mapping
float tiltScale = 4.0f; // increase = faster movement across screen
إذا تحرك النقطة بسرعة كبيرة أو قفزت، قلل من هذا الرقم.
إعدادات الجرس (اختياري)
// Buzzer pin (optional)
int buzzerPin = 6; // connect buzzer + to pin 6, – to GND
bool useBuzzer = true; // set false to disable sound
إذا لم تقم بتوصيل صفارة، فقط قم بتعيينuseBuzzer = false;
ملخص
يجمع المشروع 6 كل ما تم تعلمه من المشاريع السابقة: رسم المصفوفات، إدخال مستشعر الحركة، التحكم في الألوان، تنعيم الحركة، وصوت اختياري. يميل اللوح لتحريك النقطة، وضغط الدائرة يغير لونها وتفعيل صفارة (اختياريًا). إنها عرض ممتع للكشف عن الحركة على شاشة RGB مدمجة.
يتم عرض رمز "لعبة الهدف" الكامل تلقائيًا أسفل هذه المقالة. يمكنك أيضًا مشاهدة الجزء الخاص بمشروع 6 من الفيديو لرؤية كيفية تحرك النقطة وكيف يتم الكشف عن الضربات. إذا كنت ترغب في بناء لعبتك الخاصة، ستظهر روابط تابعة لشراء وحدة مصفوفة LED RGB ESP32-S3 تحت قسم الرمز.
هذا الدليل هو جزء من: مصفوفة مصابيح LED RGB من نوع ESP32-S3
- مشاريع مصفوفة LED الملونة ESP32-S3 (لعبة الميل، النص، السهم، عرض الواي فاي)
- مشروع مصفوفة LED RGB ESP32-S3 2 - نص متحرك
- مشروع مصفوفة LED RGB ESP32-S3 3 - نص من الهاتف المحمول
- مشروع مصفوفة LED RGB ESP32-S3 4 - نقطة مائلة
- مشروع مصفوفة LED RGB ESP32-S3 5 - السهم دائما لأعلى
- مشروع ساعة بتوقيت NTP + Wi-Fi لمصفوفة LED RGB ESP32-S3 -1 ساعة أساسية
- مشروع ساعة الإنترنت لشاشة مصفوفة LED RGB ESP32-S3 - عرض الوقت والتاريخ متعدد الألوان 2 ساعة
- مشروع ساعة الإنترنت لمصفوفة LED RGB ESP32-S3 - 3 ألوان ليلية مع التاريخ
- مشروع ساعة إنترنت مصفوفة LED RGB ESP32-S3 - 5 ألوان قوس قزح
- مشروع ساعة الإنترنت لشبكة مصفوفة LEDs RGB ESP32-S3 - 4 ألوان عشوائية
- اختبار مصفوفة LED RGB ESP32-S3 لإعداد RGB و GRB
/*
* المشروع 6: لعبة دائرة الميل – مصفوفة LED ملونة ESP32-S3 (Waveshare)
*
* هذا الرمز يقرأ بيانات الميل من وحدة القياس بالقصور الذاتي QMI8658C ويحرك نقطة بسلاسة
* على مصفوفة LED الملونة 8×8 بناءً على اتجاه اللوحة.
*
* ▶️ فيديو تعليمي:
* https://youtu.be/JKLuYrRcLMI
*
* 📚⬇️ صفحة الموارد والكود:
* https://robojax.com/RJT829
*
* QMI8658_RGB_2
*/
#include <Arduino.h>
#include <math.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#include <QMI8658.h> // بواسطة لاحاف جاهالي
// -------- إعداد مصفوفة LED --------
#define MATRIX_PIN 14
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
// دبوس الجرس – غيّر هذا إلى منفذ GPIO الفعلي للجرس.
const int BUZZER_PIN = 6; // المهمة: اضبط على دبوس الجرس الخاص بك
// سطوع المصفوفة (0–255)
const uint8_t MATRIX_BRIGHTNESS = 10;
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(
MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN,
NEO_MATRIX_TOP + NEO_MATRIX_LEFT +
NEO_MATRIX_ROWS + NEO_MATRIX_PROGRESSIVE,
NEO_GRB + NEO_KHZ800
);
// -------- إعداد وحدة القياس بالقصور الذاتي (IMU) --------
QMI8658 imu;
// -------- إعدادات اللعبة --------
// كم مرة يُسمح للنقطة بالتحرك (مللي ثانية).
// الأكبر = حركة أبطأ.
const uint16_t MOVE_INTERVAL_MS = 150; // جرب 120–250
// كم مقدار الميل (م/ث^2) قبل أن تتحرك النقطة.
// زِدْ إذا كان يشعر بحساسية مفرطة.
const float ACC_TILT_THRESHOLD = 2.0f; // حوالي 0.2 غرام
// لون النقطة الأساسي (RGB)
const uint8_t DOT_R = 255;
const uint8_t DOT_G = 255;
const uint8_t DOT_B = 255;
// هندسة الدائرة (مركزها 8x8)
const float CIRCLE_CENTER_X = (MATRIX_WIDTH - 1) / 2.0f; // 3.5
const float CIRCLE_CENTER_Y = (MATRIX_HEIGHT - 1) / 2.0f; // 3.5
const float CIRCLE_RADIUS = 3.0f;
const float CIRCLE_THICKNESS = 0.8f; // +- سماكة حول نصف القطر
// -------- حالة اللعبة --------
// موضع النقطة على الشبكة 8x8 (0..7)
int dotX = 3;
int dotY = 3;
// الألوان (ألوان NeoMatrix 16-بت)
uint16_t dotColor;
uint16_t circleColor;
// لاكتشاف "لمست الدائرة للتو" مقابل "ما زلت على الدائرة"
bool wasOnCircle = false;
// مؤقت لتقييد معدل الحركة
unsigned long lastMoveTime = 0;
// لا توجد نص للترجمة. يرجى تقديم النص الذي ترغب في ترجمته من الإنجليزية إلى العربية.
// عجلة الألوان الكلاسيكية لنيوبيكسل (0-255 -> قوس قزح)
uint16_t wheel(byte pos) {
if (pos < 85) {
return matrix.Color(pos * 3, 255 - pos * 3, 0);
} else if (pos < 170) {
pos -= 85;
return matrix.Color(255 - pos * 3, 0, pos * 3);
} else {
pos -= 170;
return matrix.Color(0, pos * 3, 255 - pos * 3);
}
}
// هل يقع البكسل المحدد تقريبًا على الدائرة؟
bool isOnCircle(int x, int y) {
float dx = x - CIRCLE_CENTER_X;
float dy = y - CIRCLE_CENTER_Y;
float d2 = dx * dx + dy * dy;
float rMin = CIRCLE_RADIUS - CIRCLE_THICKNESS;
float rMax = CIRCLE_RADIUS + CIRCLE_THICKNESS;
return (d2 >= rMin * rMin) && (d2 <= rMax * rMax);
}
// ارسم دائرة + نقطة
void drawScene() {
matrix.fillScreen(0);
// ارسم دائرة
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
if (isOnCircle(x, y)) {
matrix.drawPixel(x, y, circleColor);
}
}
}
// ارسم نقطة (في الأعلى)
matrix.drawPixel(dotX, dotY, dotColor);
matrix.show();
}
// نغمة حجب بسيطة (قصيرة)
void buzzOnce() {
digitalWrite(BUZZER_PIN, HIGH);
delay(40);
digitalWrite(BUZZER_PIN, LOW);
}
// استخدم عجلة التسارع لتحديد حركة النقطة
void updateDotFromTilt(float ax, float ay) {
unsigned long now = millis();
if (now - lastMoveTime < MOVE_INTERVAL_MS) {
return; // مبكرًا جدًا، انتظر
}
int dx = 0;
int dy = 0;
// على هذه اللوحة، يشعر الميل Y مثل "يسار/يمين" على المصفوفة،
// والميل X يشعر وكأنه "أعلى/أسفل" → لذا نقوم بالتبديل.
// --- الحركة الأفقية من AY (الميل لليسار/لليمين) ---
if (ay > ACC_TILT_THRESHOLD) {
dx = 1; // الميل إلى اليمين → نقل النقطة إلى اليمين
} else if (ay < -ACC_TILT_THRESHOLD) {
dx = -1; // الميل إلى اليسار → تحريك النقطة إلى اليسار
}
// --- الحركة العمودية من AX (الميل للأمام/للخلف) ---
// هذا تم عكسه. نحن نقلب الإشارات:
// المحور س > العتبة = يميل "إلى الأمام" (بعيدًا) → حرك النقطة لأعلى (دلتا ص = -1)
// المحور س < -العتبة = إمالة "للخلف" (باتجاه) → حرك النقطة لأسفل (دي ص = 1)
if (ax > ACC_TILT_THRESHOLD) {
dy = -1; // كان +1 قبل
} else if (ax < -ACC_TILT_THRESHOLD) {
dy = 1; // كان -1 قبل
}
if (dx != 0 || dy != 0) {
dotX = constrain(dotX + dx, 0, MATRIX_WIDTH - 1);
dotY = constrain(dotY + dy, 0, MATRIX_HEIGHT - 1);
lastMoveTime = now;
}
}
// -------- الإعداد والحلقة --------
void setup() {
Serial.begin(115200);
delay(100);
// تهيئة المصفوفة
matrix.begin();
matrix.setBrightness(MATRIX_BRIGHTNESS);
matrix.fillScreen(0);
matrix.show();
// مُنَبِّه البداية
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
// تهيئة وحدة القياس بالقصور الذاتي
if (!imu.begin(11, 12)) {
Serial.println("Failed to initialize QMI8658!");
while (1) {
delay(100);
}
}
// استخدم م/ث² ودرجة/ثانية (اختياري، لكنه جيد)
imu.setAccelUnit_mps2(true);
imu.setGyroUnit_dps(true);
imu.setDisplayPrecision(3);
Serial.println("QMI8658 initialized.");
// الحالة الأولية للعبة
randomSeed((uint32_t)micros());
dotX = MATRIX_WIDTH / 2;
dotY = MATRIX_HEIGHT / 2;
dotColor = matrix.Color(DOT_R, DOT_G, DOT_B);
circleColor = wheel(random(256));
drawScene();
}
void loop() {
// قراءة مقياس التسارع
float ax, ay, az;
if (imu.readAccelMPS2(ax, ay, az)) {
// تصحيح إذا لزم الأمر:
// `Serial.print("محور س: "); Serial.print(ax);`
// Serial.print(" AY: "); Serial.print(ay);
// Serial.print(" السمت: "); Serial.println(az);
updateDotFromTilt(ax, ay);
}
// التحقق من التصادم مع الدائرة
bool onCircle = isOnCircle(dotX, dotY);
if (onCircle && !wasOnCircle) {
// لمست الدائرة للتو: تغيير اللون + صوت تنبيه
circleColor = wheel(random(256));
buzzOnce();
}
wasOnCircle = onCircle;
// إعادة رسم
drawScene();
// تأخير بسيط حتى لا نفرط في استخدام I2C
delay(10);
}
الأشياء التي قد تحتاجها
-
أمازون
-
إي باي
-
علي إكسبريساشترِ مصفوفة RGB ESP32-S3 من علي إكسبريسs.click.aliexpress.com
-
علي إكسبريسشراء مصفوفة RGB ESP32-S3 من علي إكسبريس (2)s.click.aliexpress.com
الموارد والمراجع
-
داخليأداة اختيار الألوانrobojax.com
ملفات📁
Fritzing File
-
جزء فريتزنج esp32-S3-supermini-tht
esp32-S3-supermini-tht.fzpz0.02 MB