#include <Adafruit_NeoPixel.h>
// ===============================================
// 1. تعريفات وإعدادات الأردوينو
// ===============================================
#define PIN 6 // Digital Pin الذي يتم توصيل شريط الـ NeoPixel عليه
#define NUM_PIXELS 16 // عدد لمبات الـ LED في شريطك الحالي (يجب أن يكون 12)
#define PATTERN_SIZE 16 // حجم النمط الكامل الذي طلبته (4+4+4+4)
#define DELAYVAL 25 // زمن التأخير: 10ms يعطي سلاسة ممتازة لحركة الدوران
#define FADE_STEPS 40 // عدد الخطوات الداخلية للتلاشي لكل خطوة دوران (30 خطوة لتأثير ناعم)
// إنشاء كائن (object) للتحكم في الشريط
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, PIN, NEO_GRB + NEO_KHZ800);
// ===============================================
// 2. تعريف الألوان المطلوبة (4 ألوان)
// ===============================================
uint32_t colorGreen = strip.Color(0, 166, 80); // Green (أخضر)
uint32_t colorRed = strip.Color(206, 17, 38); // Red (أحمر)
uint32_t colorWhite = strip.Color(255, 255, 255); // White (أبيض)
uint32_t colorBlack = strip.Color(0, 0, 0); // Black / Off (مطفي)
// مصفوفة الألوان التي ستشكل "النمط" بحجم 16 لمبة
uint32_t FullPattern[PATTERN_SIZE] = {
// 4 أخضر
colorGreen, colorGreen, colorGreen, colorGreen,
// 4 أسود (مطفي)
colorBlack, colorBlack, colorBlack, colorBlack,
// 4 أحمر
colorRed, colorRed, colorRed, colorRed,
// 4 أبيض
colorWhite, colorWhite, colorWhite, colorWhite
};
// ===============================================
// 3. دوال مساعدة لاستخلاص مكونات اللون (RGB)
// ===============================================
byte getR(uint32_t c) { return (byte)(c >> 16); }
byte getG(uint32_t c) { return (byte)(c >> 8); }
byte getB(uint32_t c) { return (byte)(c); }
// ===============================================
// 4. دالة التحديث مع التلاشي والدوران
// ===============================================
void updateWithSmoothRotation(int currentOffset) {
// اللفة الخارجية تمثل خطوات التلاشي السلس (Interpolation)
for (int step = 0; step < FADE_STEPS; step++) {
// اللفة الداخلية تمثل كل لمبة على الشريط
for (int i = 0; i < NUM_PIXELS; i++) {
// 1. تحديد اللون الحالي واللون المستهدف (اللون الذي ستنتقل إليه اللمبة)
// مؤشر اللون الحالي (قبل الدوران)
int currentColorIndex = (i + currentOffset) % PATTERN_SIZE;
// مؤشر اللون المستهدف (الذي سيدخل إلى موقع اللمبة i في الخطوة التالية)
int targetColorIndex = (i + currentOffset + 1) % PATTERN_SIZE;
uint32_t colorStart = FullPattern[currentColorIndex];
uint32_t colorEnd = FullPattern[targetColorIndex];
// 2. حساب مكونات اللون الحالي والنهائي
byte r1 = getR(colorStart);
byte g1 = getG(colorStart);
byte b1 = getB(colorStart);
byte r2 = getR(colorEnd);
byte g2 = getG(colorEnd);
byte b2 = getB(colorEnd);
// 3. حساب الفرق اللوني الكلي
int diffR = r2 - r1;
int diffG = g2 - g1;
int diffB = b2 - b1;
// 4. تطبيق التلاشي: حساب اللون الوسيط (الآن)
uint32_t currentColor = strip.Color(
r1 + (diffR * step / FADE_STEPS),
g1 + (diffG * step / FADE_STEPS),
b1 + (diffB * step / FADE_STEPS)
);
// تعيين اللون لللمبة
strip.setPixelColor(i, currentColor);
}
strip.show();
delay(DELAYVAL);
}
}
// ===============================================
// 5. دالة setup و loop
// ===============================================
void setup() {
strip.begin();
strip.show();
}
void loop() {
// زيادة الإزاحة (offset) بمقدار 1 لـ "دفع" النمط خطوة للأمام
// التلاشي يحدث بين الإزاحة الحالية والإزاحة التالية
for (int offset = 0; offset < PATTERN_SIZE; offset++) {
updateWithSmoothRotation(offset);
}
}