Arduinoで無線通信を使いデータのやり取りが出来ると電子工作の幅が広がります。
無線を使ったやり取りにはWi-FiやBluetoothを使った方法などいろいろとあるようです。
例えば、双方向でのデータのやり取りのほかに複数モジュール間でのやり取りも出来るnRF24L01無線モジュールは電子工作用途で便利に使える無線モジュールでした。
Arduino間でのデータのやり取りによりこのようなロボットカーを無線で動かすことが出来ます。
この無線モジュールはSPIでのデータのやり取りとなるため、使うGPIOピンが多くArduinoで使えるSPIピンはボードによって決まっているため製作物に組み込む際は既に組んでいるピンを再配置するなど少し手間もかかります。
そしてBluetoothモジュールを使えば、基本的に1対1のみのやり取りとなりますがTX/RXの通常のシリアルでのやり取りとなるため組み込みには便利に使えました。
電子工作でこれまで製作したものの無線化をいろいろと模索しているのですが、今回はArduinoで赤外線(IR)モジュールを使いリモコンの赤外線信号(IRデータ)を読み取り、それを使ってArduinoの制御等で使ってみたいと思います。
赤外線(IR)信号を使ったやり取りは、身の回りにあるテレビやエアコンなど様々な電化製品のリモコンで使われているので、Arduinoでその信号を読み取ることが出来ると面白いことができそうですよね!
リモコンの信号を読み取りArduinoに繋いだ赤外線モジュールから送信すれば、リモコンを使わずArduinoから家電をON/OFFさせたりなんてことも出来そうです!
例えばこんな感じ!
部屋にあったLEDテープライト用のリモコン信号を読み取り、Arduinoから点灯を制御するなんてことも出来ますね!
また、赤外線受光モジュール(送信用赤外線LEDも)はデジタルピン1本のみで使えるため、既に製作したものに組み込むことも簡単に出来ます。
赤外線でのやり取りなので受光部の位置により受信感度が悪くなることもありますが、リモコンを使って簡単に動きをテスト出来たりと・・・電子工作用途で何かと使える場面は多そうです。
今回は、赤外線(IR)モジュールを使ってリモコンの信号を読み取る方法やその信号を送信する基本的な方法を見ていきたいと思います。
目次
赤外線(IR)モジュールを使いリモコンの信号を読み取り送受信する方法!
赤外線を使ったやり取りは家庭内にある多くのリモコンで使われているため、もう説明するまでもないですね。
赤外線(IR)通信は、安価で使いやすい無線通信なのでこの通信方式を使ったリモコンは身の回りに多くあります。
赤外線は人が認識できる波長よりも長い光なので直接見ることが出来ませんが、簡単に言うと赤外線を発するLEDを使い非常に速く点滅させてデータとして送信しているものとなります。
Arduinoで言うと、デジタルピンを使ったHIGH/LOWで赤や青のLEDを点滅させているのと原理は同じです。
ただ赤外線を発するLEDを使っているので人にはその点滅を認識することが出来ないということですね。
こちらはIRデータを読み取ることが出来るトランジスタテスター(多機能テスター)ですが、リモコンから出たIRデータを読み取らせて数値を表示させることが出来ます。
リモコンのスイッチを押した瞬間に、目には見えませんが赤外線LEDが高速でHIGHとLOW(点灯・消灯)を繰り返し、それをデータとして送信しているということですね。
ON/OFFの波形を見てみると何となくですがイメージも掴みやすいと思います。
少し難しそうですがやっている事はLEDのON/OFFでデータを作っているということです。
ArduinoはIRデータを扱うためのライブラリが用意されているので、この雰囲気だけ掴めれば比較的簡単に扱うことが出来ます。
赤外線受光モジュール(センサー)
赤外線を使ったリモコンでのやり取りは、赤外線を発して送信する赤外線(IR)LEDとそのデータを受信する赤外線受光モジュール(センサー)が使われます。
Arduinoスターターキットにも1セット(赤外線LED/赤外線受光モジュール/リモコン)付属していました。
Arduino学習用として使えるようになると便利に活用できる機会も多いと思います。
赤外線LEDは通常のLEDと使い方は同じです。
見た目も同じですね。
赤外線LEDに関しては後述します。
まず赤外線受光モジュールから見ていきます。
こちらが赤外線受光モジュール(VS1838B)です。
ピンの配列は、VCC(5V)/GND/Signalとなっています。
SignalピンをArduinoのデジタルピンに繋ぎIR信号を渡します。
またこのようなピンヘッダーが付いたモジュール形状になったものもあります。
赤外線は直接見ることが出来ないため、こちらのモジュール形状になったものではボードにLEDが搭載されています。
リモコンからのIRデータを受信時にLEDが点滅し視覚的に分かりやすくなっています。
上記単品パーツのものに確認用LEDが付いているだけですが、ピンヘッダーになっているのでブレッドボードやジャンパーワイヤーに接続してテストする際は使いやすくなっています。
今回はArduinoスターターキットに付属していたこれらのリモコンや赤外線受光モジュールを使って解説していきたいと思います。
赤外線受光モジュールとの接続
赤外線受光モジュールとの接続は簡単です。
Arduinoのデジタルピンと接続するだけです。(電源もArduino から取っています)
今回デジタルピンD11に接続しました。
赤外線受光モジュール(VS1838B) | Arduino |
Signal | D11 |
VCC | 5V |
GND | GND |
IRremoteライブラリのインストール
IRデータのやり取りを行うための専用ライブラリをインストールしておきます。
[IRremoteライブラリ]を使用します。
Arduino IDEのメニューから[スケッチ]→[ライブラリをインクルード]→[ライブラリを管理]へと進みIRremoteで検索します。
2022年2月現在、IRremoteライブラリの最新版は3.6.0となっていました。
初めて使った時は2.6あたりだったので大分バージョンが上がっているようです。
新しいバージョン3.Xでは2.Xのものとライブラリの仕様が少し変わったようですね。
今回はバージョン2.8.0を使って説明していきたいと思います。
ライブラリのインストールは通常と同じ作業となります。
受信したIRデータを確認する
【IRremoteライブラリ】のインストールが完了したらテストスケッチを使い、まず赤外線受光モジュールで受信したIRデータを確認してみたいと思います。
[ファイル]→[スケッチ例]→[IRremote]→[IRreceiveDumpV2]を選択します。ライブラリのバージョンが2.8.1以降では、このサンプルスケッチは[IRreceiveDump]に統一?されたようです。
バージョン3.Xではライブラリの仕様が少し変更になっていますが、初めて使う場合2.Xの方が分かりやすいため(ずっとこのバージョンを使っていたからかな?)、こちらではバージョン2.8.0で進めていきます。
一応[IRreceiveDumpV2]のスケッチをそのまま載せておきます。
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 | //------------------------------------------------------------------------------ // Include the IRremote library header // #include <IRremote.h> //------------------------------------------------------------------------------ // Tell IRremote which Arduino pin is connected to the IR Receiver (TSOP4838) // #if defined(ESP32) int IR_RECEIVE_PIN = 15; #else int IR_RECEIVE_PIN = 11; #endif IRrecv IrReceiver(IR_RECEIVE_PIN); //+============================================================================= // Configure the Arduino // void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); // Status message will be sent to PC at 9600 baud #if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino Serial.println(F("START " __FILE__ " from " __DATE__)); IrReceiver.enableIRIn(); // Start the receiver IrReceiver.blink13(true); // Enable feedback LED Serial.print(F("Ready to receive IR signals at pin ")); Serial.println(IR_RECEIVE_PIN); } //+============================================================================= // Dump out the decode_results structure. // void dumpInfo() { // Check if the buffer overflowed if (IrReceiver.results.overflow) { Serial.println("IR code too long. Edit IRremoteInt.h and increase RAW_BUFFER_LENGTH"); return; } IrReceiver.printResultShort(&Serial); Serial.print(" ("); Serial.print(IrReceiver.results.bits, DEC); Serial.println(" bits)"); } //+============================================================================= // The repeating section of the code // void loop() { if (IrReceiver.decode()) { // Grab an IR code dumpInfo(); // Output the results IrReceiver.printIRResultRawFormatted(&Serial); // Output the results in RAW format Serial.println(); // blank line between entries IrReceiver.printIRResultAsCArray(&Serial); // Output the results as source code array IrReceiver.printIRResultAsCVariables(&Serial); // Output address and data as source code variables IrReceiver.printIRResultAsPronto(&Serial); Serial.println(); // 2 blank lines between entries Serial.println(); IrReceiver.resume(); // Prepare for the next value } } |
このスケッチをArduino(こちらではArduino Unoを使います)に書き込み、シリアルモニタを立ち上げます。
通信速度(ボーレート)の設定は115200bpsです。
手持ちのリモコンを赤外線受光モジュールに向けてボタンを押すと、受信したデータが表示されます。
- メーカー名(メーカープロトコル)
- 受信したIRコード(Data)
- 受信したデータのbit数
- rawData(生のタイミングデータ)
などが表示されます。
必要なデータ(赤で囲った部分)をメモしておきます。
また後述する赤外線LEDを使って送信で使う場合、メーカー名やbit数、rawデータが必要となります。
今回Arduinoスターターキットに付属していたこちらのリモコンを使ってテストしてみました。
このリモコンを使い以前製作した4足歩行ロボットを動かしてみようと思います。
[2]で前進、[8]で後退、[4]で左回り、[6]で右回り、[5]で座る動作を付けるため各ボタンのIRコード(Data)を確認しておきます。
上記スケッチでそれぞれボタンが押された時のIRデータを確認します。
例えば[5]を押した時、このリモコンではこのようなデータを受信しました。
受信で使う場合必要なのは、IRコード(Data)のみです。
同様に他のボタンも確認しておきます。
受信したIRデータをシリアルモニタで確認する
リモコンの押されたボタンを判別するテストスケッチを作りました。
シリアルモニタを使い確認してみます。
先程事前に調べた各ボタンのIRコードと一致するデータを受信すると「5キーON」のように表示させるものとなります。
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 | // Arduino入門編㉗ 赤外線(IR)モジュールを使ってみる! // https://burariweb.info // 赤外線受信モジュール用スケッチ(リモコンキー判定用) #include <IRremote.h> // ライブラリのインクルード const int ReceiverPin = 11; // 赤外線受信モジュール接続ピンをD2に IRrecv irrecv(ReceiverPin); // IR受信オブジェクトの生成(使用ピンを指定) decode_results results; // 受信情報の格納先(メーカー名/受信したデータ&ビット数など) void setup() { Serial.begin(115200); // シリアルポートを初期化 irrecv.enableIRIn(); // 赤外線(IR)受信モジュールを有効に delay(500); Serial.println("リモコンのキーを押して下さい!"); } void loop() { if (irrecv.decode(&results)){ // 赤外線受信モジュールからデータを受信したかの確認 if( results.value == 0xFF18E7 ){ // "2"が押された時 Serial.println("2キーON"); } else if( results.value == 0xFF4AB5 ){ // "8"が押された時 Serial.println("8キーON"); } else if( results.value == 0xFF10EF ){ // "4"が押された時 Serial.println("4キーON"); } else if( results.value == 0xFF5AA5 ){ // "6"が押された時 Serial.println("6キーON"); } else if( results.value == 0xFF38C7 ){ // "5"が押された時 Serial.println("5キーON"); } else Serial.println("未割り当てのキー"); // 未割り当てのキーが押された時 Serial.print("IRコード: "); Serial.print(results.value, HEX); // 16進数で受信値を出力 Serial.print(", ビット: "); Serial.println(results.bits); // ビット数(受信値長)を出力 Serial.println(""); irrecv.resume(); // 次の値を受け取る } delay(500); } |
上手くリモコンから送られていくるIRコードを識別出来ていますね。
デジタルピン1本のみで使えるので、簡単に製作物に組み込むことも出来ます。
また、テスト環境などでも便利に使えそうです。
例えば、複数のスイッチを使ったテストではブレッドボードにタクトスイッチを取り付けジャンパーワイヤでArduinoと接続しプルアップさせ・・・複数のON/OFF判定が必要な場合、結構面倒な配線となります。
赤外線受光モジュールを使い、上記のようにボタンのIRデータにより分岐させれば回路も簡単にでき、判定するスイッチも必要に応じてリモコンのボタンを増やしていくだけなので簡単に出来ますね!
スケッチ解説
ライブラリのインクルード
IRremoteライブラリのインクルードです。
5 | #include <IRremote.h> // ライブラリのインクルード |
IRrecv 名称(pin番号)
受信で使用するオブジェクトの作成。
名称と使用するピンを指定します。
6 7 8 | const int ReceiverPin = 11; // 赤外線受信モジュール接続ピンをD2に IRrecv irrecv(ReceiverPin); // IR受信オブジェクトの生成(使用ピンを指定) |
decode_results ○○
受信データの格納先を作成。
受信したデータは作成した「results」内に格納されます。
9 | decode_results results; // 受信情報の格納先(メーカー名/受信したデータ&ビット数など) |
複数情報が入っていますが指定して任意の情報を取得できます。
関数 | 内容 |
decode_type | メーカー名を取得 |
value | 受信データを取得 |
bits | 受信したデータのビット数を取得 |
○○.enableIRIn();
赤外線受信を開始させます。
14 | irrecv.enableIRIn(); // 赤外線(IR)受信モジュールを有効に |
○○.decode(&~~);
赤外線受信モジュールからデータを受信したかの確認。
シリアル通信する際に使われるserial.availableと同じようなもの?です。
24 | if (irrecv.decode(&results)){ // 赤外線受信モジュールからデータを受信したかの確認 |
○○.value
受信情報格納先から受信データを取得。
26 27 28 29 30 31 32 33 34 35 36 37 38 39 | if( results.value == 0xFF18E7 ){ // "2"が押された時 Serial.println("2キーON"); } else if( results.value == 0xFF4AB5 ){ // "8"が押された時 Serial.println("8キーON"); } else if( results.value == 0xFF10EF ){ // "4"が押された時 Serial.println("4キーON"); } else if( results.value == 0xFF5AA5 ){ // "6"が押された時 Serial.println("6キーON"); } else if( results.value == 0xFF38C7 ){ // "5"が押された時 Serial.println("5キーON"); |
○○.bits
受信情報格納先から受信したデータのビット数を取得。
143 144 145 146 147 | Serial.print("IRコード: "); Serial.print(results.value, HEX); // 16進数で受信値を出力 Serial.print(", ビット: "); Serial.println(results.bits); // ビット数(受信値長)を出力 Serial.println(""); |
~.resume();
.decode()の値をリセットし、次の受信データを受け取れるようにする。
49 | irrecv.resume(); // 次の値を受け取る |
リモコンデータ(IRデータ)を送信する
リモコンから送信されたIRデータを確認し動かすことが出来ました。
次にIRデータを送信で使ってみたいと思います。
赤外線(IR)の送信には、赤外線(IR)LEDを使います。
使い方は通常のLEDと同じです。
こちらの赤外線LEDは、順方向電圧(VF)が1.25~1.8V、順方向電流(IF)が20mAとなっています。
ほぼ赤色LEDと同じくらいですね。
R=(5.0-1.5)/0.02=175Ω
今回電流制限抵抗は180Ωのものを使いました。
赤外線LEDの接続
赤外線LEDの接続は非常に簡単です。
通常のLEDと同じです。
電流制限抵抗を挟みデジタルピンD3に繋ぎます。(IRremoteライブラリの送信デフォルトピンはD3となっています)
送信にはメーカー名とData(IRコード)、受信ビット数が必要となります。
先程ライブラリのサンプルスケッチ[IRreceiveDumpV2]で事前に調べておいたものです。
今回使っているリモコンはNECのプロトコル信号を持ったリモコンでした。
これをIRremoteライブラリのsend関数に反映させます。
○○.sendNEC(Data, ビット数);
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 | // Arduino入門編㉗ 赤外線(IR)モジュールを使ってみる! // https://burariweb.info // 送信用スケッチ(メーカープロトコルを使って送信) #include <IRremote.h> // ライブラリのインクルード IRsend irsend; // IR送信オブジェクトの生成 void setup(){ Serial.begin(115200); // シリアルポートを初期化 Serial.print("デジタルピン"); // 赤外線LED接続ピンを表示 Serial.print(IR_SEND_PIN); Serial.println("に赤外線LEDを繋いで下さい!"); delay(500); } void loop(){ // 赤外線LEDからIRデータを送信する // メーカープロトコルを使って送信 // // [例]メーカープロトコル send関数例 // irsend.sendNEC(data, ビット数); // irsend.sendSony(data, ビット数); // irsend.Panasonic(アドレス, data); irsend.sendNEC(0xFF18E7, 32); // リモコンの"2"が押された時のIRコード delay(1000); irsend.sendNEC(0xFF4AB5, 32); // リモコンの"8"が押された時のIRコード delay(1000); } |
Arduinoが2台あれば受信側で確認する事が出来ます。
先程使った受信側Arduinoのシリアルモニタに1秒間隔で「2キーON」「8キーON」と表示されれば上手く送信データが送られているということになります。
こんな感じですね。
また手持ちのリモコンで取得したIRデータを上記スケッチに書き換え、Arduinoに接続した赤外線LEDから対応機器が動作すれば成功です。
例えば、こちらは部屋に設置したLEDテープライト用のリモコンです。(こちらもNECプロトコル信号のものでした)
このリモコンのIRデータを読み取り送信データとして使うことにより、リモコンを使わずArduinoのシリアルモニタから制御出来るようにしてみました。
なかなか面白いですね!
ライブラリで使える他のメーカープロトコル
メーカープロトコルによる送信関数は多数用意されています。
手元にあったいくつかのリモコンで試してみました。
上記テストで使用したリモコンはNECのプロトコル信号を持ったリモコンでした。
他のメーカープロトコル信号で使えるsend関数も多数用意されていますが、メーカーにより使い方が少し異なるようですね!
- ○○.sendNEC(Data, ビット数);
- ○○.sendSony(Data, ビット数);
- ○○.Panasonic(Address, Data);
などが使えます。
サポートされている他のメーカー製のリモコンのIRsendクラスに関してはこちらのページを確認して下さい
例えばPanasonic製のテレビリモコンの電源ボタンではこのような信号が出ていました。
Panasonicのメーカープロトコルのsend関数はこのように使います。
~~.Panasonic(Address, Data);
上記スケッチのsend関数部分をirsend.Panasonic(0x555A, 0x5AF14868);に置き換えることにより上手く使うことが出来ました。(以下のsendRaw関数を使っても送信することが出来ます)
他のメーカープロトコルに関しては、上記サイトを参考にして下さい!
プロトコルが不明(UNKNOWN)の場合の送信設定
上記のようにメーカーのプロトコル信号の場合、send関数を使いsendNECやsendPanasonicのように指定してIRコードを送信することが出来ます。
しかしプロトコルが[UNKNOWN]と表示され不明な場合や、分かっていても上手く送信できない場合はsendRaw関数を使うと上手くいく場合があります。
例えばこちらはカメラシャッター用のリモコンとなります。
中華の格安リモコンですが、プロトコルが不明(UNKNOWN)と表示されました。
このような場合、sendRaw関数を使って送信タイミングの生データを使えば上手くいきます。
上記[IRreceiveDumpV2]で信号を調べるとRawデータ(生の信号データ)が配列で表示されます。
このリモコンの場合、15配列の数となっていました。
このデータをそのままコピーし、sendRaw(○○, 15, 38)でIRデータを送信することが出来ます。(第2引数は配列の数、第3引数は38固定で大丈夫です)
先程のメーカープロトコルを使ったスケッチをsendRaw関数を使ったものに修正するとこのようになります。
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 | // Arduino入門編㉗ 赤外線(IR)モジュールを使ってみる! // https://burariweb.info // 送信用スケッチ(sendRaw関数を使って送信) #include <IRremote.h> // ライブラリのインクルード IRsend irsend; // IR送信オブジェクトの生成 void setup(){ Serial.begin(115200); // シリアルポートを初期化 Serial.print("デジタルピン"); // 赤外線LED接続ピンを表示 Serial.print(IR_SEND_PIN); Serial.println("に赤外線LEDを繋いで下さい!"); delay(500); } // 送信用データを定義(rawData) const uint16_t irData[15] = {12850,3000, 950,1050, 950,1000, 1000,1000, 950,1000, 1000,1000, 1000,1000, 950}; void loop(){ irsend.sendRaw(irData, 15, 38); delay(1000); } |
手元にあったリモコンをいろいろと試してみましたが、メーカープロトコルによる送信やsendRaw関数を使いタイミングデータを送信する方法で大抵のものは上手くいきました。
しかしエアコンのリモコンだけは送信しているデータが多いようで今回の方法ではうまくいきませんでした。
そのことはライブラリのGithubページにも書かれていました。
方法はいろいろと書かれているので興味ある方はライブラリの仕様をさらに深く探ってみるのがいいかと思います。
今回使ったアイテム
赤外線受光モジュール&赤外線LED
赤外線(IR)のデータの受信に使う赤外線受光モジュールと送信に使う赤外線LEDです。
リモコンセット
赤外線受光モジュールと赤外線LED、今回テストで使ったリモコンがセットになったものも販売されているようです。
Arduinoスターターキットにも1セット付属していました。
Arduino UNO
Arduinoはオープンソースのハードウェアなので正規品以外にも互換品が多数販売されています。
互換品でも正規品と比べて特に問題なく使用でき安価なためArduino学習用としていいと思います。
Elegoo製のArduinoボードは、互換ボードの中でも非常にクオリティーが高いのでおすすめです!
Arduino スターターキット
これからArduino学習を進めていくにあたりArduino UNO(互換品)やブレッドボード、ジャンパーピンなどがセットになったスターターキットが販売されています。
私はGeekcreit製のスターターキットを使っていますが、ELEGOO製のものは国内Amazonなどでも購入可能で人気があるようです。(セット内容はほぼ同じです!)
そしてELEGOOのサイトからスターターキット用サンプルスケッチのダウンロードも可能です。(Geekcreitのキットでも使えます)
参考 チュートリアルダウンロードELEGOO電子工作を始めるにはまずブレッドボードやジャンパーピン、メインとなるArduino UNOやサーボ、LEDなどの基本的なパーツがないと実際に動かすことが出来ませんが、個々にパーツを購入して回路を組んでとなるとかなりの手間がかかります。
スターターキットがあればArduinoの初歩的なことはかなりの数こなすことが出来るのでオススメです!
そこからスキルアップに伴い個別でセンサーやモジュールなど必要なものを増やしていくのがいいと思います。
今回使ったリモコンや赤外線受光モジュール、赤外線LEDも1セット付属していました。
最後に!
Arduinoを使った電子工作を始めた頃にArduinoスターターキットを購入し付属していたものなので、当時いろいろと試した記憶があります。
最近では以前より少しですがArduinoの事が分かるようになってきて、自作した製作物の無線化に使ってみました。
使用するGPIOピンはデジタルピン1本のみなので比較的簡単に組み込むことができテスト動作させることが出来るのがいいですね!
またテスト環境での動作テストでON/OFF判定させることはよくありますが、複数のスイッチをArduinoに接続しようと考えると接続自体は簡単ですがブレッドボードの配線やプルアップ設定など結構面倒となってきます。
IRコードを取得しスケッチ内で動作を分岐させるといった使い方で便利に使えそうですね。
動作させるボタンを増やしていくのも簡単です。
Arduinoのスターターキットに入っているパーツ構成ってよく考えられていますね。
ある程度Arduinoを触っていると追加でいろいろとセンサーやモジュールなどのパーツを増やしていくわけですが、これからArduinoを始めてみようと考えられている方には基本的な事が試せる良いキットだとあらためて思ったりしました。
めっちゃわかりやすい…
ありがとうございます(^o^)