در آموزشهای قبلی آموزش آردوینو به تولید تنهای صوتی بدون تداخل با PWM و کنترل MIDI پرداختیم. در این قسمت قصد داریم در مورد واکنش به ریموت کنترل مادون قرمز و رمزگشایی سیگنالهای آن صحبت کنیم.
فرض کنید میخواهید آردوینو به فشرده شدن هر دکمهای روی ریموت کنترل تلویزیون یا هر ریموت کنترل دیگری واکنش نشان دهد.
آردوینو با استفاده از قطعهای به نام ماژول گیرنده IR میتواند سیگنالهای ریموت مادون قرمز را دریافت و پردازش کند.
از مدلهای رایج این ماژول میتوان به TSOP38238، TSOP4838، PNA4602 و TSOP2438 اشاره کرد. سه مدل اول آرایش پایه یکسانی دارند، بنابراین مدار آنها نیز یکسان است؛ اما در مدل TSOP2438 جای پایههای +5V و GND برعکس است. برای اطمینان از اتصال درست، حتماً برگه مشخصات فنی یا Datasheet قطعه خود را بررسی کنید.
در این پروژه از کتابخانه IRremote استفاده میکنیم که میتوانید آن را از طریق Library Manager در محیط آردوینو نصب کنید. ماژول گیرنده مادون قرمز را مطابق دیتاشیت آن به برد وصل کنید. سیمکشی نشاندادهشده در شکل 56-1 برای مدلهای TSOP38238، TSOP4838 و PNA4602 است.
sketch زیر باعث میشود با فشردن هر دکمه روی ریموت کنترل مادون قرمز، LED داخلی آردوینو تغییر وضعیت دهد و روشن یا خاموش شود.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/* IR_remote_detector sketch An IR remote receiver is connected to pin 2. The built-in LED toggles each time a button on the remote is pressed. */ #include <IRremote.h> // adds the library code to the sketch const int irReceiverPin = 2; // pin the receiver is connected to const int ledPin = LED_BUILTIN; IRrecv irrecv(irReceiverPin); // create an IRrecv object decode_results decodedSignal; // stores results from IR detector void setup() { pinMode(ledPin, OUTPUT); irrecv.enableIRIn(); // Start the receiver object } bool lightState = LOW; // keep track of whether the LED is on unsigned long last = millis(); // remember when we last received an IR message void loop() { if (irrecv.decode(&decodedSignal) == true) // this is true if a message has // been received { if (millis() - last > 250) { // has it been 1/4 sec since last message? if (lightState == LOW) lightState = HIGH; else lightState = LOW; lightState = lightState ; // Yes: toggle the LED digitalWrite(ledPin, lightState); } last = millis(); irrecv.resume(); // watch out for another message } } |

شکل 1-56 – اتصال یک ماژول گیرنده مادون قرمز
اگر از برد 3/3 ولتی استفاده میکنید که تحمل ورودی 5 ولت ندارد، باید ماژول گیرنده مادون قرمز را بهجای 5 ولت، از 3/3 ولت تغذیه کنید.
ماژول گیرنده IR سیگنال مادون قرمز را به مجموعهای از پالسهای دیجیتال تبدیل میکند. این پالسها دنبالهای از صفرها و یکها هستند که هر کدام متناظر با یکی از دکمههای ریموت کنترل هستند. کتابخانه IRremote این پالسها را رمزگشایی کرده و برای هر دکمه یک مقدار عددی در اختیار sketch قرار میدهد. (مقادیر دریافتی sketch به نوع ریموت کنترلی که استفاده میکنید بستگی دارد.)
قرار دادن دستور زیر در ابتدای sketch، امکانات کتابخانه IRremote را در اختیار برنامه قرار میدهد:
|
1 |
#include <IRremote.h> |
همچنین دستور زیر شیئی از کلاس IRrecv با نام irrecv ایجاد میکند تا سیگنالهای ارسالی از ماژول گیرنده مادون قرمز متصل به پایه irReceiverPin، که در این مثال پایه 2 است، را دریافت کند.:
|
1 |
IRrecv irrecv(irReceiverPin); |
شما از شیء irrecv برای دسترسی به سیگنال گیرنده IR استفاده میکنید. میتوانید به آن دستور دهید که به دنبال سیگنالها بگردد و آنها را رمزگشایی کند. پاسخهای رمزگشاییشدهای که توسط کتابخانه فراهم میشوند در متغیری به نام decode_results ذخیره میشوند. شیء گیرنده (irrecv) در setup با خط irrecv.enableIRIn(); شروع به کار میکند. نتایج در loop با فراخوانی تابع irrecv.decode(&decodedSignal) بررسی میشوند.
تابع decode اگر دادهای وجود داشته باشد مقدار true برمیگرداند، و آن داده در متغیر decodedSignal قرار میگیرد. دستورالعمل 2.11 توضیح میدهد که چگونه نماد ampersand در فراخوانی تابعهایی استفاده میشود که پارامترهای آنها تغییر میکنند تا اطلاعات بتواند به عقب برگردانده شود.
اگر پیامی از ریموت دریافت شده باشد، کد LED را تغییر وضعیت میدهد (وضعیت آن را برعکس میکند)، به شرطی که از آخرین باری که تغییر وضعیت داده شده بیشتر از یکچهارم ثانیه گذشته باشد (در غیر این صورت، در ریموتهایی که هنگام فشار دادن دکمه، کدها را بیش از یکبار ارسال میکنند، LED خیلی سریع روشن و خاموش میشود و ممکن است به نظر برسد به شکل تصادفی چشمک میزند).
متغیر decodedSignal مقداری را در خود خواهد داشت که به یک کلید مرتبط است. این مقدار در این دستورالعمل نادیده گرفته میشود، هرچند در دستورالعمل بعدی استفاده خواهد شد. شما میتوانید با افزودن خط Serial.println که در کد زیر برجسته شده است، مقدار را چاپ کنید. (همچنین باید Serial.begin(9600); را در تابع setup اضافه کنید):
|
1 2 3 4 5 |
if (irrecv.decode(&decodedSignal) == true) // this is true if a message has // been received { if (millis() - last > 250) { // has it been 1/4 sec since last message Serial.println(decodedSignal.value); |
باید به کتابخانه گفته شود که پایش سیگنالها را ادامه دهد و این کار با خط irrecv.resume(); انجام میشود.
این sketch هنگامی که هر دکمهای روی ریموت کنترل فشرده شود یک LED را چشمکزن میکند، اما شما میتوانید چیزهای دیگری را هم کنترل کنید؛ برای مثال، میتوانید از یک stepper motor برای چرخاندن knob روی چراغ یا استریو استفاده کنید.
فرض کنید میخواهید یک کلید خاص را که روی کنترل تلویزیون یا ریموت کنترل دیگری فشرده شده است تشخیص دهید.
این sketch از فشرده شدن کلیدهای ریموت کنترل برای تنظیم روشنایی یک LED استفاده میکند. هنگام شروع sketch، کدها برای کلیدهای 0 تا 4 ریموت کنترل درخواست میشوند. این کدها در حافظه آردوینو (RAM) ذخیره میشوند و سپس sketch با تنظیم روشنایی LED متناسب با دکمه فشردهشده به این کلیدها پاسخ میدهد، به طوری که 0 باعث خاموش شدن LED میشود و کلیدهای 1 تا 4 روشنایی را به صورت مرحلهای افزایش میدهند:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
/* * RemoteDecode sketch * Infrared remote control signals are decoded to control LED brightness. * The values for keys 0-4 are detected and stored when the sketch starts. * Key 0 turns the LED off; brightness increases in steps with keys 1-4. */ #include <IRremote.h> // IR remote control library const int irReceivePin = 2; // pin connected to IR detector output const int ledPin = 9; // LED is connected to a PWM pin const int numberOfKeys = 5; // 5 keys are learned (0 through 4) long irKeyCodes[numberOfKeys]; // holds the codes for each key IRrecv irrecv(irReceivePin); // create the IR library decode_results results; // IR data goes here void setup() { Serial.begin(9600); while(!Serial); // Needed for Leonardo and ARM boards pinMode(irReceivePin, INPUT); pinMode(ledPin, OUTPUT); irrecv.enableIRIn(); // Start the IR receiver learnKeycodes(); // learn remote control key codes Serial.println("Press a remote key"); } void loop() { long key; int brightness; if (irrecv.decode(&results)) { // here if data is received irrecv.resume(); key = convertCodeToKey(results.value); if(key >= 0) { Serial.print("Got key "); Serial.println(key); brightness = map(key, 0,numberOfKeys-1, 0, 255); analogWrite(ledPin, brightness); } } } /* * get remote control codes */ void learnKeycodes() { while(irrecv.decode(&results)) // empty the buffer irrecv.resume(); Serial.println("Ready to learn remote codes"); long prevValue = -1; int i=0; while(i < numberOfKeys) { Serial.print("press remote key "); Serial.print(i); while(true) { if(irrecv.decode(&results)) { if(results.value != -1 && results.decode_type != UNKNOWN && results.value != prevValue) { showReceivedData(); Serial.println(results.value); irKeyCodes[i] = results.value; i = i + 1; prevValue = results.value; irrecv.resume(); // Receive the next value break; } irrecv.resume(); // Receive the next value } } } Serial.println("Learning complete"); } /* * converts a remote protocol code to a logical key code * (or -1 if no digit received) */ int convertCodeToKey(long code) { for(int i=0; i < numberOfKeys; i++) { if(code == irKeyCodes[i]) { return i; // found the key so return it } } return -1; } /* * display the protocol type and value */ void showReceivedData() { if (results.decode_type == UNKNOWN) { Serial.println("-Could not decode message"); } else { if (results.decode_type == NEC) { Serial.print("- decoded NEC: "); } else if (results.decode_type == SONY) { Serial.print("- decoded SONY: "); } else if (results.decode_type == RC5) { Serial.print("- decoded RC5: "); } else if (results.decode_type == RC6) { Serial.print("- decoded RC6: "); } Serial.print("hex value = "); Serial.println( results.value, HEX); } } |
این راهحل بر اساس کتابخانه IRremote است.
این sketch کتابخانه ریموت کنترل را با کد زیر شروع میکند:
|
1 |
irrecv.enableIRIn(); // Start the IR receiver |
سپس تابع learnKeyCodes را فراخوانی میکند تا از کاربر بخواهد کلیدهای 0 تا 4 را فشار دهد. کد هر کلید در آرایهای به نام irKeyCodes ذخیره میشود. پس از اینکه تمام کلیدها شناسایی و ذخیره شدند، کد loop منتظر فشرده شدن یک کلید میماند و بررسی میکند که آیا این کلید یکی از ارقام ذخیرهشده در آرایه irKeyCodes بوده است یا خیر. اگر چنین باشد، از مقدار آن برای کنترل روشنایی یک LED با استفاده از analogWrite استفاده میشود.
برای اطلاعات بیشتر درباره استفاده از تابع map و analogWrite برای کنترل روشنایی LED، دستورالعمل 5.7 را ببینید.
کتابخانه باید بتواند تقریباً با هر ریموت کنترل IR کار کند؛ این کتابخانه میتواند زمانبندیها را کشف و به خاطر بسپارد و در صورت دستور، سیگنال را تکرار کند.
میتوانید مقادیر کد کلیدها را به صورت دائمی ذخیره کنید تا لازم نباشد هر بار که sketch را شروع میکنید آنها را یاد بگیرید. اعلان irKeyCodes را با خطوط زیر جایگزین کنید تا مقادیر هر کلید مقداردهی اولیه شوند، و فراخوانی learnKeycodes(); را به صورت comment درآورید. مقادیر را طوری تغییر دهید که با مقادیر ریموت شما مطابقت داشته باشند (این مقادیر هنگامی که کلیدها را در تابع learnKeyCodes فشار میدهید در Serial Monitor نمایش داده میشوند):
|
1 2 3 4 5 6 7 |
long irKeyCodes[numberOfKeys] = { 0x18E758A7, //0 key 0x18E708F7, //1 key 0x18E78877, //2 key 0x18E748B7, //3 key 0x18E7C837, //4 key }; |
آموزش ساخت Synthesizer صوتی با Arduino
من کاپیتان آردوینو، اسمم میلاده و اینجا هستم تا تجربیاتم در رابطه با آردوینو رو با شما به اشتراک بزارم!
سیسوگ با افتخار فضایی برای اشتراک گذاری دانش شماست. برای ما مقاله بنویسید.