ماژول کنترل از راه دور مینی مادون قرمز 16 کاناله

16Channel Tiny Infra-Red Remote Controller Module

 

این ماژول کوچک و کاربردی طوری طراحی گشته بتواند شانزده کلید ریموت کنترل مادون قرمز را دریافت نماید و خروجی مرتبط با آن را بصورت پایدار (Latch) روشن نگه دارد و در مرتب بعد فشردن همان کلید بصورت معکوس عمل و آن را خاموش نماید.

کنترلر بی‌سیم پیشرفته

📱 کنترل از راه دور مینی مادون قرمز 16 کاناله: فرماندهی هوشمند بی‌سیم

ماژول کنترل از راه دور مینی مادون قرمز 16 کاناله یک راه‌حل کامپکت و قدرتمند برای کنترل بی‌سیم پروژه‌های الکترونیکی، رباتیک و سیستم‌های اتوماسیون است. این ماژول با پشتیبانی از 16 کانال مجزا، امکان کنترل چندین دستگاه را به طور همزمان فراهم می‌کند.

🎯 ویژگی‌های کلیدی

🔌 طراحی مینیاتوری و کاربردی:

  • ابعاد کوچک: طراحی جمع‌وجور برای نصب آسان

  • 16 دکمه مستقل: کنترل مجزای 16 عملکرد مختلف

  • فرستنده مادون قرمز: برد مؤثر تا 10 متر

  • گیرنده حساس: تشخیص دقیق سیگنال‌های IR

⚡ عملکرد پیشرفته:

  • کدگذاری اختصاصی: جلوگیری از تداخل با دستگاه‌های دیگر

  • مصرف برق پایین: مناسب برای پروژه‌های باتری‌دار

  • پاسخ سریع: زمان پاسخ کمتر از 100ms

  • قابلیت برنامه‌ریزی: تنظیم کدهای دلخواه

📊 مشخصات فنی دقیق

پارامترهای فرستنده (کنترل از راه دور):

  • ولتاژ کاری: 3V DC (2 باتری قلمی AAA)

  • جریان مصرف: 15-25mA در حالت ارسال

  • فرکانس کاری: 38kHz استاندارد

  • طول موج: 940nm (مادون قرمز)

  • برد مؤثر: 8-10 متر (در خط دید)

  • زاویه ارسال: ±30 درجه

  • ابعاد: 55mm × 35mm × 10mm

  • وزن: 25 گرم (با باتری)

پارامترهای گیرنده:

  • ولتاژ کاری: 3.3V – 5V DC

  • جریان مصرف: 0.8-1.5mA (آماده‌به‌کار)

  • فرکانس تشخیص: 38kHz ±1kHz

  • ولتاژ خروجی: 0V (فعال) – Vcc (غیرفعال)

  • پین‌های خروجی: 3 پین (VCC, GND, OUT)

  • ابعاد ماژول: 18mm × 15mm × 5mm

مشخصات دکمه‌ها:

  • تعداد دکمه‌ها: 16 دکمه مستقل

  • چیدمان: ماتریس 4×4

  • برچسب دکمه‌ها:

    • ردیف 1: 1, 2, 3, A

    • ردیف 2: 4, 5, 6, B

    • ردیف 3: 7, 8, 9, C

    • ردیف 4: *, 0, #, D

  • طول عمر مکانیکی: 100,000 فشار

🔧 ساختار و پیکربندی

پیکربندی کنترل از راه دور:

طراحی کنترل از راه دور:
   [نمایشگر LCD] (در برخی مدل‌ها)
        ↓
   [ماتریس دکمه 4×4]
        ↓
   [میکروکنترلر رمزگذاری]
        ↓
   [درایور LED مادون قرمز]
        ↓
   [LED فرستنده IR]

پین‌های ماژول گیرنده:

پیکربندی 3 پین:
   ┌───────┐
   │ ● ● ● │
   └───────┘
   │ │   │
   VCC OUT GND
   
اتصال:
- VCC: به 3.3V یا 5V
- OUT: به پین دیجیتال میکروکنترلر
- GND: به زمین

کدهای هر دکمه (معمولاً به صورت hex):

دکمه‌ها و کدهای نمونه:
1: 0x45    2: 0x46    3: 0x47    A: 0x44
4: 0x40    5: 0x43    6: 0x07    B: 0x15
7: 0x09    8: 0x16    9: 0x19    C: 0x0D
*: 0x0C    0: 0x18    #: 0x5E    D: 0x52

💻 برنامه‌نویسی و راه‌اندازی

اتصال پایه به آردوینو:

// تعریف پایه‌های ماژول گیرنده IR
#define IR_RECEIVER_PIN 11  // پین خروجی گیرنده
#define STATUS_LED_PIN  13  // LED نشانگر (اختیاری)

// کتابخانه IR (اگر موجود باشد)
#include <IRremote.h>

// تعریف کدهای دکمه‌ها (مقادیر نمونه)
#define IR_BUTTON_1     0x45
#define IR_BUTTON_2     0x46
#define IR_BUTTON_3     0x47
#define IR_BUTTON_4     0x40
#define IR_BUTTON_5     0x43
#define IR_BUTTON_6     0x07
#define IR_BUTTON_7     0x09
#define IR_BUTTON_8     0x16
#define IR_BUTTON_9     0x19
#define IR_BUTTON_0     0x18
#define IR_BUTTON_A     0x44
#define IR_BUTTON_B     0x15
#define IR_BUTTON_C     0x0D
#define IR_BUTTON_D     0x52
#define IR_BUTTON_STAR  0x0C
#define IR_BUTTON_HASH  0x5E

// متغیرهای全局
IRrecv irrecv(IR_RECEIVER_PIN);
decode_results results;
unsigned long lastCode = 0;
unsigned long lastPressTime = 0;

void setupIRRemote16CH() {
    Serial.begin(9600);
    Serial.println("ماژول کنترل IR 16 کاناله راه‌اندازی شد");
    Serial.println("=====================================");
    
    // راه‌اندازی گیرنده IR
    irrecv.enableIRIn();
    
    // تنظیم پین LED نشانگر
    pinMode(STATUS_LED_PIN, OUTPUT);
    digitalWrite(STATUS_LED_PIN, LOW);
    
    // نمایش راهنما
    printRemoteLayout();
}

void loop() {
    // بررسی دریافت کد IR
    if (irrecv.decode(&results)) {
        processIRCode(results.value);
        irrecv.resume(); // آماده برای دریافت بعدی
        
        // نشانگر بصری
        blinkStatusLED();
    }
    
    // سایر کارها...
    delay(10);
}

void processIRCode(unsigned long code) {
    // جلوگیری از تکرار سریع
    if (code == lastCode && (millis() - lastPressTime < 200)) {
        return;
    }
    
    lastCode = code;
    lastPressTime = millis();
    
    // شناسایی دکمه فشرده شده
    String buttonName = decodeButton(code);
    
    // نمایش اطلاعات
    Serial.print("کد دریافت شده: 0x");
    Serial.print(code, HEX);
    Serial.print(" | دکمه: ");
    Serial.println(buttonName);
    
    // اجرای عملکرد مربوطه
    executeCommand(buttonName, code);
}

String decodeButton(unsigned long code) {
    // تطبیق کد با دکمه‌ها
    switch(code) {
        case IR_BUTTON_1: return "1";
        case IR_BUTTON_2: return "2";
        case IR_BUTTON_3: return "3";
        case IR_BUTTON_4: return "4";
        case IR_BUTTON_5: return "5";
        case IR_BUTTON_6: return "6";
        case IR_BUTTON_7: return "7";
        case IR_BUTTON_8: return "8";
        case IR_BUTTON_9: return "9";
        case IR_BUTTON_0: return "0";
        case IR_BUTTON_A: return "A";
        case IR_BUTTON_B: return "B";
        case IR_BUTTON_C: return "C";
        case IR_BUTTON_D: return "D";
        case IR_BUTTON_STAR:  return "*";
        case IR_BUTTON_HASH:  return "#";
        default: return "ناشناخته (0x" + String(code, HEX) + ")";
    }
}

void executeCommand(String button, unsigned long code) {
    // اجرای دستورات بر اساس دکمه فشرده شده
    Serial.print("اجرای دستور برای دکمه ");
    Serial.println(button);
    
    if (button == "1") {
        // عملکرد دکمه 1
        channel1Control();
    }
    else if (button == "2") {
        // عملکرد دکمه 2
        channel2Control();
    }
    else if (button == "A") {
        // عملکرد دکمه A
        functionA();
    }
    else if (button == "*") {
        // عملکرد ستاره (مثلاً تنظیمات)
        settingsMenu();
    }
    else if (button == "#") {
        // عملکرد هشتگ (مثلاً تأیید)
        confirmAction();
    }
    
    // می‌توانید برای همه 16 دکمه عملکرد تعریف کنید
}

void blinkStatusLED() {
    // چشمک زدن LED نشانگر
    digitalWrite(STATUS_LED_PIN, HIGH);
    delay(50);
    digitalWrite(STATUS_LED_PIN, LOW);
}

void printRemoteLayout() {
    Serial.println("طرح‌بندی کنترل از راه دور:");
    Serial.println("┌───┬───┬───┬───┐");
    Serial.println("│ 1 │ 2 │ 3 │ A │");
    Serial.println("├───┼───┼───┼───┤");
    Serial.println("│ 4 │ 5 │ 6 │ B │");
    Serial.println("├───┼───┼───┼───┤");
    Serial.println("│ 7 │ 8 │ 9 │ C │");
    Serial.println("├───┼───┼───┼───┤");
    Serial.println("│ * │ 0 │ # │ D │");
    Serial.println("└───┴───┴───┴───┘");
}

کلاس مدیریت پیشرفته کنترل IR:

class AdvancedIRRemoteController {
private:
    int receiverPin;
    int statusLED;
    unsigned long buttonCodes[16];
    String buttonNames[16];
    bool buttonStates[16];
    unsigned long lastPressTime[16];
    unsigned long repeatDelay;
    void (*callbacks[16])();
    
public:
    AdvancedIRRemoteController(int pin, int ledPin = -1) {
        receiverPin = pin;
        statusLED = ledPin;
        repeatDelay = 200; // میلی‌ثانیه
        
        // راه‌اندازی گیرنده
        irrecv = new IRrecv(receiverPin);
        irrecv->enableIRIn();
        
        // تنظیم LED نشانگر
        if (statusLED != -1) {
            pinMode(statusLED, OUTPUT);
        }
        
        // مقداردهی اولیه آرایه‌ها
        initializeButtonData();
        initializeCallbacks();
        
        Serial.println("کنترلر IR پیشرفته راه‌اندازی شد");
    }
    
    void initializeButtonData() {
        // کدهای پیش‌فرض دکمه‌ها
        unsigned long defaultCodes[] = {
            0x45, 0x46, 0x47, 0x44,  // 1,2,3,A
            0x40, 0x43, 0x07, 0x15,  // 4,5,6,B
            0x09, 0x16, 0x19, 0x0D,  // 7,8,9,C
            0x0C, 0x18, 0x5E, 0x52   // *,0,#,D
        };
        
        String defaultNames[] = {
            "1", "2", "3", "A",
            "4", "5", "6", "B",
            "7", "8", "9", "C",
            "*", "0", "#", "D"
        };
        
        for (int i = 0; i < 16; i++) {
            buttonCodes[i] = defaultCodes[i];
            buttonNames[i] = defaultNames[i];
            buttonStates[i] = false;
            lastPressTime[i] = 0;
            callbacks[i] = nullptr;
        }
    }
    
    void update() {
        decode_results results;
        
        if (irrecv->decode(&results)) {
            processReceivedCode(results.value);
            irrecv->resume();
            
            // نشانگر بصری
            indicateReception();
        }
    }
    
    void processReceivedCode(unsigned long code) {
        // جستجوی کد در بین دکمه‌ها
        for (int i = 0; i < 16; i++) {
            if (code == buttonCodes[i]) {
                handleButtonPress(i);
                return;
            }
        }
        
        // اگر کد شناخته شده نبود
        Serial.print("کد ناشناخته: 0x");
        Serial.println(code, HEX);
    }
    
    void handleButtonPress(int buttonIndex) {
        unsigned long currentTime = millis();
        
        // بررسی تکرار سریع
        if (currentTime - lastPressTime[buttonIndex] < repeatDelay) {
            return;
        }
        
        // به‌روزرسانی زمان آخرین فشار
        lastPressTime[buttonIndex] = currentTime;
        
        // تغییر حالت دکمه (toggle)
        buttonStates[buttonIndex] = !buttonStates[buttonIndex];
        
        // نمایش اطلاعات
        Serial.print("دکمه ");
        Serial.print(buttonNames[buttonIndex]);
        Serial.print(" فشرده شد. حالت: ");
        Serial.println(buttonStates[buttonIndex] ? "فعال" : "غیرفعال");
        
        // اجرای تابع callback اگر تعریف شده باشد
        if (callbacks[buttonIndex] != nullptr) {
            callbacks[buttonIndex]();
        }
        
        // اجرای عملکرد عمومی
        executeButtonFunction(buttonIndex);
    }
    
    void setButtonCallback(int buttonIndex, void (*callback)()) {
        if (buttonIndex >= 0 && buttonIndex < 16) {
            callbacks[buttonIndex] = callback;
            Serial.print("تابع برای دکمه ");
            Serial.print(buttonNames[buttonIndex]);
            Serial.println(" تنظیم شد");
        }
    }
    
    void executeButtonFunction(int buttonIndex) {
        // عملکردهای مختلف برای دکمه‌ها
        switch(buttonIndex) {
            case 0: // دکمه 1
                controlChannel(1, buttonStates[buttonIndex]);
                break;
                
            case 1: // دکمه 2
                controlChannel(2, buttonStates[buttonIndex]);
                break;
                
            case 2: // دکمه 3
                controlChannel(3, buttonStates[buttonIndex]);
                break;
                
            case 3: // دکمه A
                functionGroupA(buttonStates[buttonIndex]);
                break;
                
            case 12: // دکمه *
                enterSettingsMode();
                break;
                
            case 14: // دکمه #
                confirmSelection();
                break;
                
            case 15: // دکمه D
                emergencyStop();
                break;
                
            default:
                // عملکرد پیش‌فرض برای دکمه‌های عددی
                if (buttonIndex >= 0 && buttonIndex <= 11) {
                    int channel = buttonIndex + 1;
                    if (channel <= 12) {
                        controlChannel(channel, buttonStates[buttonIndex]);
                    }
                }
                break;
        }
    }
    
    void controlChannel(int channel, bool state) {
        Serial.print("کانال ");
        Serial.print(channel);
        Serial.print(" تنظیم شد به: ");
        Serial.println(state ? "ON" : "OFF");
        
        // در اینجا می‌توانید رله، LED یا سایر دستگاه‌ها را کنترل کنید
        // digitalWrite(channelPins[channel-1], state ? HIGH : LOW);
    }
    
    void functionGroupA(bool state) {
        Serial.print("گروه A ");
        Serial.println(state ? "فعال شد" : "غیرفعال شد");
        
        // کنترل همزمان چند کانال
        if (state) {
            // روشن کردن کانال‌های 1-4
            for (int i = 1; i <= 4; i++) {
                controlChannel(i, true);
            }
        } else {
            // خاموش کردن کانال‌های 1-4
            for (int i = 1; i <= 4; i++) {
                controlChannel(i, false);
            }
        }
    }
    
    void enterSettingsMode() {
        Serial.println("📝 ورود به حالت تنظیمات");
        // کد برای حالت تنظیمات
    }
    
    void confirmSelection() {
        Serial.println("✅ انتخاب تأیید شد");
        // کد برای تأیید
    }
    
    void emergencyStop() {
        Serial.println("🛑 توقف اضطراری فعال شد");
        
        // خاموش کردن همه کانال‌ها
        for (int i = 1; i <= 16; i++) {
            controlChannel(i, false);
        }
    }
    
    void indicateReception() {
        if (statusLED != -1) {
            digitalWrite(statusLED, HIGH);
            delay(20);
            digitalWrite(statusLED, LOW);
        }
    }
    
    void setButtonCode(int buttonIndex, unsigned long newCode) {
        if (buttonIndex >= 0 && buttonIndex < 16) {
            buttonCodes[buttonIndex] = newCode;
            Serial.print("کد دکمه ");
            Serial.print(buttonNames[buttonIndex]);
            Serial.print(" به 0x");
            Serial.println(newCode, HEX);
            Serial.println("تغییر یافت");
        }
    }
    
    void setRepeatDelay(unsigned long delayMs) {
        repeatDelay = delayMs;
        Serial.print("تأخیر تکرار به ");
        Serial.print(delayMs);
        Serial.println("ms تنظیم شد");
    }
    
    bool getButtonState(int buttonIndex) {
        if (buttonIndex >= 0 && buttonIndex < 16) {
            return buttonStates[buttonIndex];
        }
        return false;
    }
    
    String getButtonName(int buttonIndex) {
        if (buttonIndex >= 0 && buttonIndex < 16) {
            return buttonNames[buttonIndex];
        }
        return "نامعتبر";
    }
    
    void printStatus() {
        Serial.println("=== وضعیت کنترلر IR ===");
        Serial.println("دکمه | حالت | آخرین فشار");
        Serial.println("-----|------|------------");
        
        for (int i = 0; i < 16; i++) {
            Serial.print("  ");
            Serial.print(buttonNames[i]);
            Serial.print("  | ");
            Serial.print(buttonStates[i] ? " ON " : " OFF ");
            Serial.print(" | ");
            
            if (lastPressTime[i] > 0) {
                unsigned long secondsAgo = (millis() - lastPressTime[i]) / 1000;
                Serial.print(secondsAgo);
                Serial.println("s پیش");
            } else {
                Serial.println("هرگز");
            }
        }
    }
    
    void learnMode() {
        Serial.println("🎓 فعال کردن حالت یادگیری");
        Serial.println("لطفاً دکمه مورد نظر را فشار دهید...");
        
        unsigned long startTime = millis();
        bool learned = false;
        
        while (millis() - startTime < 10000) { // 10 ثانیه زمان
            decode_results results;
            
            if (irrecv->decode(&results)) {
                Serial.print("کد یاد گرفته شده: 0x");
                Serial.println(results.value, HEX);
                
                // ذخیره کد برای اولین دکمه خالی
                for (int i = 0; i < 16; i++) {
                    if (buttonCodes[i] == 0) {
                        buttonCodes[i] = results.value;
                        Serial.print("کد به دکمه ");
                        Serial.print(buttonNames[i]);
                        Serial.println(" اختصاص داده شد");
                        learned = true;
                        break;
                    }
                }
                
                irrecv->resume();
                
                if (learned) break;
            }
            delay(10);
        }
        
        if (learned) {
            Serial.println("✅ یادگیری موفق");
        } else {
            Serial.println("❌ زمان یادگیری به پایان رسید");
        }
    }
};

⚙️ کاربردهای عملی

۱. سیستم کنترل نور ۱۶ کاناله:

class IRLightingControlSystem {
private:
    AdvancedIRRemoteController irController;
    int relayPins[16];
    bool lightStates[16];
    String lightNames[16];
    
public:
    IRLightingControlSystem(int irPin, int relayPinsArray[16]) 
        : irController(irPin, 13) {
        
        // کپی پین‌های رله
        for (int i = 0; i < 16; i++) {
            relayPins[i] = relayPinsArray[i];
            lightStates[i] = false;
            lightNames[i] = "چراغ " + String(i + 1);
            
            // تنظیم پین‌های رله
            pinMode(relayPins[i], OUTPUT);
            digitalWrite(relayPins[i], LOW); // حالت اولیه خاموش
        }
        
        // تنظیم نام‌های خاص برای برخی چراغ‌ها
        lightNames[0] = "چراغ پذیرایی";
        lightNames[1] = "چراغ آشپزخانه";
        lightNames[2] = "چراغ خواب";
        lightNames[3] = "چراغ راهرو";
        
        // تنظیم توابع callback
        setupCallbacks();
        
        Serial.println("سیستم کنترل نور IR راه‌اندازی شد");
    }
    
    void setupCallbacks() {
        // تنظیم توابع برای دکمه‌ها
        for (int i = 0; i < 16; i++) {
            // ایجاد تابع lambda برای هر دکمه
            irController.setButtonCallback(i, [this, i]() {
                this->toggleLight(i);
            });
        }
        
        // تنظیم توابع خاص برای دکمه‌های عملیاتی
        irController.setButtonCallback(12, [this]() { // دکمه *
            this->allLightsOn();
        });
        
        irController.setButtonCallback(14, [this]() { // دکمه #
            this->allLightsOff();
        });
        
        irController.setButtonCallback(15, [this]() { // دکمه D
            this->emergencyLighting();
        });
    }
    
    void toggleLight(int lightIndex) {
        if (lightIndex >= 0 && lightIndex < 16) {
            lightStates[lightIndex] = !lightStates[lightIndex];
            
            digitalWrite(relayPins[lightIndex], 
                        lightStates[lightIndex] ? HIGH : LOW);
            
            Serial.print(lightNames[lightIndex]);
            Serial.print(" ");
            Serial.println(lightStates[lightIndex] ? "روشن شد" : "خاموش شد");
        }
    }
    
    void allLightsOn() {
        Serial.println("💡 روشن کردن همه چراغ‌ها");
        
        for (int i = 0; i < 16; i++) {
            lightStates[i] = true;
            digitalWrite(relayPins[i], HIGH);
        }
    }
    
    void allLightsOff() {
        Serial.println("🌙 خاموش کردن همه چراغ‌ها");
        
        for (int i = 0; i < 16; i++) {
            lightStates[i] = false;
            digitalWrite(relayPins[i], LOW);
        }
    }
    
    void emergencyLighting() {
        Serial.println("🚨 فعال کردن روشنایی اضطراری");
        
        // خاموش کردن همه چراغ‌ها
        allLightsOff();
        
        // روشن کردن فقط چراغ‌های ضروری
        int essentialLights[] = {0, 3, 7}; // پذیرایی، راهرو، سرویس بهداشتی
        for (int i = 0; i < 3; i++) {
            toggleLight(essentialLights[i]);
        }
    }
    
    void lightShowPattern() {
        Serial.println("✨ نمایش الگوی نور");
        
        // الگوی چشمک زدن
        for (int pattern = 0; pattern < 3; pattern++) {
            switch(pattern) {
                case 0: // یکی در میان
                    for (int i = 0; i < 16; i += 2) {
                        toggleLight(i);
                    }
                    delay(500);
                    for (int i = 0; i < 16; i += 2) {
                        toggleLight(i);
                    }
                    break;
                    
                case 1: // موج
                    for (int i = 0; i < 16; i++) {
                        toggleLight(i);
                        delay(100);
                        toggleLight(i);
                    }
                    break;
                    
                case 2: // همه با هم
                    allLightsOn();
                    delay(300);
                    allLightsOff();
                    break;
            }
            delay(300);
        }
    }
    
    void update() {
        // به‌روزرسانی وضعیت کنترلر IR
        irController.update();
        
        // سایر عملیات...
        static unsigned long lastUpdate = 0;
        if (millis() - lastUpdate > 1000) {
            lastUpdate = millis();
            monitorPowerConsumption();
        }
    }
    
    void monitorPowerConsumption() {
        float totalPower = 0;
        int lightsOn = 0;
        
        for (int i = 0; i < 16; i++) {
            if (lightStates[i]) {
                lightsOn++;
                totalPower += 50; // فرض: هر چراغ 50 وات
            }
        }
        
        if (lightsOn > 0) {
            Serial.print("چراغ‌های روشن: ");
            Serial.print(lightsOn);
            Serial.print(" | مصرف کل: ");
            Serial.print(totalPower);
            Serial.println("W");
        }
    }
    
    void printLightingStatus() {
        Serial.println("=== وضعیت روشنایی ===");
        
        for (int i = 0; i < 16; i++) {
            Serial.print(i + 1);
            Serial.print(". ");
            Serial.print(lightNames[i]);
            Serial.print(": ");
            Serial.println(lightStates[i] ? "✅ روشن" : "❌ خاموش");
        }
    }
};

۲. کنترل ربات ۱۶ کاناله:

class IRRobotController {
private:
    AdvancedIRRemoteController irController;
    int motorPins[4][2]; // 4 موتور، هر کدام 2 پین (جهت و PWM)
    int servoPins[4];    // 4 سروو موتور
    int speed;
    int currentMode; // 0: دستی, 1: نیمه خودکار, 2: خودکار
    
public:
    IRRobotController(int irPin) : irController(irPin) {
        speed = 150; // سرعت پیش‌فرض (0-255)
        currentMode = 0;
        
        // تنظیم پین‌های موتور (مثال)
        motorPins[0][0] = 2; motorPins[0][1] = 3; // موتور چپ
        motorPins[1][0] = 4; motorPins[1][1] = 5; // موتور راست
        motorPins[2][0] = 6; motorPins[2][1] = 7; // موتور بازو
        motorPins[3][0] = 8; motorPins[3][1] = 9; // موتور گیره
        
        // تنظیم پین‌های سروو
        servoPins[0] = 10; // سروو گردن
        servoPins[1] = 11; // سروو شانه
        servoPins[2] = 12; // سروو آرنج
        servoPins[3] = 13; // سروو مچ
        
        // تنظیم پین‌ها
        initializePins();
        
        // تنظیم توابع کنترل
        setupControlFunctions();
        
        Serial.println("کنترلر ربات IR راه‌اندازی شد");
        Serial.println("حالت: دستی");
    }
    
    void initializePins() {
        // تنظیم پین‌های موتور
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 2; j++) {
                pinMode(motorPins[i][j], OUTPUT);
                digitalWrite(motorPins[i][j], LOW);
            }
        }
        
        // تنظیم پین‌های سروو
        for (int i = 0; i < 4; i++) {
            pinMode(servoPins[i], OUTPUT);
        }
    }
    
    void setupControlFunctions() {
        // حرکت ربات
        irController.setButtonCallback(2, [this]() { // دکمه 3: جلو
            this->moveForward();
        });
        
        irController.setButtonCallback(8, [this]() { // دکمه 9: عقب
            this->moveBackward();
        });
        
        irController.setButtonCallback(4, [this]() { // دکمه 5: چرخش چپ
            this->turnLeft();
        });
        
        irController.setButtonCallback(6, [this]() { // دکمه 7: چرخش راست
            this->turnRight();
        });
        
        irController.setButtonCallback(5, [this]() { // دکمه 6: توقف
            this->stopRobot();
        });
        
        // کنترل سرعت
        irController.setButtonCallback(0, [this]() { // دکمه 1: کاهش سرعت
            this->decreaseSpeed();
        });
        
        irController.setButtonCallback(1, [this]() { // دکمه 2: افزایش سرعت
            this->increaseSpeed();
        });
        
        // کنترل سرووها
        irController.setButtonCallback(10, [this]() { // دکمه 9 (بازو بالا)
            this->moveArmUp();
        });
        
        irController.setButtonCallback(11, [this]() { // دکمه C (بازو پایین)
            this->moveArmDown();
        });
        
        // حالت‌های عملیاتی
        irController.setButtonCallback(12, [this]() { // دکمه *: تغییر حالت
            this->changeMode();
        });
        
        irController.setButtonCallback(15, [this]() { // دکمه D: توقف اضطراری
            this->emergencyStop();
        });
    }
    
    void moveForward() {
        if (currentMode == 0) { // فقط در حالت دستی
            Serial.println("🔼 حرکت به جلو");
            
            // کنترل موتورهای چپ و راست
            analogWrite(motorPins[0][0], speed); // موتور چپ جلو
            digitalWrite(motorPins[0][1], LOW);
            
            analogWrite(motorPins[1][0], speed); // موتور راست جلو
            digitalWrite(motorPins[1][1], LOW);
        }
    }
    
    void moveBackward() {
        if (currentMode == 0) {
            Serial.println("🔽 حرکت به عقب");
            
            analogWrite(motorPins[0][1], speed); // موتور چپ عقب
            digitalWrite(motorPins[0][0], LOW);
            
            analogWrite(motorPins[1][1], speed); // موتور راست عقب
            digitalWrite(motorPins[1][0], LOW);
        }
    }
    
    void turnLeft() {
        if (currentMode == 0) {
            Serial.println("↪️ چرخش به چپ");
            
            // موتور راست جلو، موتور چپ عقب
            analogWrite(motorPins[1][0], speed);
            digitalWrite(motorPins[1][1], LOW);
            
            analogWrite(motorPins[0][1], speed);
            digitalWrite(motorPins[0][0], LOW);
        }
    }
    
    void turnRight() {
        if (currentMode == 0) {
            Serial.println("↩️ چرخش به راست");
            
            // موتور چپ جلو، موتور راست عقب
            analogWrite(motorPins[0][0], speed);
            digitalWrite(motorPins[0][1], LOW);
            
            analogWrite(motorPins[1][1], speed);
            digitalWrite(motorPins[1][0], LOW);
        }
    }
    
    void stopRobot() {
        Serial.println("⏹️ توقف ربات");
        
        for (int i = 0; i < 2; i++) { // فقط موتورهای حرکت
            digitalWrite(motorPins[i][0], LOW);
            digitalWrite(motorPins[i][1], LOW);
        }
    }
    
    void increaseSpeed() {
        speed = constrain(speed + 20, 0, 255);
        Serial.print("سرعت افزایش یافت: ");
        Serial.println(speed);
    }
    
    void decreaseSpeed() {
        speed = constrain(speed - 20, 0, 255);
        Serial.print("سرعت کاهش یافت: ");
        Serial.println(speed);
    }
    
    void moveArmUp() {
        Serial.println("🔼 حرکت بازو به بالا");
        // کنترل سروو بازو
        // analogWrite(servoPins[2], angle++);
    }
    
    void moveArmDown() {
        Serial.println("🔽 حرکت بازو به پایین");
        // کنترل سروو بازو
        // analogWrite(servoPins[2], angle--);
    }
    
    void changeMode() {
        currentMode = (currentMode + 1) % 3;
        
        Serial.print("تغییر حالت به: ");
        switch(currentMode) {
            case 0: Serial.println("دستی"); break;
            case 1: Serial.println("نیمه خودکار"); break;
            case 2: Serial.println("خودکار"); break;
        }
        
        if (currentMode == 2) {
            startAutonomousMode();
        }
    }
    
    void startAutonomousMode() {
        Serial.println("🚀 شروع حالت خودکار");
        // الگوریتم‌های حرکت خودکار
    }
    
    void emergencyStop() {
        Serial.println("🚨 توقف اضطراری ربات");
        
        // خاموش کردن همه موتورها
        for (int i = 0; i < 4; i++) {
            digitalWrite(motorPins[i][0], LOW);
            digitalWrite(motorPins[i][1], LOW);
        }
        
        // برگشت به حالت دستی
        currentMode = 0;
    }
    
    void update() {
        irController.update();
        
        // در حالت خودکار، تصمیم‌گیری مستقل
        if (currentMode == 2) {
            autonomousDecisionMaking();
        }
    }
    
    void autonomousDecisionMaking() {
        // الگوریتم‌های هوش مصنوعی ساده
        static unsigned long lastDecision = 0;
        
        if (millis() - lastDecision > 1000) {
            lastDecision = millis();
            
            // تصمیم‌گیری بر اساس سنسورها (شبیه‌سازی)
            int obstacleDistance = random(0, 100); // شبیه‌سازی فاصله
            
            if (obstacleDistance < 20) {
                Serial.println("⚠️ مانع نزدیک - تغییر مسیر");
                avoidObstacle();
            } else {
                moveForward();
            }
        }
    }
    
    void avoidObstacle() {
        // الگوریتم اجتناب از مانع
        stopRobot();
        delay(500);
        turnRight();
        delay(300);
        stopRobot();
    }
    
    void printRobotStatus() {
        Serial.println("=== وضعیت ربات ===");
        Serial.print("حالت: ");
        switch(currentMode) {
            case 0: Serial.println("دستی"); break;
            case 1: Serial.println("نیمه خودکار"); break;
            case 2: Serial.println("خودکار"); break;
        }
        
        Serial.print("سرعت: ");
        Serial.println(speed);
        
        Serial.print("موتورها: ");
        for (int i = 0; i < 4; i++) {
            bool dir1 = digitalRead(motorPins[i][0]);
            bool dir2 = digitalRead(motorPins[i][1]);
            
            Serial.print("M");
            Serial.print(i+1);
            Serial.print(": ");
            
            if (dir1 && !dir2) Serial.print("جلو ");
            else if (!dir1 && dir2) Serial.print("عقب ");
            else Serial.print("توقف ");
        }
        Serial.println();
    }
};

۳. سیستم صوتی چند کاناله:

class IRAudioSystemController {
private:
    AdvancedIRRemoteController irController;
    int volumeLevel;
    int bassLevel;
    int trebleLevel;
    int currentSource; // 0: AUX, 1: Bluetooth, 2: Radio
    bool powerState;
    
public:
    IRAudioSystemController(int irPin) : irController(irPin) {
        volumeLevel = 50; // 0-100
        bassLevel = 0;    // -10 to +10
        trebleLevel = 0;  // -10 to +10
        currentSource = 0;
        powerState = false;
        
        setupAudioControls();
        
        Serial.println("سیستم صوتی IR راه‌اندازی شد");
    }
    
    void setupAudioControls() {
        // کنترل قدرت
        irController.setButtonCallback(0, [this]() { // دکمه 1: روشن/خاموش
            this->togglePower();
        });
        
        // کنترل صدا
        irController.setButtonCallback(1, [this]() { // دکمه 2: افزایش صدا
            this->increaseVolume();
        });
        
        irController.setButtonCallback(2, [this]() { // دکمه 3: کاهش صدا
            this->decreaseVolume();
        });
        
        // کنترل بیس و تریبل
        irController.setButtonCallback(4, [this]() { // دکمه 5: افزایش بیس
            this->increaseBass();
        });
        
        irController.setButtonCallback(5, [this]() { // دکمه 6: کاهش بیس
            this->decreaseBass();
        });
        
        irController.setButtonCallback(6, [this]() { // دکمه 7: افزایش تریبل
            this->increaseTreble();
        });
        
        irController.setButtonCallback(7, [this]() { // دکمه 8: کاهش تریبل
            this->decreaseTreble();
        });
        
        // انتخاب منبع
        irController.setButtonCallback(8, [this]() { // دکمه 9: AUX
            this->selectSource(0);
        });
        
        irController.setButtonCallback(9, [this]() { // دکمه 0: Bluetooth
            this->selectSource(1);
        });
        
        irController.setButtonCallback(10, [this]() { // دکمه A: Radio
            this->selectSource(2);
        });
        
        // کنترل پخش
        irController.setButtonCallback(3, [this]() { // دکمه 4: پخش/مکث
            this->playPause();
        });
        
        irController.setButtonCallback(11, [this]() { // دکمه B: آهنگ بعدی
            this->nextTrack();
        });
        
        irController.setButtonCallback(12, [this]() { // دکمه C: آهنگ قبلی
            this->previousTrack();
        });
        
        // اکولایزر
        irController.setButtonCallback(13, [this]() { // دکمه *: تغییر preset
            this->changeEqualizerPreset();
        });
        
        // حالت سکوت
        irController.setButtonCallback(14, [this]() { // دکمه #: سکوت
            this->toggleMute();
        });
    }
    
    void togglePower() {
        powerState = !powerState;
        
        Serial.print("سیستم ");
        Serial.println(powerState ? "روشن شد" : "خاموش شد");
        
        if (powerState) {
            // اجرای مراحل راه‌اندازی
            initializeAudioSystem();
        } else {
            // خاموش کردن همه بخش‌ها
            shutdownAudioSystem();
        }
    }
    
    void initializeAudioSystem() {
        Serial.println("🎵 راه‌اندازی سیستم صوتی...");
        
        // شبیه‌سازی راه‌اندازی
        for (int i = 0; i < 3; i++) {
            Serial.print(".");
            delay(300);
        }
        Serial.println();
        
        // تنظیمات اولیه
        volumeLevel = 30;
        currentSource = 0;
        
        Serial.println("✅ سیستم صوتی آماده است");
        printAudioStatus();
    }
    
    void shutdownAudioSystem() {
        Serial.println("🔄 خاموش کردن سیستم صوتی...");
        
        // کاهش تدریجی صدا
        for (int i = volumeLevel; i > 0; i -= 10) {
            volumeLevel = i;
            Serial.print("صدا: ");
            Serial.println(volumeLevel);
            delay(100);
        }
        
        volumeLevel = 0;
        Serial.println("✅ سیستم خاموش شد");
    }
    
    void increaseVolume() {
        if (powerState) {
            volumeLevel = constrain(volumeLevel + 5, 0, 100);
            Serial.print("🔊 افزایش صدا به: ");
            Serial.println(volumeLevel);
        }
    }
    
    void decreaseVolume() {
        if (powerState) {
            volumeLevel = constrain(volumeLevel - 5, 0, 100);
            Serial.print("🔉 کاهش صدا به: ");
            Serial.println(volumeLevel);
        }
    }
    
    void increaseBass() {
        if (powerState) {
            bassLevel = constrain(bassLevel + 1, -10, 10);
            Serial.print("🎵 افزایش بیس به: ");
            Serial.println(bassLevel);
        }
    }
    
    void decreaseBass() {
        if (powerState) {
            bassLevel = constrain(bassLevel - 1, -10, 10);
            Serial.print("🎵 کاهش بیس به: ");
            Serial.println(bassLevel);
        }
    }
    
    void increaseTreble() {
        if (powerState) {
            trebleLevel = constrain(trebleLevel + 1, -10, 10);
            Serial.print("🎶 افزایش تریبل به: ");
            Serial.println(trebleLevel);
        }
    }
    
    void decreaseTreble() {
        if (powerState) {
            trebleLevel = constrain(trebleLevel - 1, -10, 10);
            Serial.print("🎶 کاهش تریبل به: ");
            Serial.println(trebleLevel);
        }
    }
    
    void selectSource(int source) {
        if (powerState && source >= 0 && source < 3) {
            currentSource = source;
            
            Serial.print("منبع انتخاب شد: ");
            switch(source) {
                case 0: Serial.println("AUX"); break;
                case 1: Serial.println("Bluetooth"); break;
                case 2: Serial.println("Radio"); break;
            }
        }
    }
    
    void playPause() {
        if (powerState) {
            static bool playing = false;
            playing = !playing;
            
            Serial.println(playing ? "▶️ پخش" : "⏸️ مکث");
        }
    }
    
    void nextTrack() {
        if (powerState) {
            Serial.println("⏭️ آهنگ بعدی");
            // کد تغییر آهنگ
        }
    }
    
    void previousTrack() {
        if (powerState) {
            Serial.println("⏮️ آهنگ قبلی");
            // کد تغییر آهنگ
        }
    }
    
    void changeEqualizerPreset() {
        if (powerState) {
            static int preset = 0;
            preset = (preset + 1) % 5;
            
            Serial.print("🎛️ preset اکولایزر: ");
            switch(preset) {
                case 0: Serial.println("نرمال"); break;
                case 1: Serial.println("پاپ"); break;
                case 2: Serial.println("راک"); break;
                case 3: Serial.println("جاز"); break;
                case 4: Serial.println("کلاسیک"); break;
            }
        }
    }
    
    void toggleMute() {
        if (powerState) {
            static bool muted = false;
            muted = !muted;
            
            if (muted) {
                Serial.println("🔇 حالت سکوت فعال");
            } else {
                Serial.print("🔊 حالت سکوت غیرفعال - صدا: ");
                Serial.println(volumeLevel);
            }
        }
    }
    
    void update() {
        irController.update();
        
        // به‌روزرسانی وضعیت سیستم
        static unsigned long lastUpdate = 0;
        if (millis() - lastUpdate > 5000) {
            lastUpdate = millis();
            systemHealthCheck();
        }
    }
    
    void systemHealthCheck() {
        if (powerState) {
            Serial.println("🔍 بررسی سلامت سیستم صوتی...");
            
            // شبیه‌سازی بررسی
            bool allOK = true;
            
            // بررسی سطح صدا
            if (volumeLevel > 90) {
                Serial.println("⚠️ هشدار: سطح صدا بسیار بالا");
                allOK = false;
            }
            
            // بررسی تنظیمات اکولایزر
            if (abs(bassLevel) > 8 || abs(trebleLevel) > 8) {
                Serial.println("⚠️ هشدار: تنظیمات اکولایزر شدید");
                allOK = false;
            }
            
            if (allOK) {
                Serial.println("✅ سیستم در وضعیت مطلوب");
            }
        }
    }
    
    void printAudioStatus() {
        if (powerState) {
            Serial.println("=== وضعیت سیستم صوتی ===");
            Serial.print("منبع: ");
            switch(currentSource) {
                case 0: Serial.println("AUX"); break;
                case 1: Serial.println("Bluetooth"); break;
                case 2: Serial.println("FM Radio"); break;
            }
            
            Serial.print("صدا: ");
            Serial.print(volumeLevel);
            Serial.print("% | بیس: ");
            Serial.print(bassLevel);
            Serial.print(" | تریبل: ");
            Serial.println(trebleLevel);
            
            // نمایش گرافیکی صدا
            Serial.print("سطح صدا: [");
            int bars = volumeLevel / 10;
            for (int i = 0; i < 10; i++) {
                Serial.print(i < bars ? "█" : "░");
            }
            Serial.println("]");
        } else {
            Serial.println("سیستم صوتی خاموش است");
        }
    }
};

🔧 نصب و راه‌اندازی

مراحل نصب ماژول گیرنده:

void setupIRReceiverModule() {
    Serial.println("=== راهنمای نصب ماژول گیرنده IR ===");
    
    // 1. اتصال سیم‌ها
    Serial.println("1. اتصال سیم‌های ماژول:");
    Serial.println("   VCC → 5V (یا 3.3V)");
    Serial.println("   GND → Ground");
    Serial.println("   OUT → پین دیجیتال (مثلاً پین 11)");
    
    // 2. موقعیت‌دهی گیرنده
    Serial.println("\n2. موقعیت‌دهی گیرنده:");
    Serial.println("   - رو به کنترل از راه دور");
    Serial.println("   - دور از منابع نور مستقیم");
    Serial.println("   - فاصله مناسب (1-8 متر)");
    
    // 3. تست اولیه
    Serial.println("\n3. تست اولیه:");
    testIRReceiverInstallation();
    
    // 4. تنظیم کنترل از راه دور
    Serial.println("\n4. تنظیم کنترل از راه دور:");
    setupRemoteControl();
}

void testIRReceiverInstallation() {
    Serial.println("در حال تست گیرنده IR...");
    Serial.println("لطفاً دکمه‌ای از کنترل از راه دور را فشار دهید");
    
    unsigned long startTime = millis();
    bool received = false;
    
    while (millis() - startTime < 10000) { // 10 ثانیه فرصت
        if (checkIRSignal()) {
            received = true;
            Serial.println("✅ گیرنده به درستی کار می‌کند");
            break;
        }
        delay(100);
    }
    
    if (!received) {
        Serial.println("❌ گیرنده IR پاسخ نمی‌دهد");
        Serial.println("علل احتمالی:");
        Serial.println("- اتصالات را بررسی کنید");
        Serial.println("- باتری کنترل از راه دور");
        Serial.println("- مانع بین کنترل و گیرنده");
    }
}

کالیبراسیون کدهای دکمه:

void calibrateIRRemote() {
    Serial.println("=== کالیبراسیون کنترل از راه دور ===");
    Serial.println("این روال کدهای IR دکمه‌ها را یاد می‌گیرد");
    
    unsigned long learnedCodes[16] = {0};
    String buttonLabels[] = {
        "1", "2", "3", "A",
        "4", "5", "6", "B", 
        "7", "8", "9", "C",
        "*", "0", "#", "D"
    };
    
    for (int i = 0; i < 16; i++) {
        Serial.print("\nلطفاً دکمه ");
        Serial.print(buttonLabels[i]);
        Serial.println(" را فشار دهید...");
        
        unsigned long code = learnSingleButton();
        
        if (code != 0) {
            learnedCodes[i] = code;
            Serial.print("✅ دکمه ");
            Serial.print(buttonLabels[i]);
            Serial.print(": 0x");
            Serial.println(code, HEX);
        } else {
            Serial.print("❌ دریافت کد برای دکمه ");
            Serial.println(buttonLabels[i]);
        }
        
        delay(1000);
    }
    
    // نمایش نتایج
    Serial.println("\n=== نتایج کالیبراسیون ===");
    for (int i = 0; i < 16; i++) {
        if (learnedCodes[i] != 0) {
            Serial.print("#define BUTTON_");
            Serial.print(buttonLabels[i]);
            Serial.print(" 0x");
            Serial.print(learnedCodes[i], HEX);
            Serial.println("");
        }
    }
}

⚡ بهینه‌سازی و نکات فنی

افزایش برد و حساسیت:

void optimizeIRRange() {
    Serial.println("=== بهینه‌سازی برد IR ===");
    
    // 1. استفاده از LED اضافی
    Serial.println("1. افزایش قدرت فرستنده:");
    Serial.println("   - اضافه کردن LED IR موازی");
    Serial.println("   - استفاده از مقاومت مناسب");
    
    // 2. بهبود گیرنده
    Serial.println("\n2. بهبود گیرنده:");
    Serial.println("   - استفاده از فیلتر نوری");
    Serial.println("   - کاهش نویز محیطی");
    Serial.println("   - موقعیت‌دهی صحیح");
    
    // 3. تنظیمات نرم‌افزاری
    Serial.println("\n3. تنظیمات نرم‌افزاری:");
    Serial.println("   - افزایش timeout دریافت");
    Serial.println("   - فیلتر کدهای نامعتبر");
    Serial.println("   - سیستم تکرار خودکار");
}

void increaseTransmitterPower() {
    // مدار افزایش قدرت فرستنده
    Serial.println("مدار تقویت کننده IR:");
    Serial.println("باتری 3V → مقاومت 10Ω → LED IR × 2 (موازی)");
    Serial.println("⚠️ توجه: جریان کل نباید از 100mA تجاوز کند");
}

حل مشکلات رایج:

void troubleshootIRProblems() {
    Serial.println("=== عیب‌یابی مشکلات IR ===");
    
    // جدول مشکلات و راه‌حل‌ها
    String problems[][2] = {
        {"عدم پاسخ کنترل", "بررسی باتری‌ها، خط دید، فاصله"},
        {"پاسخ متناوب", "کاهش نویز، تغییر فرکانس، کالیبراسیون"},
        {"تداخل با دستگاه‌های دیگر", "تغییر کد، استفاده از کدگذاری اختصاصی"},
        {"برد کم", "تمیز کردن لنز، افزایش قدرت، بهبود گیرنده"},
        {"پاسخ نادرست دکمه‌ها", "کالیبراسیون مجدد، بررسی کدها"}
    };
    
    for (int i = 0; i < 5; i++) {
        Serial.print(i + 1);
        Serial.print(". مشکل: ");
        Serial.print(problems[i][0]);
        Serial.print(" - راه‌حل: ");
        Serial.println(problems[i][1]);
    }
}

📦 مشخصات کامل محصول

ویژگی‌های کنترل از راه دور:

  • ابعاد: 90mm × 40mm × 15mm

  • وزن: 38 گرم (با باتری)

  • باتری: 2×AAA (3V)

  • LED نشانگر: قرمز (هنگام ارسال)

  • جنس بدنه: پلاستیک ABS

  • رنگ: معمولاً مشکی

  • طول عمر باتری: 6-12 ماه (با استفاده معمولی)

ویژگی‌های ماژول گیرنده:

  • ماژول: VS1838B یا TSOP38238

  • ولتاژ کاری: 2.7V – 5.5V

  • جریان آماده‌به‌کار: 0.35mA

  • پهنای باند: ±1kHz در 38kHz

  • دمای کاری: -25°C تا +85°C

  • فاصله نصب: توصیه شده 20mm از PCB

گارانتی و پشتیبانی:

  • پشتیبانی فنی رایگان
  • به‌روزرسانی نرم‌افزار

  • کتابخانه‌های آماده آردوینو

  • نمونه کدهای کامل

🌟 نتیجه‌گیری

ماژول کنترل از راه دور مینی مادون قرمز 16 کاناله یک راه‌حل ایده‌آل برای پروژه‌های کنترل بی‌سیم است. با ترکیب سادگی استفاده، قابلیت اطمینان بالا و قیمت مناسب، این ماژول می‌تواند در طیف گسترده‌ای از کاربردها از پروژه‌های آموزشی تا سیستم‌های اتوماسیون خانگی استفاده شود.

کنترل هوشمند، عملکرد مطمئن