ذخیره ریموت کنترل (رادیویی) RF کدلرن در آردوینو و ESP8266

محتوا

ریموت کنترل کد لرن (Learning Code)

در این آموزش نحوه ست کردن ریموت رو با فشار دادن یک دکمه رو به شما در آردوینو و ESP8266 یاد می دهم ، این جزء مواردی بود که خودم هم دنبالش بودم و با کمی تست چندین روش برای ذخیره کد های ریموت پیدا کردم که یکی از این روش رو در این آموزش ارائه می دهم. اول از اینکه در مورد ریموت های کد لرن باید بگم که با فشار دادن هر دکمه یک کد برای شما ارسال می کند که در ریموت های 24 بیتی 20 بیت اول آدرس و 4 بیت آخر مربوط به دکمه ها است و این مقادیر ثابت هستند و کمک می کند با روش های مختلف بدون نیاز به ذخیره همه کلید ها ، کد ارسالی رو تشخیص داد.

تجزیه و تحلیل کد های ارسال توسط ریموت کنترل کد لرن

همان طور که در زیر مشاهده می کنید 20 بیت اول ارسالی کلید ها شبیه هم هستند و 4 بیت آخر هم که مربوط به کلید های یک ریموت 4 دکمه ایی است با فقط با جابجا شد بیت 1 چهار کد متفاوت ایجاد کرده است پس برای ذخیره کردن ریموت فقط کافی است یک دکمه را ذخیره کنید و بعد برای تشخیص دکمه دیگر بودن ذخیره کردن با مقایسه 20 بیت اول دستورات متفاوتی اجرا کنید.

Button 1:
Decimal: 8571080 (24Bit)
Binary: 100000101100100011001000
Tri-State: not applicable
PulseLength: 321 microseconds
Protocol: 1
Raw data: 9964,956,332,312,976,312,976,308,980,304,980,308,980,952,340,304,980,956,336,188,908,276,728,264,124,168,308,60,24,60,236,88,88,204,88,76,80,56,1020,284,440,56,24,40,100,84,12,36,56,

Button      Address                               Data
Button 1: 10000010110010001100 1000
Button 2: 10000010110010001100 0100
Button 3: 10000010110010001100 0010
Button 4: 10000010110010001100 0001

برای درک بهتر این موضوع و کدی برای شما آماده کردم که تمام این موارد انجام شده و حتی قالبیت ذخیره 100 ریموت رو به شما می دهد که بر اساس ظرفیت حافظه EEPROM تغییر می کند.

نحوه ذخیره 100 ریموت کنترل RF کد لرن در آردوینو و ESP8266

کتابخونه مورد نیاز رو از اینجا دانلود کنید. این کد رو برای برد های آردوینو و ماژول ESP8266 می تونید استفاده کنید فقط در برد Uno مقدار mySwitch.enableReceive(14) برابر صفر و در ESP8266 برابر 14 قرار بدهید در این پروژه بر روی پایه 14 تنظیم شده چون کد رو بر روی ESP8266 تست زدم ، نکته بعدی در Uno بعد از دستور EEPROM.write برای ذخیره نیاز به دستور EEPROM.commit() نیست ولی برای ESP8266 حتما باید بعد از هر بار نوشتن این دستور هم اجرا بشه ، برای ذخیره هر ریموت 4 بایت از حافظه EEPROM استفاده می شود که من در اینجا حافظه ی EEPROM رو با ظرفیت 1024 بایت پیکربندی کردم و این مورد فقط در ESP8266 استفاده می شود که حداکثر 2048 است.

#include <RCSwitch.h>
#include <EEPROM.h>
#include <Arduino.h> 
 
RCSwitch mySwitch = RCSwitch();
 
int Store = 1;
boolean Reg = false;
unsigned long int Time;

void EEPROMWritelong(int address, long value){
  int Wadr = address * 4;
 
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);
 
  EEPROM.write(Wadr, four);
  //EEPROM.commit();   //Use only in ESP8266 
  delay(5);
  EEPROM.write(Wadr + 1, three);
  //EEPROM.commit();   //Use only in ESP8266 
  delay(5);
  EEPROM.write(Wadr + 2, two);
  //EEPROM.commit();   //Use only in ESP8266 
  delay(5);
  EEPROM.write(Wadr + 3, one);
  //EEPROM.commit();   //Use only in ESP8266 
  delay(5);
}
 
long EEPROMReadlong(int address){
  int Wadr = address * 4;
 
  long four = EEPROM.read(Wadr);
  delay(5);
  long three = EEPROM.read(Wadr + 1);
  delay(5);
  long two = EEPROM.read(Wadr + 2);
  delay(5);
  long one = EEPROM.read(Wadr + 3);
  delay(5);
 
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}
 
String InttobinStr(unsigned long Dec, unsigned int bitLength) {
  static char bin[64];
  unsigned int i=0;
 
  while (Dec > 0) {
    bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0';
    Dec = Dec >> 1;
  }
 
  for (unsigned int j = 0; j < bitLength; j++) {
   if (j >= bitLength - i) {
      bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
    } else {
      bin[j] = '0';
   }
  }
  bin[bitLength] = '\0';
 
  return String(bin);
}
 
boolean Comparison(String comp1, String comp2, String recv){
  if (comp1 == comp2){
    Serial.print("matched Ok > ");
    String Button = recv.substring(20, 24);
 
    if((Button) == "0001") {Serial.println("UP");}
    if((Button) == "0010") {Serial.println("DOWN");}
    if((Button) == "0100") {Serial.println("Look");}
    if((Button) == "1000") {Serial.println("Unlook");}
    return true;
  } else {
    return false;
  }
}

void DeleteRemote(int ID){
  EEPROMWritelong(ID, 0);
}
 
void setup() {
  Serial.begin(9600);
  Serial.println("Start");
  //EEPROM.begin(1024);  //Use only in ESP8266 
  mySwitch.enableReceive(0); // Use only in Uno &amp; Nano
  // mySwitch.enableReceive(14);  //Use only in ESP8266 
 /* for(int i=0;i<=512;i++){
    EEPROM.write(i, 0);
    delay(10);
  }*/
}
 
void loop() {
  if (mySwitch.available()) {
    Serial.println(InttobinStr(mySwitch.getReceivedValue(), 24));
 
    if (Reg){
      EEPROMWritelong(Store, mySwitch.getReceivedValue());
      Reg = false;
      Serial.println("Saved into ID "+String(Store));
    }
  
    if (!Reg){
      String Recv = InttobinStr(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength());
 
      for(int I=1;I<=100;I++){
        long RegID = EEPROMReadlong(I);
        String SavedID = InttobinStr(RegID, 24);
 
        String Comp1 = SavedID.substring(0, 20);
        String Comp2 = Recv.substring(0, 20);
 
        if (Comparison(Comp1, Comp2, Recv)){break;}
        if (I == 100){Serial.println("Not matched");}
      }
    }
 
    mySwitch.resetAvailable();
  }
 
  if (Serial.available()){
    String CMD = Serial.readString();
 
    if (CMD.indexOf("REG") != -1){
      CMD.replace("REG=", "");
      Store = CMD.toInt();
      Time = (millis()/1000)+30;
      Reg = true;
      Serial.println("Press any button...");
    }
 
    if (CMD == "RUN"){
      Reg = false;
    }
  }
 
  if((millis()/1000) == Time or Reg == true){
    Reg = false;
     Serial.println("Timeout");
  }
}

 

نحوه عمکرد هم به این صورت است که با ارسال درستور REG=x در سریال ترمینال به برنامه منتظر دریافت کد به مدت 30 ثانیه می ماند که دستور دریافت کد ذخیره و در صورت سپری شدن زمان 30 ثانیه پیغام Timeout به شما نشان می دهد ، x شماره حافظه است. خط 90 تا 93 که یه فرمت کامنت تغییر برای پاک کردن کامل حافظه EEPROM است و نکته ایی رو باید در نظر داشته باشید که مقدار REG برابر 0 نباشد.

اجرای عملکردهای مختلف به وسیله یک دکمه با رویداد OnLongPress (هنگام فشار دادن طولانی)

برای اینکه بتونید فقط با یک دکمه چندین عملکرد مختلف داشته باشین مثل: اضافه کردن ریموت ، حذف همه ی ریموت ها و ریست کلی قطعه کدی رو آماده کردم که در زیر مشاهده می کنید. درصورتی که دکمه را به مدت 1 الی 2 ثانیه فشار دهید و سپس رها کنید متن “Press any button…” در سریال ترمینال چاپ می شود ، در صورتی که دکمه را بین 4 الی 6 ثانیه فشار دهید و سپس رها کنید متن “Remove all remote’s” در سریال مانیتور چاپ می شود و در صورتی که دکمه را بیش 9 ثانیه فشار دهید و سپس رها کنید متن “Factory reset” در سریال مانیتور چاپ می شود.

#include <Arduino.h> 
 
unsigned long int LongPress = 0;
boolean onepush = false;
 
void setup() {
  pinMode(16, INPUT);
  Serial.begin(115200):
}
 
void loop() {
 
  if(digitalRead(16) == 1){
    if (onepush == false){
      onepush = true;
      LongPress = (millis()/1000); 
    }
  }
 
  if(digitalRead(16) == 0){
    if (onepush == true){ 
       onepush = false;
       int func = (millis()/1000)-LongPress;
       
       if (func >= 1 and func <= 3){
	      Serial.println("Press any button…");
          //کد های خود را اینجا بویسید
       }
 
       if (func >= 4 and func <= 6){
	      Serial.println("Remove all remote’s");
          //کد های خود را اینجا بویسید
       }
 
       if (func >= 9){
	      Serial.println("Factory reset");
          //کد های خود را اینجا بویسید
       }
    }
  }
}

ذخیره خودکار کد ریموت به ترتیب در حافظه

توسط قطعه کد زیر که باید جایگزین خط 104 تا 108 شود ، کد دریافتی از ریموت به صورت خودکار در اولین حافظه خالی که مقدارش برابر با صفر باشد ذخیره و شماره حافظه ایی که کد ذخیره شده رو در سریال مانیتور چاپ می کند نکته: برای ذخیره ریموت این بار فقط کلمه REG رو ارسال کنید و شماره حافظه رو نیاز نیست تعیین کنید.

if (Reg){
   for (int i=1; i<=100;i++){
      if (EEPROMReadlong(i) == 0){
          EEPROMWritelong(i, mySwitch.getReceivedValue());
          Reg = false;
          Serial.println("Saved into ID "+String(i));
          break;
      }
   } 
}

3.7 6 votes
امتیازدهی به مقاله
بخش نظرات
مشترک شوید
Notify of
guest
69 نظرات
قدیمی ترین
جدیدترین بیشترین آرای
Inline Feedbacks
View all comments
محمدرضا
محمدرضا
4 years ago

سلام نشکر از پست خیلی خیلی مفیدتون
ببخشید ی سوال داشتم شما تو این پست نوشتین ((در این آموزش نحوه ست کردن ریموت رو با فشار دادن یک دکمه رو به شما در آردوینو میدهم)) منظور دکمه لرن هست ؟؟ اگه هست کجا تعریف شده ؟؟ اگه میشه یه راهنمایی کنین بدجور لازم دارم

مجتبی
مجتبی
4 years ago

واسم این خطا میاد WARNING: Category ‘Device Control, Signal Input/Output’ in library rc-switch is not valid. Setting to ‘Uncategorized’

مجتبی
مجتبی
4 years ago

ممنون بابت پاسخ منrc-switch رو اپدیت کرم این خطا رو داد پاکش کردم دباره نصب کردم بعد اردینو رو هم اپدیت کردم خطا از بین رفت حالا یه مشکل دیگه امد اینکه وقتی این ReceiveDemo_Advanced رو از کتاب خونه میریزم داخل اردینو داخل ترمینال هیچ کدی نمیاد کلن صفحه خلیه من هم با اردینو انو هم با نانو امتحان کردم همین مشکل دارم سه تا مازول با فر کانس مختلف و همینتور ریموت مختلف این کارو کردم

مجتبی
مجتبی
4 years ago

ببخش وقتتو گرفتم به 2 تغییر دادم فقط یک بار کار کرد باز یک بار یگه برنامه رو رو اردینو ریختم دیگه عمل نمی کنه

مجتبی
مجتبی
4 years ago
Reply to  مجتبی

مشکل حل شد درایور دوبار نصب کرم درست شد

hasan
hasan
4 years ago

سلام تشکر از پست بسیار مفیدتون
فقط یک مشکلی که هست من مقدار mySwitch.enableReceive( رو صفر گذاشتم ولی هیچ عکس العملی از اردینو دریافت نکردم و یک سواله دیگه قسمت دوم آموزش رو جایگزین viod loop آموزش اولی کنیم ؟؟

hasan
hasan
4 years ago

ببخشید 2 هم کردم واکنشی نداشت بنظرتون مشکل از کجا میتونه باشه >؟؟ ممکن از RF باشه؟

hasan
hasan
4 years ago

بله پایه دیتای گیرنده رو به ی بار به صفر و ی بار به 2وصل کردم ، اسم گیرنده rx470rالبته سه تاگیرنده دارم هر سه هم 432 امتحان کردم باز جواب نداد

مجتبی
مجتبی
4 years ago

سلام ببخشید باز وقت شماروگرفتم چرا همش داخل ترمینا همش مینویسهNot matched

مجتبی
مجتبی
4 years ago

ببخشید اینهمه می پرسم اول اینکه کجای کد باید حافظه رو تغییر بدم بعد خود کد این کارو انجام نمیده یعنی باید هر دفه برای هر ریموت این کار رو بکنی

مجتبی
مجتبی
4 years ago

جواب گرفتم دستت درد نکنه راهی هم هست این کارو دستی انجام ندیم

محمدرضا
محمدرضا
4 years ago

سلام خسته نباشید
اگه لطف کنین زودتر اضافه کنین خیلی خیلی ممنون میشم چون بد جور لازم دارم

محمد
محمد
4 years ago

سلام ممنون از مطلب خوبتون فقط یه سوال میشه بجای esp8266 از nrf24l01 استفاده کرد؟؟

محمد
محمد
4 years ago
Reply to  محمد

ممنون فقط یه سوال یعنی میشه به جای rf433 از nrf استفاده کرد یا اون یه پروژه جداست؟

ahmad
ahmad
4 years ago

با سلام و ممنون از پست خوبتون
یه سوال داشتم این کد به چه درد میخوره آیا میشه این کدو درون یک ریموت دیگه ست کرد؟
ممنونم

Ali
Ali
4 years ago

سلام سپاس از پروژه خوبتون چجوری میتونیم یک ریموت رو حذف کنیم میشه روشش رو بگید یا خودتون کد رو اپدیت کنید تشکر

69
0
Would love your thoughts, please comment.x
×
×

سبد خرید