ماژول گیرنده RF با کنترلر از راه دور

سیستم کنترل بی‌سیم 315MHz/433MHz با برد بالا

ماژول گیرنده RF همراه با کنترلر از راه دور یک سیستم کنترل بی‌سیم کامل است که بر اساس فرکانس‌های 315MHz یا 433MHz کار می‌کند. این سیستم امکان کنترل بی‌سیم دستگاه‌ها تا فاصله 100 متر (در فضای باز) را فراهم کرده و برای پروژه‌های خانه هوشمند، کنترل ربات‌ها، سیستم‌های امنیتی و اتوماسیون صنعتی ایده‌آل است.


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

  • فرکانس‌های متعدد: 315MHz، 433MHz، 868MHz، 2.4GHz (بسته به مدل)

  • برد مؤثر: تا 100 متر در فضای باز (30-50 متر در فضای بسته)

  • کنترلر 4 کاناله: 4 دکمه مستقل + ترکیبی (تا 15 دستور)

  • کدگذاری دیجیتال: هر کنترلر کد منحصر به فرد دارد

  • ماژول گیرنده حساس: حساسیت بالا تا -105dBm

  • خروجی دیجیتال: داده‌های دکود شده قابل خواندن توسط میکروکنترلر

  • منبع تغذیه دوگانه: کنترلر با باتری 12V/23A، گیرنده با 5V

  • نصب آسان: گیرنده با پین‌های استاندارد 2.54mm

  • مقاوم در برابر نویز: فیلترهای دیجیتال برای کاهش تداخل


مشخصات فنی

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

  • فرکانس کاری: 315MHz یا 433.92MHz

  • ولتاژ کاری: 5V DC (±0.5V)

  • جریان مصرف: 5mA (استندبای)، 10mA (دریافت)

  • حساسیت: -105dBm (برای 433MHz)

  • نرخ داده: تا 10kbps

  • خروجی: دیجیتال (TTL) – داده‌های دکود شده

  • رابط: 4 پین (VCC, GND, DATA, ANT)

  • دمای کاری: -10°C تا +70°C

  • ابعاد: 30mm × 14mm × 7mm

کنترلر از راه دور:

  • فرکانس ارسال: 433.92MHz (مدل رایج)

  • ولتاژ باتری: 12V (باتری 23A)

  • برد مؤثر: 100 متر (فضای باز)

  • دکمه‌ها: 4 دکمه (A, B, C, D)

  • کدها: 1527 کد منحصر به فرد

  • ابعاد: 60mm × 35mm × 15mm

  • آنتن: آنتن سیمی 25cm

کیت کامل شامل:

  1. ماژول گیرنده RF

  2. کنترلر از راه دور 4 دکمه

  3. باتری 12V برای کنترلر

  4. آنتن گیرنده 25cm

  5. هدر پین 4 پین

  6. سیم‌های جامپر


کاربردهای اصلی

  • کنترل درب گاراژ و کرکره برقی

  • سیستم‌های روشنایی بی‌سیم (کنترل چراغ‌ها)

  • کنترل ربات‌های متحرک و پهپادها

  • سیستم‌های امنیتی (آلارم، قفل‌ها)

  • اتوماسیون خانگی (کنترل پرده، پنکه)

  • کنترل از راه دور صنعتی (ماشین‌آلات)

  • دستگاه‌های پزشکی بی‌سیم

  • پروژه‌های دانشجویی و آموزشی


پروتکل ارتباطی

فرمت داده‌های ارسالی:
[پیشوند 24 بیت] + [آدرس 20 بیت] + [داده 4 بیت] + [توقف 4 بیت]

هر دکمه کد منحصر به فرد:
A: 0x0F
B: 0xF0  
C: 0x33
D: 0xCC

ترکیب دکمه‌ها کدهای جدید ایجاد می‌کند:
A+B: 0xFF
A+C: 0x3F
و ...

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

ماژول گیرنده RF ← آردوینو
---------------------------------
VCC  → 5V
GND  → GND
DATA → پایه دیجیتال (مثلاً D2)
ANT  → آنتن (اختیاری، برای برد بیشتر)

کد پایه: دریافت دستورات RF

/*
 * دریافت دستورات از کنترلر RF 433MHz
 * اتصال: پایه DATA گیرنده به D2 آردوینو
 */

#include <VirtualWire.h>

const int receivePin = 2;      // پایه دریافت داده
const int ledPin = 13;         // LED نشانگر دریافت
const int relayPins[] = {8, 9, 10, 11}; // رله‌های کنترل بار

// متغیرهای سیستم
unsigned long lastReceiveTime = 0;
const unsigned long TIMEOUT = 5000; // 5 ثانیه
int lastButton = -1;
int receiveCount = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("\n\n========================================");
  Serial.println("   RF Remote Control Receiver");
  Serial.println("========================================");
  
  // راه‌اندازی پایه‌ها
  pinMode(ledPin, OUTPUT);
  for (int i = 0; i < 4; i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], LOW); // همه رله‌ها خاموش
  }
  
  // راه‌اندازی کتابخانه VirtualWire
  vw_set_rx_pin(receivePin);
  vw_setup(2000); // نرخ بیت 2000bps
  
  vw_rx_start(); // شروع دریافت
  
  Serial.println("Receiver ready. Waiting for RF signals...");
  Serial.println("Buttons: A=Light1, B=Light2, C=Light3, D=Light4");
  Serial.println("A+B=All ON, C+D=All OFF");
  Serial.println("----------------------------------------");
}

void loop() {
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  
  // بررسی دریافت داده
  if (vw_get_message(buf, &buflen)) {
    // دریافت موفق
    digitalWrite(ledPin, HIGH);
    lastReceiveTime = millis();
    receiveCount++;
    
    // تبدیل به رشته
    buf[buflen] = '\0';
    String message = String((char*)buf);
    
    // نمایش اطلاعات دریافت شده
    Serial.print("Received [");
    Serial.print(receiveCount);
    Serial.print("]: ");
    Serial.print(message);
    Serial.print(" (");
    
    // نمایش هگزادسیمال
    for (int i = 0; i < buflen; i++) {
      Serial.print(buf[i], HEX);
      if (i < buflen - 1) Serial.print(":");
    }
    Serial.println(")");
    
    // پردازش دستور
    processCommand(message, buf[0]);
    
    digitalWrite(ledPin, LOW);
  }
  
  // نمایش وضعیت دوره‌ای
  displayStatus();
  
  // بررسی تایم‌اوت
  checkTimeout();
  
  delay(10);
}

void processCommand(String message, byte data) {
  // تشخیص دکمه فشرده شده
  int button = -1;
  
  if (message.indexOf("A") >= 0) button = 0;
  if (message.indexOf("B") >= 0) button = 1;
  if (message.indexOf("C") >= 0) button = 2;
  if (message.indexOf("D") >= 0) button = 3;
  
  // همچنین می‌توان از مقدار هگز استفاده کرد
  switch (data) {
    case 0x0F: // دکمه A
      button = 0;
      break;
    case 0xF0: // دکمه B
      button = 1;
      break;
    case 0x33: // دکمه C
      button = 2;
      break;
    case 0xCC: // دکمه D
      button = 3;
      break;
    case 0xFF: // A+B
      button = 4;
      break;
    case 0x3F: // A+C
      button = 5;
      break;
    case 0xCF: // A+D
      button = 6;
      break;
    case 0xFC: // B+C
      button = 7;
      break;
    case 0xF3: // B+D
      button = 8;
      break;
    case 0x3C: // C+D
      button = 9;
      break;
  }
  
  // اجرای دستور
  executeCommand(button, message);
  
  lastButton = button;
}

void executeCommand(int button, String message) {
  Serial.print("Executing: ");
  
  switch (button) {
    case 0: // دکمه A
      toggleRelay(0);
      Serial.println("Button A - Toggle Light 1");
      break;
      
    case 1: // دکمه B
      toggleRelay(1);
      Serial.println("Button B - Toggle Light 2");
      break;
      
    case 2: // دکمه C
      toggleRelay(2);
      Serial.println("Button C - Toggle Light 3");
      break;
      
    case 3: // دکمه D
      toggleRelay(3);
      Serial.println("Button D - Toggle Light 4");
      break;
      
    case 4: // A+B
      setAllRelays(HIGH);
      Serial.println("A+B - ALL LIGHTS ON");
      break;
      
    case 5: // A+C
      toggleRelays(0, 2);
      Serial.println("A+C - Toggle Lights 1 & 3");
      break;
      
    case 6: // A+D
      toggleRelays(0, 3);
      Serial.println("A+D - Toggle Lights 1 & 4");
      break;
      
    case 7: // B+C
      toggleRelays(1, 2);
      Serial.println("B+C - Toggle Lights 2 & 3");
      break;
      
    case 8: // B+D
      toggleRelays(1, 3);
      Serial.println("B+D - Toggle Lights 2 & 4");
      break;
      
    case 9: // C+D
      setAllRelays(LOW);
      Serial.println("C+D - ALL LIGHTS OFF");
      break;
      
    default:
      Serial.println("Unknown command: " + message);
  }
}

void toggleRelay(int relay) {
  int currentState = digitalRead(relayPins[relay]);
  digitalWrite(relayPins[relay], !currentState);
}

void toggleRelays(int relay1, int relay2) {
  toggleRelay(relay1);
  toggleRelay(relay2);
}

void setAllRelays(int state) {
  for (int i = 0; i < 4; i++) {
    digitalWrite(relayPins[i], state);
  }
}

void displayStatus() {
  static unsigned long lastDisplay = 0;
  
  if (millis() - lastDisplay > 3000) {
    Serial.print("Status: R1=");
    Serial.print(digitalRead(relayPins[0]));
    Serial.print(" R2=");
    Serial.print(digitalRead(relayPins[1]));
    Serial.print(" R3=");
    Serial.print(digitalRead(relayPins[2]));
    Serial.print(" R4=");
    Serial.print(digitalRead(relayPins[3]));
    Serial.print(" | Signals: ");
    Serial.print(receiveCount);
    Serial.print(" | Last: ");
    
    if (lastButton >= 0) {
      char buttonChar = 'A' + (lastButton % 4);
      Serial.print(buttonChar);
      if (lastButton >= 4) {
        Serial.print("+");
        Serial.print((char)('A' + ((lastButton-4)/2)));
      }
    } else {
      Serial.print("None");
    }
    
    Serial.println();
    
    lastDisplay = millis();
  }
}

void checkTimeout() {
  if (millis() - lastReceiveTime > TIMEOUT && lastReceiveTime > 0) {
    Serial.println("No signal for 5 seconds - Receiver idle");
    lastReceiveTime = 0;
  }
}

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

/*
 * سیستم خانه هوشمند با کنترلر RF 433MHz
 * کنترل 8 دستگاه با حالت‌های مختلف
 */

#include <VirtualWire.h>
#include <EEPROM.h>

// پایه‌های گیرنده RF
const int RF_RX_PIN = 2;
const int STATUS_LED = 13;

// پایه‌های خروجی (رله‌ها)
const int OUTPUT_PINS[] = {3, 4, 5, 6, 7, 8, 9, 10};
const int NUM_OUTPUTS = 8;

// دکمه‌های کنترلر
enum RemoteButton {
  BTN_A      = 0x0F,
  BTN_B      = 0xF0,
  BTN_C      = 0x33,
  BTN_D      = 0xCC,
  BTN_A_B    = 0xFF,
  BTN_A_C    = 0x3F,
  BTN_A_D    = 0xCF,
  BTN_B_C    = 0xFC,
  BTN_B_D    = 0xF3,
  BTN_C_D    = 0x3C,
  BTN_A_B_C  = 0x03,
  BTN_B_C_D  = 0x30,
  BTN_A_C_D  = 0x0C,
  BTN_A_B_D  = 0xC0,
  BTN_A_B_C_D= 0x00
};

// حالت‌های سیستم
enum SystemMode {
  MODE_NORMAL,      // کنترل مستقیم
  MODE_SCENE,       // صحنه‌های از پیش تنظیم شده
  MODE_TIMER,       // کنترل زمان‌بندی شده
  MODE_SECURITY     // حالت امنیتی
};

// ساختار ذخیره وضعیت در EEPROM
struct SystemState {
  byte outputStates;
  SystemMode currentMode;
  byte sceneStates[4]; // 4 صحنه ذخیره شده
  unsigned long securityArmedTime;
};

// متغیرهای سیستم
SystemState systemState;
SystemMode currentMode = MODE_NORMAL;
bool securityArmed = false;
unsigned long lastRFTime = 0;
unsigned long lastModeChange = 0;
int currentScene = 0;
const int SCENE_COUNT = 4;

// تایمرهای خودکار
unsigned long autoTimers[NUM_OUTPUTS];
bool autoTimerActive[NUM_OUTPUTS];

void setup() {
  Serial.begin(115200);
  Serial.println("\n\n========================================");
  Serial.println("   SMART HOME RF CONTROL SYSTEM");
  Serial.println("========================================");
  
  // راه‌اندازی پایه‌ها
  initializePins();
  
  // راه‌اندازی RF
  vw_set_rx_pin(RF_RX_PIN);
  vw_setup(2000);
  vw_rx_start();
  
  // بارگذاری وضعیت از EEPROM
  loadSystemState();
  
  // نمایش منوی راهنما
  displayHelp();
  
  Serial.println("System ready. Waiting for RF commands...");
  Serial.println("----------------------------------------");
}

void loop() {
  // دریافت دستورات RF
  checkRFCommands();
  
  // بررسی تایمرهای خودکار
  checkAutoTimers();
  
  // بررسی حالت امنیتی
  if (securityArmed) {
    checkSecurityMode();
  }
  
  // نمایش وضعیت دوره‌ای
  static unsigned long lastStatusDisplay = 0;
  if (millis() - lastStatusDisplay > 5000) {
    displaySystemStatus();
    lastStatusDisplay = millis();
  }
  
  // پردازش دستورات سریال (برای تنظیمات)
  checkSerialCommands();
  
  delay(10);
}

void initializePins() {
  pinMode(STATUS_LED, OUTPUT);
  
  for (int i = 0; i < NUM_OUTPUTS; i++) {
    pinMode(OUTPUT_PINS[i], OUTPUT);
    digitalWrite(OUTPUT_PINS[i], LOW);
    autoTimers[i] = 0;
    autoTimerActive[i] = false;
  }
}

void checkRFCommands() {
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  
  if (vw_get_message(buf, &buflen)) {
    // دریافت موفق
    digitalWrite(STATUS_LED, HIGH);
    lastRFTime = millis();
    
    byte command = buf[0];
    
    Serial.print("RF Command: 0x");
    Serial.print(command, HEX);
    Serial.print(" (");
    printButtonName(command);
    Serial.println(")");
    
    // پردازش دستور بر اساس حالت فعلی
    processRFCommand(command);
    
    // ذخیره وضعیت
    saveSystemState();
    
    digitalWrite(STATUS_LED, LOW);
  }
}

void processRFCommand(byte command) {
  switch (currentMode) {
    case MODE_NORMAL:
      processNormalMode(command);
      break;
    case MODE_SCENE:
      processSceneMode(command);
      break;
    case MODE_TIMER:
      processTimerMode(command);
      break;
    case MODE_SECURITY:
      processSecurityMode(command);
      break;
  }
}

void processNormalMode(byte command) {
  switch (command) {
    case BTN_A: // کنترل خروجی 1
      toggleOutput(0);
      break;
      
    case BTN_B: // کنترل خروجی 2
      toggleOutput(1);
      break;
      
    case BTN_C: // کنترل خروجی 3
      toggleOutput(2);
      break;
      
    case BTN_D: // کنترل خروجی 4
      toggleOutput(3);
      break;
      
    case BTN_A_B: // کنترل خروجی 5
      toggleOutput(4);
      break;
      
    case BTN_A_C: // کنترل خروجی 6
      toggleOutput(5);
      break;
      
    case BTN_A_D: // کنترل خروجی 7
      toggleOutput(6);
      break;
      
    case BTN_B_C: // کنترل خروجی 8
      toggleOutput(7);
      break;
      
    case BTN_B_D: // صحنه 1
      saveScene(0);
      Serial.println("Scene 1 saved");
      break;
      
    case BTN_C_D: // صحنه 2
      saveScene(1);
      Serial.println("Scene 2 saved");
      break;
      
    case BTN_A_B_C: // تمام خروجی‌ها روشن
      setAllOutputs(HIGH);
      Serial.println("ALL OUTPUTS ON");
      break;
      
    case BTN_B_C_D: // تمام خروجی‌ها خاموش
      setAllOutputs(LOW);
      Serial.println("ALL OUTPUTS OFF");
      break;
      
    case BTN_A_C_D: // تغییر حالت
      changeMode();
      break;
      
    case BTN_A_B_D: // حالت امنیتی
      toggleSecurity();
      break;
  }
}

void processSceneMode(byte command) {
  switch (command) {
    case BTN_A: // اجرای صحنه 1
      loadScene(0);
      break;
      
    case BTN_B: // اجرای صحنه 2
      loadScene(1);
      break;
      
    case BTN_C: // اجرای صحنه 3
      loadScene(2);
      break;
      
    case BTN_D: // اجرای صحنه 4
      loadScene(3);
      break;
      
    case BTN_A_C_D: // بازگشت به حالت نرمال
      currentMode = MODE_NORMAL;
      Serial.println("Mode: NORMAL");
      break;
  }
}

void processTimerMode(byte command) {
  // در اینجا منطق کنترل زمان‌بندی شده پیاده‌سازی می‌شود
  switch (command) {
    case BTN_A: // تنظیم تایمر 30 دقیقه برای خروجی 1
      setAutoTimer(0, 30 * 60 * 1000UL); // 30 دقیقه
      break;
      
    case BTN_A_C_D: // بازگشت به حالت نرمال
      currentMode = MODE_NORMAL;
      Serial.println("Mode: NORMAL");
      break;
  }
}

void processSecurityMode(byte command) {
  if (securityArmed) {
    // در حالت امنیتی، فقط کد خاصی سیستم را غیرفعال می‌کند
    if (command == BTN_A_B_C_D) { // کد غیرفعال‌سازی
      securityArmed = false;
      Serial.println("Security DISARMED");
      digitalWrite(STATUS_LED, LOW);
    }
  }
}

void toggleOutput(int output) {
  bool currentState = digitalRead(OUTPUT_PINS[output]);
  digitalWrite(OUTPUT_PINS[output], !currentState);
  
  // به‌روزرسانی وضعیت در حافظه
  systemState.outputStates ^= (1 << output);
  
  Serial.print("Output ");
  Serial.print(output + 1);
  Serial.println(currentState ? " OFF" : " ON");
}

void setAllOutputs(bool state) {
  for (int i = 0; i < NUM_OUTPUTS; i++) {
    digitalWrite(OUTPUT_PINS[i], state);
  }
  
  // به‌روزرسانی وضعیت
  if (state) {
    systemState.outputStates = 0xFF;
  } else {
    systemState.outputStates = 0x00;
  }
  
  Serial.println(state ? "All outputs ON" : "All outputs OFF");
}

void saveScene(int sceneIndex) {
  if (sceneIndex >= 0 && sceneIndex < SCENE_COUNT) {
    systemState.sceneStates[sceneIndex] = systemState.outputStates;
    Serial.print("Scene ");
    Serial.print(sceneIndex + 1);
    Serial.println(" saved");
  }
}

void loadScene(int sceneIndex) {
  if (sceneIndex >= 0 && sceneIndex < SCENE_COUNT) {
    byte sceneState = systemState.sceneStates[sceneIndex];
    
    for (int i = 0; i < NUM_OUTPUTS; i++) {
      bool state = (sceneState >> i) & 1;
      digitalWrite(OUTPUT_PINS[i], state);
    }
    
    systemState.outputStates = sceneState;
    
    Serial.print("Scene ");
    Serial.print(sceneIndex + 1);
    Serial.println(" loaded");
  }
}

void changeMode() {
  currentMode = (SystemMode)((currentMode + 1) % 4);
  lastModeChange = millis();
  
  Serial.print("Mode changed to: ");
  switch (currentMode) {
    case MODE_NORMAL:
      Serial.println("NORMAL");
      break;
    case MODE_SCENE:
      Serial.println("SCENE");
      break;
    case MODE_TIMER:
      Serial.println("TIMER");
      break;
    case MODE_SECURITY:
      Serial.println("SECURITY");
      break;
  }
}

void toggleSecurity() {
  securityArmed = !securityArmed;
  
  if (securityArmed) {
    systemState.securityArmedTime = millis();
    Serial.println("Security ARMED");
    digitalWrite(STATUS_LED, HIGH);
    
    // در حالت امنیتی، همه خروجی‌ها خاموش می‌شوند
    setAllOutputs(LOW);
  } else {
    Serial.println("Security DISARMED");
    digitalWrite(STATUS_LED, LOW);
  }
}

void setAutoTimer(int output, unsigned long duration) {
  if (output >= 0 && output < NUM_OUTPUTS) {
    autoTimers[output] = millis() + duration;
    autoTimerActive[output] = true;
    
    // روشن کردن خروجی
    digitalWrite(OUTPUT_PINS[output], HIGH);
    systemState.outputStates |= (1 << output);
    
    Serial.print("Timer set for output ");
    Serial.print(output + 1);
    Serial.print(": ");
    Serial.print(duration / 60000);
    Serial.println(" minutes");
  }
}

void checkAutoTimers() {
  for (int i = 0; i < NUM_OUTPUTS; i++) {
    if (autoTimerActive[i] && millis() >= autoTimers[i]) {
      // زمان تایمر به پایان رسیده
      digitalWrite(OUTPUT_PINS[i], LOW);
      autoTimerActive[i] = false;
      systemState.outputStates &= ~(1 << i);
      
      Serial.print("Timer expired - Output ");
      Serial.print(i + 1);
      Serial.println(" OFF");
    }
  }
}

void checkSecurityMode() {
  // چشمک زدن LED وضعیت در حالت امنیتی
  static unsigned long lastBlink = 0;
  static bool blinkState = false;
  
  if (millis() - lastBlink > 500) {
    blinkState = !blinkState;
    digitalWrite(STATUS_LED, blinkState);
    lastBlink = millis();
  }
  
  // نمایش مدت زمان فعال بودن امنیت
  static unsigned long lastSecurityDisplay = 0;
  if (millis() - lastSecurityDisplay > 60000) { // هر 1 دقیقه
    unsigned long armedTime = (millis() - systemState.securityArmedTime) / 60000;
    Serial.print("Security armed for ");
    Serial.print(armedTime);
    Serial.println(" minutes");
    lastSecurityDisplay = millis();
  }
}

void printButtonName(byte command) {
  switch (command) {
    case BTN_A: Serial.print("A"); break;
    case BTN_B: Serial.print("B"); break;
    case BTN_C: Serial.print("C"); break;
    case BTN_D: Serial.print("D"); break;
    case BTN_A_B: Serial.print("A+B"); break;
    case BTN_A_C: Serial.print("A+C"); break;
    case BTN_A_D: Serial.print("A+D"); break;
    case BTN_B_C: Serial.print("B+C"); break;
    case BTN_B_D: Serial.print("B+D"); break;
    case BTN_C_D: Serial.print("C+D"); break;
    case BTN_A_B_C: Serial.print("A+B+C"); break;
    case BTN_B_C_D: Serial.print("B+C+D"); break;
    case BTN_A_C_D: Serial.print("A+C+D"); break;
    case BTN_A_B_D: Serial.print("A+B+D"); break;
    case BTN_A_B_C_D: Serial.print("A+B+C+D"); break;
    default: Serial.print("Unknown");
  }
}

void displaySystemStatus() {
  Serial.print("Status: ");
  
  // نمایش وضعیت خروجی‌ها
  Serial.print("Outputs: ");
  for (int i = 0; i < NUM_OUTPUTS; i++) {
    Serial.print(digitalRead(OUTPUT_PINS[i]));
    if (i < NUM_OUTPUTS - 1) Serial.print("-");
  }
  
  Serial.print(" | Mode: ");
  switch (currentMode) {
    case MODE_NORMAL: Serial.print("NORMAL"); break;
    case MODE_SCENE: Serial.print("SCENE"); break;
    case MODE_TIMER: Serial.print("TIMER"); break;
    case MODE_SECURITY: Serial.print("SECURITY"); break;
  }
  
  Serial.print(" | Security: ");
  Serial.print(securityArmed ? "ARMED" : "DISARMED");
  
  Serial.println();
}

void checkSerialCommands() {
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    command.trim();
    
    if (command == "help") {
      displayHelp();
    }
    else if (command == "status") {
      displayDetailedStatus();
    }
    else if (command == "reset") {
      resetSystem();
    }
    else if (command.startsWith("set ")) {
      // دستور تنظیم خروجی: set 1 on
      int output = command.substring(4, 5).toInt() - 1;
      String state = command.substring(6);
      
      if (output >= 0 && output < NUM_OUTPUTS) {
        if (state == "on") {
          digitalWrite(OUTPUT_PINS[output], HIGH);
          systemState.outputStates |= (1 << output);
          Serial.print("Output ");
          Serial.print(output + 1);
          Serial.println(" ON");
        } else if (state == "off") {
          digitalWrite(OUTPUT_PINS[output], LOW);
          systemState.outputStates &= ~(1 << output);
          Serial.print("Output ");
          Serial.print(output + 1);
          Serial.println(" OFF");
        }
      }
    }
  }
}

void displayHelp() {
  Serial.println("\n=== SMART HOME CONTROL SYSTEM ===");
  Serial.println("RF Remote Commands:");
  Serial.println("A/B/C/D     - Control outputs 1-4");
  Serial.println("A+B/A+C/A+D - Control outputs 5-7");
  Serial.println("B+C         - Control output 8");
  Serial.println("B+D/C+D     - Save scenes 1-2");
  Serial.println("A+B+C       - All ON");
  Serial.println("B+C+D       - All OFF");
  Serial.println("A+C+D       - Change mode");
  Serial.println("A+B+D       - Toggle security");
  Serial.println("\nSerial Commands:");
  Serial.println("help        - Show this help");
  Serial.println("status      - Show detailed status");
  Serial.println("set X on/off- Manual control");
  Serial.println("reset       - Reset system");
  Serial.println("==============================\n");
}

void displayDetailedStatus() {
  Serial.println("\n=== SYSTEM DETAILED STATUS ===");
  
  Serial.println("Output States:");
  for (int i = 0; i < NUM_OUTPUTS; i++) {
    Serial.print("  ");
    Serial.print(i + 1);
    Serial.print(": ");
    Serial.print(digitalRead(OUTPUT_PINS[i]) ? "ON" : "OFF");
    
    if (autoTimerActive[i]) {
      unsigned long remaining = (autoTimers[i] - millis()) / 1000;
      Serial.print(" (Timer: ");
      Serial.print(remaining);
      Serial.print("s)");
    }
    Serial.println();
  }
  
  Serial.println("\nSaved Scenes:");
  for (int i = 0; i < SCENE_COUNT; i++) {
    Serial.print("  Scene ");
    Serial.print(i + 1);
    Serial.print(": ");
    printBinary(systemState.sceneStates[i]);
    Serial.println();
  }
  
  Serial.print("\nCurrent Mode: ");
  switch (currentMode) {
    case MODE_NORMAL: Serial.println("NORMAL"); break;
    case MODE_SCENE: Serial.println("SCENE"); break;
    case MODE_TIMER: Serial.println("TIMER"); break;
    case MODE_SECURITY: Serial.println("SECURITY"); break;
  }
  
  Serial.print("Security: ");
  Serial.println(securityArmed ? "ARMED" : "DISARMED");
  
  if (securityArmed) {
    unsigned long armedTime = (millis() - systemState.securityArmedTime) / 60000;
    Serial.print("Armed for: ");
    Serial.print(armedTime);
    Serial.println(" minutes");
  }
  
  Serial.println("=============================\n");
}

void printBinary(byte value) {
  for (int i = 7; i >= 0; i--) {
    Serial.print((value >> i) & 1);
  }
}

void resetSystem() {
  Serial.println("Resetting system...");
  
  // خاموش کردن همه خروجی‌ها
  setAllOutputs(LOW);
  
  // ریست متغیرها
  currentMode = MODE_NORMAL;
  securityArmed = false;
  
  for (int i = 0; i < NUM_OUTPUTS; i++) {
    autoTimerActive[i] = false;
    autoTimers[i] = 0;
  }
  
  // پاک کردن صحنه‌ها
  for (int i = 0; i < SCENE_COUNT; i++) {
    systemState.sceneStates[i] = 0;
  }
  
  saveSystemState();
  
  Serial.println("System reset complete");
}

void saveSystemState() {
  systemState.currentMode = currentMode;
  EEPROM.put(0, systemState);
}

void loadSystemState() {
  EEPROM.get(0, systemState);
  
  // اعمال وضعیت ذخیره شده
  currentMode = (SystemMode)systemState.currentMode;
  
  for (int i = 0; i < NUM_OUTPUTS; i++) {
    bool state = (systemState.outputStates >> i) & 1;
    digitalWrite(OUTPUT_PINS[i], state);
  }
  
  // اگر امنیتی فعال بود، LED را روشن کن
  if (systemState.securityArmedTime > 0) {
    // بررسی اینکه آیا هنوز باید فعال باشد
    unsigned long elapsed = millis() - systemState.securityArmedTime;
    if (elapsed < 24UL * 60 * 60 * 1000) { // حداکثر 24 ساعت
      securityArmed = true;
      digitalWrite(STATUS_LED, HIGH);
    } else {
      systemState.securityArmedTime = 0;
    }
  }
}

کد ارسال کننده RF (کنترلر مجازی)

/*
 * کنترلر RF مجازی با آردوینو
 * برای تست گیرنده یا ایجاد کنترلرهای سفارشی
 */

#include <VirtualWire.h>

const int transmitPin = 12;    // پایه ارسال داده
const int ledPin = 13;         // LED نشانگر ارسال
const int buttonPins[] = {2, 3, 4, 5}; // دکمه‌های کنترل

// کدهای دکمه‌ها
const char* buttonCodes[] = {
  "A",  // دکمه 1
  "B",  // دکمه 2
  "C",  // دکمه 3
  "D"   // دکمه 4
};

// کدهای هگز برای پروتکل 1527
const byte hexCodes[] = {
  0x0F, // A
  0xF0, // B
  0x33, // C
  0xCC  // D
};

// متغیرهای سیستم
unsigned long lastPressTime[4] = {0, 0, 0, 0};
const unsigned long DEBOUNCE_DELAY = 200; // 200ms
bool lastButtonState[4] = {HIGH, HIGH, HIGH, HIGH};
int transmitCount = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("\n\n========================================");
  Serial.println("   RF Transmitter - Virtual Remote");
  Serial.println("========================================");
  
  // راه‌اندازی پایه‌ها
  pinMode(ledPin, OUTPUT);
  for (int i = 0; i < 4; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
  }
  
  // راه‌اندازی فرستنده RF
  vw_set_tx_pin(transmitPin);
  vw_setup(2000); // نرخ بیت 2000bps
  
  Serial.println("Virtual Remote Ready");
  Serial.println("Press buttons 1-4 to send RF commands");
  Serial.println("Button mapping: 1=A, 2=B, 3=C, 4=D");
  Serial.println("Hold two buttons for combination");
  Serial.println("----------------------------------------");
}

void loop() {
  // خواندن دکمه‌ها
  bool buttonStates[4];
  for (int i = 0; i < 4; i++) {
    buttonStates[i] = digitalRead(buttonPins[i]);
  }
  
  // تشخیص فشار دکمه
  for (int i = 0; i < 4; i++) {
    // اگر دکمه فشرده شد (LOW) و قبلاً فشرده نبود
    if (buttonStates[i] == LOW && lastButtonState[i] == HIGH) {
      // Debouncing
      if (millis() - lastPressTime[i] > DEBOUNCE_DELAY) {
        // ارسال کد دکمه
        sendRFCommand(i);
        lastPressTime[i] = millis();
      }
    }
    
    lastButtonState[i] = buttonStates[i];
  }
  
  // تشخیص ترکیب دکمه‌ها (اگر دو دکمه همزمان فشرده شوند)
  checkButtonCombinations(buttonStates);
  
  // نمایش وضعیت دوره‌ای
  static unsigned long lastStatus = 0;
  if (millis() - lastStatus > 10000) {
    Serial.print("Transmissions: ");
    Serial.println(transmitCount);
    lastStatus = millis();
  }
  
  delay(10);
}

void sendRFCommand(int buttonIndex) {
  transmitCount++;
  
  // روشن کردن LED
  digitalWrite(ledPin, HIGH);
  
  // ارسال کد متنی
  const char* message = buttonCodes[buttonIndex];
  vw_send((uint8_t*)message, strlen(message));
  vw_wait_tx(); // منتظر اتمام ارسال
  
  // ارسال کد هگز (برای سازگاری با گیرنده‌های مختلف)
  byte hexCode = hexCodes[buttonIndex];
  vw_send(&hexCode, 1);
  vw_wait_tx();
  
  Serial.print("Sent: Button ");
  Serial.print(buttonIndex + 1);
  Serial.print(" (");
  Serial.print(message);
  Serial.print("/0x");
  Serial.print(hexCode, HEX);
  Serial.println(")");
  
  digitalWrite(ledPin, LOW);
}

void sendCombination(int button1, int button2) {
  transmitCount++;
  
  digitalWrite(ledPin, HIGH);
  
  // ایجاد پیام ترکیبی
  char message[3];
  message[0] = 'A' + button1;
  message[1] = '+';
  message[2] = 'A' + button2;
  
  vw_send((uint8_t*)message, 3);
  vw_wait_tx();
  
  // کد هگز ترکیبی
  byte hexCode = hexCodes[button1] & hexCodes[button2];
  vw_send(&hexCode, 1);
  vw_wait_tx();
  
  Serial.print("Sent: ");
  Serial.print(message);
  Serial.print(" (0x");
  Serial.print(hexCode, HEX);
  Serial.println(")");
  
  digitalWrite(ledPin, LOW);
}

void checkButtonCombinations(bool states[4]) {
  static unsigned long lastComboTime = 0;
  
  // شمارش دکمه‌های فشرده شده
  int pressedCount = 0;
  int pressedButtons[4] = {-1, -1, -1, -1};
  
  for (int i = 0; i < 4; i++) {
    if (states[i] == LOW) {
      pressedButtons[pressedCount] = i;
      pressedCount++;
    }
  }
  
  // اگر دو دکمه فشرده شده باشند
  if (pressedCount == 2) {
    // Debouncing برای ترکیب
    if (millis() - lastComboTime > DEBOUNCE_DELAY) {
      sendCombination(pressedButtons[0], pressedButtons[1]);
      lastComboTime = millis();
    }
  }
  
  // اگر سه دکمه فشرده شده باشند
  if (pressedCount == 3) {
    if (millis() - lastComboTime > DEBOUNCE_DELAY) {
      // ارسال کد ترکیبی سه دکمه
      byte hexCode = hexCodes[pressedButtons[0]] & 
                    hexCodes[pressedButtons[1]] & 
                    hexCodes[pressedButtons[2]];
      
      digitalWrite(ledPin, HIGH);
      vw_send(&hexCode, 1);
      vw_wait_tx();
      
      Serial.print("Sent: 3-button combo (0x");
      Serial.print(hexCode, HEX);
      Serial.println(")");
      
      digitalWrite(ledPin, LOW);
      lastComboTime = millis();
    }
  }
  
  // اگر چهار دکمه فشرده شده باشند
  if (pressedCount == 4) {
    if (millis() - lastComboTime > DEBOUNCE_DELAY) {
      // کد تمام دکمه‌ها
      byte hexCode = 0x00; // همه دکمه‌ها
      
      digitalWrite(ledPin, HIGH);
      vw_send(&hexCode, 1);
      vw_wait_tx();
      
      Serial.println("Sent: ALL BUTTONS (0x00)");
      
      digitalWrite(ledPin, LOW);
      lastComboTime = millis();
    }
  }
}

نکات نصب و بهینه‌سازی

افزایش برد ارتباطی:

  1. استفاده از آنتن مناسب:

    • آنتن 1/4 موج: 17.3cm برای 433MHz

    • آنتن سیمی: 25-30cm به صورت مستقیم

    • آنتن هلیکال: برای بردهای بسیار دور

  2. بهینه‌سازی موقعیت:

    // کد برای پیدا کردن بهترین موقعیت
    void findOptimalPosition() {
      // تست دریافت در موقعیت‌های مختلف
      // ذخیره قدرت سیگنال
      // انتخاب موقعیت با بیشترین قدرت
    }
  3. کاهش نویز:

    • استفاده از خازن 100µF نزدیک VCC گیرنده

    • شیلد کردن مدار با فویل آلومینیوم

    • دوری از منابع نویز (موتورها، ترانسفورماتورها)

عیب‌یابی:

مشکل علت راه‌حل
عدم دریافت فرکانس نادرست مطمئن شوید فرستنده و گیرنده فرکانس یکسان دارند
برد کم آنتن ضعیف آنتن بلندتر نصب کنید
تداخل نویز محیط تغییر فرکانس یا کانال
باتری ضعیف ولتاژ پایین تعویض باتری کنترلر
گرم شدن گیرنده اتصال کوتاه بررسی اتصالات

افزایش امنیت:

// کدگذاری پیشرفته
void sendEncrypted(byte data, byte key) {
  byte encrypted = data ^ key; // XOR ساده
  vw_send(&encrypted, 1);
}

// چک‌سم
void sendWithChecksum(byte data) {
  byte checksum = calculateChecksum(data);
  byte packet[2] = {data, checksum};
  vw_send(packet, 2);
}

پروژه‌های پیشنهادی

1. سیستم کنترل گاراژ هوشمند

// باز و بست در گاراژ با تایمر ایمنی

2. ربات کنترلی 4 کاناله

// کنترل حرکت ربات در 4 جهت

3. سیستم آبیاری باغچه

// کنترل پمپ آب از راه دور

4. دزدگیر ماشین ساده

// فعال‌سازی و غیرفعال‌سازی از راه دور

5. کنترل سیستم صوتی

// کنترل پخش موسیقی و تنظیم صدا

جدول مقایسه فناوری‌های بی‌سیم

فناوری فرکانس برد مصرف انرژی پیچیدگی
RF 433MHz 433MHz 100m کم ساده
RF 315MHz 315MHz 80m کم ساده
2.4GHz 2.4GHz 50m متوسط متوسط
بلوتوث 2.4GHz 10m کم متوسط
WiFi 2.4/5GHz 50m بالا پیچیده
ZigBee 2.4GHz 100m بسیار کم پیچیده

پکیج خرید

پکیج پایه:

  • 1x ماژول گیرنده RF 433MHz

  • 1x کنترلر از راه دور 4 دکمه

  • 1x باتری 12V برای کنترلر

  • 1x آنتن گیرنده 25cm

  • 1x هدر پین 4 پین

  • راهنمای نصب فارسی

پکیج پیشرفته:

  • 2x گیرنده RF (433MHz و 315MHz)

  • 2x کنترلر (4 دکمه و 8 دکمه)

  • 1x برد رله 4 کاناله

  • 4x سوکت باتری 12V

  • 2x آنتن بهینه‌شده

  • نرم‌افزار کنترل تحت ویندوز

پکیج توسعه‌دهنده:

  • 5x گیرنده RF

  • 5x کنترلر مختلف

  • 1x فرستنده RF برای آردوینو

  • 1x آنتن حرفه‌ای SMA

  • 1x کیت تست سیگنال

  • کتابچه پروتکل‌های RF


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

  • پشتیبانی: رایگان از طریق تلگرام
  • آموزش: ویدیوهای تنظیم و برنامه‌نویسی

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

  • جامعه: گروه کاربران ایرانی RF


سؤالات متداول

Q1: آیا می‌توان چند کنترلر با یک گیرنده استفاده کرد؟
بله، هر کنترلر کد منحصر به فرد دارد. گیرنده می‌تواند تا 1527 کد مختلف را تشخیص دهد.

Q2: حداکثر برد واقعی در شهر چقدر است؟
در شهر با موانع زیاد: 20-30 متر | در فضای باز: 80-100 متر

Q3: آیا با ریموت درب گاراژ موجود کار می‌کند؟
بله، اگر فرکانس یکسان باشد (معمولاً 433.92MHz). ممکن است نیاز به کدخوانی داشته باشید.

Q4: چگونه از تداخل با دستگاه‌های دیگر جلوگیری کنم؟

  • تغییر کد کنترلر

  • استفاده از فرکانس 315MHz (کمتر شلوغ)

  • افزودن کد شناسه منحصر به فرد

Q5: آیا می‌توانم برد را به 1 کیلومتر برسانم؟
با تقویت کننده (PA) و آنتن بهینه، بله. ولی نیاز به مجوز رادیویی دارد.


توجه: استفاده از فرستنده‌های RF با قدرت بالا نیاز به مجوز از سازمان تنظیم مقررات رادیویی دارد. برای کاربردهای صنعتی و برد بالا حتماً با کارشناسان ما مشورت کنید.