赤外線リモコンを学習して送信する [Arduino]
テレビなどのリモコンの赤外線信号を「赤外線リモコン受信モジュール」(PL-IRM1261-C438)で取得して、ブレッドボードのボタンを押した時にその赤外線を「赤外線LED」(OSI5LA5113A)で送信します。
[TVを操作する例]
1. 使用部品・材料
総額で約500円です。(Arduino本体の値段を除く)
部品/材料 | 値段 | 備考 |
---|---|---|
ブレッドボード | ¥270 | 秋月電子の通販コード(P-00315) |
赤外線リモコン受信モジュール PL-IRM1261-C438 | ¥100 | 秋月電子の通販コード(I-04169) |
5mm赤外線LED OSI5LA5113A | ¥100 | 秋月電子の通販コード(I-04311) |
5mm赤色LED OSDR5113A | ¥20 | 秋月電子の通販コード(I-11655) |
タクトスイッチ | ¥10 | 秋月電子の通販コード(P-03647) |
カーボン抵抗器 | 数円 | 10kΩ(1個)、220Ω(2個)、47Ω(1個)を使用。 |
コネクタ付コード(みの虫×ジャンパーワイヤ) | 任意 | 赤外線LEDの延長用。 秋月電子の通販コード(C-08916) |
LED光拡散キャップ(5mm) 白 日本製 | 任意 | 赤外線LEDの送信用。(なくてもOK!) 秋月電子の通販コード(I-00641) |
[上記外で動作確認済みの部品]
5mm赤外線LED OSI5FU5111C-40(5個入) | ¥100 | 秋月電子の通販コード(I-03261) |
GaAs赤外LED NJL1104B | ¥30 | 秋月電子の通販コード(I-11570) |
赤外線リモコン受信モジュール PL-IRM2121(38kHz) | ¥100 | 秋月電子の通販コード(I-01570) |
[動作しなかった部品]
5mm赤外線LED OSI3CA5111A | ¥150 | ピーク波長が原因(?)。使い方次第で動作するかも知れません。 秋月電子の通販コード(I-04779) |
赤外線リモコン受信モジュール SPS-448-1(38kHz) | ¥30 | なんらかのデータは受信できますが、受信データがおかしいです。このSPSシリーズは相性が悪いのかも知れません。 秋月電子の通販コード(I-00872) |
大面積Si PINフォトダイオードS6775-01(可視光カット) | ¥200 | これは上級者が使用する部品のようです。(今の私にはまだ扱えません) 秋月電子の通販コード(I-06183) |
2. 配線図
3. スケッチ(プログラム)
今回はオープンソースの「Arduino-IRremote」という赤外線のライブラリを使用しますのでダウンロードします。
インストールする前に...
C:Program Files (x86)Arduinolibraries
にある「RobotIRremote」というライブラリのフォルダを丸ごと別のフォルダに移動します。これは同じ作者が作成しているので「IRremote.h」というヘッダファイルが重複してしまうからです。
インストール方法
Arduino IDEのメニューの[スケッチ][ライブラリをインクルード][ZIP形式のライブラリをインストール]を選択して、ダウンロードしたファイルを指定するだけです。
スケッチ
今回のスケッチはArduino IDEのメニューの[ファイル][スケッチ例][IRremote][IRrecord]を使用します。
...
なんですが、このスケッチ例には「送信処理に不具合」がありましたので修正版を公開します。
※元のコードは崩さずに160,170-172,175,181,182行目を追加。180行目のdelay(50)をdelay(100)に変更。
/* * IRrecord: record and play back IR signals as a minimal * An IR detector/demodulator must be connected to the input RECV_PIN. * An IR LED must be connected to the output PWM pin 3. * A button must be connected to the input BUTTON_PIN; this is the * send button. * A visible LED can be connected to STATUS_PIN to provide status. * * The logic is: * If the button is pressed, send the IR code. * If an IR code is received, record it. * * Version 0.11 September, 2009 * Copyright 2009 Ken Shirriff * http://arcfn.com */ #include <IRremote.h> int RECV_PIN = 11; int BUTTON_PIN = 12; int STATUS_PIN = 13; IRrecv irrecv(RECV_PIN); IRsend irsend; decode_results results; void setup() { Serial.begin(9600); irrecv.enableIRIn(); // Start the receiver pinMode(BUTTON_PIN, INPUT); pinMode(STATUS_PIN, OUTPUT); } // Storage for the recorded code int codeType = -1; // The type of code unsigned long codeValue; // The code value if not raw unsigned int rawCodes[RAWBUF]; // The durations if raw int codeLen; // The length of the code int toggle = 0; // The RC5/6 toggle state // Stores the code for later playback // Most of this code is just logging void storeCode(decode_results *results) { codeType = results->decode_type; int count = results->rawlen; if (codeType == UNKNOWN) { Serial.println("Received unknown code, saving as raw"); codeLen = results->rawlen - 1; // To store raw codes: // Drop first value (gap) // Convert from ticks to microseconds // Tweak marks shorter, and spaces longer to cancel out IR receiver distortion for (int i = 1; i <= codeLen; i++) { if (i % 2) { // Mark rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS; Serial.print(" m"); } else { // Space rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS; Serial.print(" s"); } Serial.print(rawCodes[i - 1], DEC); } Serial.println(""); } else { if (codeType == NEC) { Serial.print("Received NEC: "); if (results->value == REPEAT) { // Don't record a NEC repeat value as that's useless. Serial.println("repeat; ignoring."); return; } } else if (codeType == SONY) { Serial.print("Received SONY: "); } else if (codeType == PANASONIC) { Serial.print("Received PANASONIC: "); } else if (codeType == JVC) { Serial.print("Received JVC: "); } else if (codeType == RC5) { Serial.print("Received RC5: "); } else if (codeType == RC6) { Serial.print("Received RC6: "); } else { Serial.print("Unexpected codeType "); Serial.print(codeType, DEC); Serial.println(""); } Serial.println(results->value, HEX); codeValue = results->value; codeLen = results->bits; } } void sendCode(int repeat) { if (codeType == NEC) { if (repeat) { irsend.sendNEC(REPEAT, codeLen); Serial.println("Sent NEC repeat"); } else { irsend.sendNEC(codeValue, codeLen); Serial.print("Sent NEC "); Serial.println(codeValue, HEX); } } else if (codeType == SONY) { irsend.sendSony(codeValue, codeLen); Serial.print("Sent Sony "); Serial.println(codeValue, HEX); } else if (codeType == PANASONIC) { irsend.sendPanasonic(codeValue, codeLen); Serial.print("Sent Panasonic"); Serial.println(codeValue, HEX); } else if (codeType == JVC) { irsend.sendJVC(codeValue, codeLen, false); Serial.print("Sent JVC"); Serial.println(codeValue, HEX); } else if (codeType == RC5 || codeType == RC6) { if (!repeat) { // Flip the toggle bit for a new button press toggle = 1 - toggle; } // Put the toggle bit into the code to send codeValue = codeValue & ~(1 << (codeLen - 1)); codeValue = codeValue | (toggle << (codeLen - 1)); if (codeType == RC5) { Serial.print("Sent RC5 "); Serial.println(codeValue, HEX); irsend.sendRC5(codeValue, codeLen); } else { irsend.sendRC6(codeValue, codeLen); Serial.print("Sent RC6 "); Serial.println(codeValue, HEX); } } else if (codeType == UNKNOWN /* i.e. raw */) { // Assume 38 KHz irsend.sendRaw(rawCodes, codeLen, 38); Serial.println("Sent raw"); } } int lastButtonState; bool readyState = true; void loop() { // If button pressed, send the code. int buttonState = digitalRead(BUTTON_PIN); if (lastButtonState == HIGH && buttonState == LOW) { Serial.println("Released"); irrecv.enableIRIn(); // Re-enable receiver } if (!buttonState) { readyState = true; } if (buttonState) { if(readyState){ Serial.println("Pressed, sending"); digitalWrite(STATUS_PIN, HIGH); sendCode(lastButtonState == buttonState); digitalWrite(STATUS_PIN, LOW); delay(100); // Wait a bit between retransmissions } readyState = false; } else if (irrecv.decode(&results)) { digitalWrite(STATUS_PIN, HIGH); storeCode(&results); irrecv.resume(); // resume receiver digitalWrite(STATUS_PIN, LOW); } lastButtonState = buttonState; }
180行目のdelay()の時間は送信処理の要ですので、環境に合わせて適宜、変更してください。また、全ての形式の赤外線に対応しているわけではありませんのでご注意ください。
4. 抵抗値の計算(5mm赤外線LED)
Arduinoの電源は5V(V)。データシートに記載されている順方向電圧(DC Forward Voltage/VF)は標準1.35V。絶対最大定格(Absolute Maximum Rating)の最大電流(DC Forward Current)は100mA(IF)。電流を最大より少し下げて90mAとするとオームの法則で40.5Ωになります。
※今回は大きめに47Ωを使用しています。
5. 抵抗器の電力計算(5mm赤外線LED)
[公式]
を元に計算すると
0.38Wですので「1/2W」(0.5W)の抵抗器で良いように思えますが、実際はその2倍以上の1Wの抵抗器を使った方が安全です。
掲示板
ArduinoやRaspberry Piなどの電子工作の掲示板を作成しました。質問やわからない事は電子工作 (Arduino・ラズパイ等)でユーザー同士で情報を共有して下さい。