ریموت کنترل کد لرن (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 & 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 and 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;
}
}
}
سلام نشکر از پست خیلی خیلی مفیدتون
ببخشید ی سوال داشتم شما تو این پست نوشتین ((در این آموزش نحوه ست کردن ریموت رو با فشار دادن یک دکمه رو به شما در آردوینو میدهم)) منظور دکمه لرن هست ؟؟ اگه هست کجا تعریف شده ؟؟ اگه میشه یه راهنمایی کنین بدجور لازم دارم
آموزش بروز رسانی شد
واسم این خطا میاد WARNING: Category ‘Device Control, Signal Input/Output’ in library rc-switch is not valid. Setting to ‘Uncategorized’
چه نسخه ایی از نرم افزار آردوینو رو استفاده می کنید؟
چه بردی؟
نسخه rc-switch چند است؟
یه توضیح در این مورد در لینک زیر است
https://github.com/sui77/rc-switch/issues/100
و اینکه پیغام توجه است نه خطا ، که مشکلی ایجاد نمی کنه
ممنون بابت پاسخ منrc-switch رو اپدیت کرم این خطا رو داد پاکش کردم دباره نصب کردم بعد اردینو رو هم اپدیت کردم خطا از بین رفت حالا یه مشکل دیگه امد اینکه وقتی این ReceiveDemo_Advanced رو از کتاب خونه میریزم داخل اردینو داخل ترمینال هیچ کدی نمیاد کلن صفحه خلیه من هم با اردینو انو هم با نانو امتحان کردم همین مشکل دارم سه تا مازول با فر کانس مختلف و همینتور ریموت مختلف این کارو کردم
در آردوینو یونو (Uno) یا نانو (Nano) باید در خط زیر تغییر ایجاد کنی
mySwitch.enableReceive(14); // Receiver on interrupt 0 => that is pin #2
و عدد 14 رو به 2 تغییر بدی
اینو انجام دادی؟
ببخش وقتتو گرفتم به 2 تغییر دادم فقط یک بار کار کرد باز یک بار یگه برنامه رو رو اردینو ریختم دیگه عمل نمی کنه
مشکل حل شد درایور دوبار نصب کرم درست شد
سلام تشکر از پست بسیار مفیدتون
فقط یک مشکلی که هست من مقدار mySwitch.enableReceive( رو صفر گذاشتم ولی هیچ عکس العملی از اردینو دریافت نکردم و یک سواله دیگه قسمت دوم آموزش رو جایگزین viod loop آموزش اولی کنیم ؟؟
باید ۲ باشه برای برد آردوینو یونو و نانو
قسمت دوم باید ترکیب بشه با قسمت اول
ببخشید 2 هم کردم واکنشی نداشت بنظرتون مشکل از کجا میتونه باشه >؟؟ ممکن از RF باشه؟
گیرنده رو به پایه 2 وصل کردید؟
چی مدلی است گیرنده؟
بله پایه دیتای گیرنده رو به ی بار به صفر و ی بار به 2وصل کردم ، اسم گیرنده rx470rالبته سه تاگیرنده دارم هر سه هم 432 امتحان کردم باز جواب نداد
بیاین داخل گروه اونجا بهتر میشه مشکل رو فهمید
https://t.me/joinchat/B2oyXER9Oa6YNBpI0jI7dw
سلام ببخشید باز وقت شماروگرفتم چرا همش داخل ترمینا همش مینویسهNot matched
اولین اینکه کدها آپدیت شده همین الان دوباره کپی کنید
و دوم باید حتما ریموت رو در حافظه 1 الی 100 ذخیره کنید
ببخشید اینهمه می پرسم اول اینکه کجای کد باید حافظه رو تغییر بدم بعد خود کد این کارو انجام نمیده یعنی باید هر دفه برای هر ریموت این کار رو بکنی
توی سریال مانیتور REG=1 رو ارسال کنی کد ریموت در حافظه شماره 1 ذخیره میشه و فقط یکبار اینکار رو انجام میدی
جواب گرفتم دستت درد نکنه راهی هم هست این کارو دستی انجام ندیم
بله
به کد ها اضاف می کنم
سلام خسته نباشید
اگه لطف کنین زودتر اضافه کنین خیلی خیلی ممنون میشم چون بد جور لازم دارم
اضاف شد
آموزش رو نگاه کنید مجدد و کد رو تست کنید
سلام ممنون از مطلب خوبتون فقط یه سوال میشه بجای esp8266 از nrf24l01 استفاده کرد؟؟
نه
ماژول esp از یک میکرو پروسسور استفاده می کنه که قابلیت کد نویسی داره ولی nrf فقط یک فرستنده و گیرنده است
ممنون فقط یه سوال یعنی میشه به جای rf433 از nrf استفاده کرد یا اون یه پروژه جداست؟
به این روش آره میشه
با سلام و ممنون از پست خوبتون
یه سوال داشتم این کد به چه درد میخوره آیا میشه این کدو درون یک ریموت دیگه ست کرد؟
ممنونم
برنامه ریزی ریموت که نه و اصلا نیازی نیست
ولی میشه با این کد تجهیزات رو هم با گوشی و هم با ریموت های 433 موجود در بازار کنترل کرد
حالا اینجا نحوه ست کردن چند ریموت رو با ماژول وای فای و گیرنده 433 آموزش دادم
سلام سپاس از پروژه خوبتون چجوری میتونیم یک ریموت رو حذف کنیم میشه روشش رو بگید یا خودتون کد رو اپدیت کنید تشکر
سلام تابع DeleteRemote(int ID) به کدها اضاف شد