はじめに:赤外線リモコンとArduinoで広がるIoTの世界
テレビやエアコンを操作する赤外線リモコン。その信号を自分のマイコンで受信・解析できたら、様々なIoTアプリケーションが実現できます。
- 家電の状態を自動記録するスマートホーム
- 複数の家電を一括操作する統合リモコン
- リモコン操作をトリガーにした自動化システム
- 赤外線信号を学習・再送信する万能リモコン
今回は、Arduino UNOと赤外線受信モジュール(OSRB38C9AA)、そしてIRremoteライブラリを使って、家庭用リモコンの信号を受信・解析し、その信号に応じて6個のLEDを制御するシステムを構築します。
単に「動かす」だけでなく、赤外線通信の原理、信号のデコード方法、実用的な制御ロジックまで、電子工作とプログラミングの両面から詳しく解説していきます。
赤外線とは?電磁波の基礎知識
赤外線の特性と可視光線との違い
**赤外線(Infrared、IR)**は、可視光線よりも波長が長い電磁波の一種です。人間の目には見えませんが、熱として感じることができ、リモコン通信に最適な特性を持っています。
電磁波のスペクトル
波長(nm) 種類 用途
200-380 紫外線 殺菌、日焼け
380-450 可視光(青) 照明、ディスプレイ
450-550 可視光(緑) 照明、ディスプレイ
550-700 可視光(赤) 照明、ディスプレイ
700-1400 近赤外線 リモコン、通信(← 今回使用)
1400-3000 中赤外線 暖房、センサー
3000- 遠赤外線 暖房、調理
リモコンに使われる赤外線の特徴:
| 特性 | 詳細 | メリット |
|---|---|---|
| 波長 | 約850-950nm(近赤外線) | LEDで容易に発生可能 |
| 指向性 | 比較的直進性が高い | 特定の機器だけを操作できる |
| 減衰 | 壁を透過しない | 他の部屋の機器に影響しない |
| コスト | 部品が安価 | 大量生産に適している |
| 消費電力 | 極めて低い | 電池で長期間動作可能 |
なぜ赤外線がリモコンに使われるのか?
1. 人間の目に見えない
- 可視光だと点滅が気になる
- 赤外線なら視覚的なノイズがゼロ
2. 太陽光や室内照明の影響を受けにくい
- 38kHzという特定の周波数で変調することで、ノイズと区別可能
- フィルタ回路で不要な光をカット
3. 安価で確実な通信
- 赤外線LEDと受信モジュールは数十円から入手可能
- 30年以上の実績がある枯れた技術
4. 免許不要
- 電波(Wi-Fi、Bluetooth)と違い、電波法の規制対象外
- 申請や認証なしで自由に使用可能
電子工作の基礎知識:この工作で必要な予備知識
このプロジェクトを理解するために必要な、電子工作の基本概念を解説します。
1. デジタル信号とアナログ信号
デジタル信号(Digital Signal)
**HIGH(5V)とLOW(0V)**の2つの状態だけで情報を表現します。
電圧
5V ┌─┐ ┌─┐ ┌─┐
│ │ │ │ │ │
0V ┘ └──┘ └──┘ └──
1 0 0 1 0 0 1 0 ← ビット列
今回の使用例:
- 赤外線受信モジュールの出力 → デジタル信号
- LED制御の
digitalWrite()→ デジタル出力
アナログ信号(Analog Signal)
連続的に変化する電圧で情報を表現します。
電圧
5V ╱╲ ╱╲
╱ ╲ ╱ ╲
0V ╱ ╲╱ ╲
← 連続的に変化
応用例:
- 温度センサー(電圧が温度に比例)
- 可変抵抗器(ボリューム)
- PWM制御による疑似アナログ出力
2. GPIO(汎用入出力ピン)の基本
**GPIO(General Purpose Input/Output)**は、Arduinoのデジタルピン(D0-D13)やアナログピン(A0-A5)のことです。
入力モード(INPUT)
外部からの信号を読み取るモードです。
pinMode(A0, INPUT); // A0を入力に設定
int value = digitalRead(A0); // HIGHまたはLOWを読み取り
今回の使用: 赤外線受信モジュールの信号を読み取り
出力モード(OUTPUT)
外部にHIGH(5V)またはLOW(0V)を出力するモードです。
pinMode(2, OUTPUT); // D2を出力に設定
digitalWrite(2, HIGH); // D2に5Vを出力(LEDが点灯)
digitalWrite(2, LOW); // D2に0Vを出力(LEDが消灯)
今回の使用: LEDの点灯・消灯制御
3. 電流制限抵抗の計算方法
LEDを直接電源につなぐと、過電流で破壊されます。電流制限抵抗で適切な電流に制限する必要があります。
オームの法則による計算
R(抵抗値Ω)= V(電圧V)÷ I(電流A)
LED接続時の計算例:
Arduinoピン(5V)→ [抵抗R] → [LED] → GND(0V)
条件:
- Arduino出力電圧:5V
- LED順方向電圧(Vf):2V(赤色LED標準値)
- LED定格電流(If):20mA = 0.02A(標準的な値は15-20mA)
計算:
R = (5V - 2V) ÷ 0.02A = 3V ÷ 0.02A = 150Ω
実際の選定:
- 計算値:150Ω
- 実際の部品:220Ω(E12系列の標準抵抗値、安全マージン込み)
- 結果の電流:(5V - 2V) ÷ 220Ω ≈ 13.6mA(LEDに優しい値)
抵抗値と明るさの関係:
| 抵抗値 | 電流 | LED明るさ | 備考 |
|---|---|---|---|
| 100Ω | 30mA | ⚠️ 明るいが過電流 | 長時間使用で劣化 |
| 220Ω | 13.6mA | ✅ 適度な明るさ | 推奨値 |
| 330Ω | 9.1mA | やや暗い | 省電力重視 |
| 1kΩ | 3mA | かなり暗い | インジケーター用 |
4. ブレッドボードの構造と使い方
ブレッドボードは、ハンダ付け不要で部品を接続できる便利なツールです。
電源ライン(縦方向で接続)
↓
+ + + + + + + + ← すべて内部で接続
- - - - - - - - ← すべて内部で接続
===============
a b c d e f g h ← 横の5穴が内部で接続
---------------
a b c d e f g h
接続時の注意点:
- 電源ライン(+/-)は縦方向に導通
- 中央部は横の5穴が導通
- 中央の溝で左右は絶縁されている
- ジャンパー線で任意の穴を接続可能
5. シリアル通信とデバッグ
ArduinoとPCの間でデータをやり取りする方法です。
void setup() {
Serial.begin(9600); // 9600bpsで通信開始
}
void loop() {
Serial.println("Hello"); // PCに文字列を送信
delay(1000);
}
今回の使用:
- 受信した赤外線信号を16進数で表示
- プログラムの動作確認(デバッグ)
- 現在のLED状態の確認
ボーレート(通信速度)の選択:
- 9600bps:標準的、安定性重視
- 115200bps:高速、大量データ転送時
赤外線リモコン通信の原理
家庭用リモコンは、赤外線LEDから約38kHzでパルス変調された光信号を送信します。この赤外線は人間の目には見えませんが、赤外線受信モジュールによって電気信号に変換できます。
主な赤外線通信プロトコル
家電メーカーやデバイスによって異なる通信規格が使われています:
| プロトコル | 主な使用機器 | キャリア周波数 | ビット長 |
|---|---|---|---|
| NEC | 汎用リモコン、照明機器 | 38kHz | 32ビット |
| SONY | ソニー製品(テレビ、AV機器) | 40kHz | 12/15/20ビット |
| RC-5/RC-6 | Philips製品 | 36kHz | 13/32ビット |
| Samsung | サムスン製品 | 38kHz | 32ビット |
IRremoteライブラリは、これらの主要プロトコルを自動認識してデコードしてくれます。
赤外線受信モジュールの仕組み
OSRB38C9AAなどの赤外線受信モジュールは、以下の機能を1つのパッケージに統合しています:
- フォトダイオード: 赤外線を電気信号に変換
- AGC(自動利得制御): 受信感度を自動調整
- バンドパスフィルタ: 38kHz帯のみを通過
- 復調回路: キャリア周波数を除去してデジタル信号に変換
これにより、Arduino側ではデジタルピンで単純にHIGH/LOWを読み取るだけで、複雑な赤外線信号を受信できます。
必要な部品と技術仕様
信号受信用の部品リスト
| 部品名 | 仕様 | 数量 | 備考 |
|---|---|---|---|
| Arduino UNO | R3 / R4 Minima | 1 | R4推奨(処理速度向上) |
| 赤外線受信モジュール | OSRB38C9AA(38kHz) | 1 | TSOP38238等でも可 |
| 家庭用赤外線リモコン | TV/照明/エアコン等 | 1 | NEC/SONY規格推奨 |
| ブレッドボード | 標準サイズ | 1 | 400穴タイプ |
| ジャンパー線 | オス-オス | 適量 | 3本以上 |
LED制御用の追加部品
| 部品名 | 仕様 | 数量 |
|---|---|---|
| 赤色LED | Vf=1.8-2.2V | 6 |
| カーボン抵抗 | 220Ω(1/4W) | 6 |
| ブレッドボード | 標準サイズ | 1 |
準備した部品一式
リモコンがない場合の代替案
家のリモコンを工作に使うのが心配な方には、電子工作専用のIRリモコンモジュールがおすすめです。
今回は、家庭用のルームライトリモコン(NEC規格)を使用しました。
ステップ1:赤外線信号の受信と解析
IRremoteライブラリのインストール
Arduinoで赤外線信号を扱うには、IRremoteライブラリが必須です。
インストール方法:
- Arduino IDEを開く
- メニューから「スケッチ」→「ライブラリをインクルード」→「ライブラリを管理…」
- 検索窓に「IRremote」と入力
- shirriff/IRremote(または互換バージョン)を選択してインストール
信号受信回路の構成
赤外線受信モジュールは、以下のように接続します:
赤外線受信モジュールの配線図
OSRB38C9AAのピン配置:
| ピン番号 | 信号名 | 接続先 |
|---|---|---|
| 1 | OUT | Arduino A0ピン |
| 2 | GND | Arduino GND |
| 3 | VCC | Arduino 5V |
重要ポイント:
- 受信モジュールは光を受ける面を工作の外側に向けて配置
- ケーブルが長い場合は、ノイズ対策として0.1μFのパスコンをVCC-GND間に追加推奨
- デジタルピン(D2-D13)でもアナログピン(A0-A5)でも使用可能
信号キャプチャプログラムの実装
リモコンボタンに対応する赤外線信号を取得するプログラムです。受信した信号を**16進数(HEX)**で表示します。
#include <IRremote.h>
int RECV_PIN = A0; // 受信ピンをA0に設定
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup(){
Serial.begin(9600); // シリアル通信開始(9600bps)
irrecv.enableIRIn(); // 赤外線受信を開始
Serial.println("IR Receiver Ready");
}
void loop() {
if (irrecv.decode(&results)) {
// 受信した信号を16進数で表示
Serial.print("Received: 0x");
Serial.println(results.value, HEX);
// プロトコルの種類も表示(デバッグ用)
Serial.print("Protocol: ");
Serial.println(results.decode_type);
irrecv.resume(); // 次の信号受信待機
}
delay(100);
}
プログラムの動作説明:
| 関数 | 機能 |
|---|---|
irrecv.enableIRIn() |
赤外線受信を有効化(setup内で1回実行) |
irrecv.decode(&results) |
信号を受信したらtrue、results構造体にデータ格納 |
results.value |
受信した信号値(unsigned long型) |
results.decode_type |
プロトコル種類(NEC=1, SONY=2, RC5=3, etc.) |
irrecv.resume() |
バッファクリア、次の受信準備 |
信号の取得と確認方法
- プログラムをArduinoに書き込む
- シリアルモニタを開く(ツール → シリアルモニタ、9600bps)
- 赤外線受信モジュールに向けてリモコンのボタンを押す
- シリアルモニタに16進数の信号値が表示される
シリアルモニタに表示された赤外線信号
注意事項:
- 同じボタンを複数回押して、毎回同じ値が出るか確認
- もし毎回違う値が出る場合は、リモコンとモジュールの距離や角度を調整
- 長押しすると「FFFFFFFF」(リピートコード)が表示されることがある
取得した信号値の整理
ルームライトリモコンから取得した赤外線信号の一覧です:
取得した赤外線信号の対応表
取得した信号の例:
| ボタン名 | 16進数コード | 機能(実装予定) |
|---|---|---|
| 点灯 | 0xEBB8D38E | LED 3個点灯(中間) |
| 全灯 | 0x1E82D3CE | LED 6個点灯(最大) |
| 消灯 | 0x1D41D404 | LED 全消灯 |
| 明るい | 0x72703D2E | LED 1個ずつ追加点灯 |
| 暗い | 0xEB95DB2E | LED 1個ずつ消灯 |
ポイント:
- これらの値はあなたのリモコン固有の値です
- 他のリモコンでは全く異なる値になるため、必ず自分で取得してください
- 信号は32ビット(8桁の16進数)で表現されます
ステップ2:赤外線信号によるLED制御システムの構築
信号の取得ができたら、次はその信号に応じてLEDを制御するプログラムを作成します。
LED制御回路の設計
6個のLEDを独立制御できる回路を構成します。各LEDには電流制限抵抗(220Ω)を直列に接続します。
赤外線リモコンによるLED制御回路の全体図
回路設計のポイント:
- LED接続ピン: デジタルピンD2〜D7(6個)
- 電流制限抵抗: 各LEDに220Ω(計算式:(5V - 2V) / 0.015A ≈ 200Ω)
- 受信モジュール: A0ピン(そのまま継続使用)
- 配線の整理: ブレッドボードの電源ラインを活用してGNDを共通化
リモコンボタンと制御動作の対応表
実装する機能を整理します:
リモコンボタンの機能マッピング
| リモコンボタン | 信号コード | 実装動作 | LED状態 |
|---|---|---|---|
| 点灯 | 0xEBB8D38E | LED 3個点灯(中間の明るさ) | D2,D3,D4=ON |
| 全灯 | 0x1E82D3CE | LED 6個全点灯(最大の明るさ) | D2-D7=ON |
| 消灯 | 0x1D41D404 | LED 全消灯 | D2-D7=OFF |
| 明るい | 0x72703D2E | 点灯LEDを1個ずつ増やす | 段階的に明るく |
| 暗い | 0xEB95DB2E | 点灯LEDを1個ずつ減らす | 段階的に暗く |
制御ロジックの設計思想:
- 変数
jで現在の明るさレベル(1〜7)を記憶 - 「明るい」「暗い」ボタンで段階的に調整可能
- 上限・下限でリミット処理を実装
LED制御プログラムの完全版
赤外線信号を受信してLEDを制御する完成版プログラムです:
#include <IRremote.h>
// ピン定義
int RECV_PIN = A0;
int i, j; // i:ループ用, j:現在の明るさレベル(1-7)
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup(){
Serial.begin(9600); // デバッグ用シリアル通信
irrecv.enableIRIn(); // 赤外線受信開始
// LEDピン(D2-D7)を出力モードに設定
for (i = 2; i <= 7; i++) {
pinMode(i, OUTPUT);
digitalWrite(i, LOW); // 初期状態:全消灯
}
j = 1; // 明るさレベル初期値
Serial.println("LED Control System Ready");
}
void loop() {
if (irrecv.decode(&results)) {
// デバッグ:受信した信号をシリアル表示
Serial.print("Received: 0x");
Serial.println(results.value, HEX);
irrecv.resume(); // 次の信号受信準備
// switch文で信号に応じた処理を実行
switch (results.value) {
case 0xEBB8D38E: // 【点灯】ボタン
// D2,D3,D4をON / D5,D6,D7をOFF
for (i = 2; i < 5; i++) digitalWrite(i, HIGH);
for (i = 5; i < 8; i++) digitalWrite(i, LOW);
j = 4; // 明るさレベルを4に設定
Serial.println("Mode: Normal (LED 0-2 ON)");
break;
case 0x1E82D3CE: // 【全灯】ボタン
// D2-D7を全てON
for (i = 2; i < 8; i++) digitalWrite(i, HIGH);
j = 7; // 明るさレベルを最大に
Serial.println("Mode: Full Brightness (All LEDs ON)");
break;
case 0x1D41D404: // 【消灯】ボタン
// D2-D7を全てOFF
for (i = 2; i < 8; i++) digitalWrite(i, LOW);
j = 1; // 明るさレベルを最小に
Serial.println("Mode: OFF (All LEDs OFF)");
break;
case 0x72703D2E: // 【明るい】ボタン
// 現在のレベルjのLEDを点灯し、jをインクリメント
j++;
if (j > 7) j = 7; // 上限チェック
digitalWrite(j, HIGH);
Serial.print("Brightness UP: Level ");
Serial.println(j - 1);
break;
case 0xEB95DB2E: // 【暗い】ボタン
// 現在のレベルjのLEDを消灯し、jをデクリメント
digitalWrite(j, LOW);
j--;
if (j < 1) j = 1; // 下限チェック
Serial.print("Brightness DOWN: Level ");
Serial.println(j - 1);
break;
default:
// 未登録のボタンが押された場合
Serial.println("Unknown button");
break;
}
delay(300); // チャタリング防止
}
}
プログラムの重要ポイント:
-
状態管理変数
j- 値の範囲:1(全消灯)〜 7(全点灯)
- LEDピン番号(D2-D7)と対応させるため、実際のピン番号-1で管理
-
段階的調光の実装
- 「明るい」:
digitalWrite(j, HIGH); j++; - 「暗い」:
digitalWrite(j, LOW); j--; - リミッタ処理で配列外アクセスを防止
- 「明るい」:
-
チャタリング対策
delay(300)で連続押下を防止- より高度な実装では
millis()を使った非ブロッキング処理も可能
-
デバッグ機能
- Serial出力で現在の状態を確認可能
- 本番環境ではSerial関連のコードを削除して軽量化可能
実行結果と動作確認
実際に動作させた様子を動画で確認できます:
動作のポイント:
- リモコンボタンを押すと、瞬時にLEDが応答
- 「明るい」「暗い」ボタンで段階的に調光可能
- 通信距離は約3〜5m(環境により変動)
- 斜めからでも約45度の角度まで受信可能
応用例とカスタマイズ
実用的な応用アイデア
このシステムは、基礎としてさまざまなプロジェクトに発展できます:
1. 学習リモコンの作成
- 受信した信号を不揮発性メモリ(EEPROM)に保存
- 赤外線LED送信回路を追加して信号を再送信
- 複数のリモコンを1つに統合
2. スマートホーム連携
- ESP32/ESP8266でWi-Fi接続を追加
- MQTTやHTTPでスマホアプリと連携
- Google HomeやAlexaからの音声制御
3. 家電の自動化
- 特定の時刻に信号送信(タイマー制御)
- 温度センサーと連携して自動でエアコン操作
- 人感センサーで照明の自動ON/OFF
4. データロギング
- リモコン操作履歴をSDカードに記録
- 使用頻度分析による省エネ提案
- 高齢者見守りシステム(操作がない場合にアラート)
プログラムのカスタマイズ方法
未使用ボタンへの機能追加:
case 0x12345678: // あなたのリモコンの信号コードに変更
// ここに新しい機能を実装
// 例:点滅パターン、ランダムカラー、etc.
break;
PWM制御による無段階調光:
// LEDピンをPWM対応ピン(D3,D5,D6,D9,D10,D11)に接続
case 0x72703D2E: // 明るい
brightness += 25;
if (brightness > 255) brightness = 255;
analogWrite(LED_PIN, brightness);
break;
複数デバイスの制御:
// サーボモーター、リレー、LCD表示などを追加
case 0x1E82D3CE:
myServo.write(90); // サーボを90度に
digitalWrite(RELAY_PIN, HIGH); // リレーON
lcd.print("Device ON");
break;
トラブルシューティング
よくある問題と解決方法
| 症状 | 原因 | 解決方法 |
|---|---|---|
| 信号が受信できない | 配線ミス、電源不足 | VCC/GND/OUTの接続を再確認、USBケーブルを交換 |
| 毎回違う値が表示される | リモコンの距離・角度 | 10-30cm、正面から信号送信 |
| 連続で同じ動作が繰り返される | リピートコード受信 | if(results.value != 0xFFFFFFFF)で除外 |
| LEDが点灯しない | ピン設定ミス、抵抗値 | pinMode設定確認、抵抗値を100Ωに変更して試行 |
| 動作が遅い | delay()が長すぎる |
delay値を50-100msに短縮、または非ブロッキング処理に変更 |
リピートコード対策
長押しすると「0xFFFFFFFF」が連続で送信されます。これを無視する処理:
if (irrecv.decode(&results)) {
if (results.value != 0xFFFFFFFF) { // リピートコード除外
// 通常の処理
}
irrecv.resume();
}
まとめ:赤外線リモコン受信システムの可能性
今回構築したシステムのポイントをまとめます:
📡 習得した技術
- IRremoteライブラリの使用方法 - 主要プロトコルの自動認識
- 赤外線信号のデコードと16進数表示 - 信号解析の基礎
- switch文を使った信号マッピング - 実用的な制御ロジック
- 状態管理変数による段階制御 - LEDの無段階調光の基礎
🚀 次のステップ
- 赤外線送信 - IRremote.cppを使って信号を送信する側も実装
- EEPROMへの保存 - 学習リモコンの作成
- センサー連携 - 温度/湿度/人感センサーとの組み合わせ
- 無線化 - ESP32/Wi-Fi/Bluetoothでスマホ連携
🔧 実用化に向けて
- ケースの設計 - 3Dプリンタでオリジナル筐体を作成
- 電源の最適化 - バッテリー駆動やUSB給電の選択
- 複数デバイス制御 - リレーモジュールで家電をON/OFF
赤外線リモコン受信は、IoT電子工作の第一歩として最適なテーマです。ここで学んだ技術を基に、あなただけのスマートホームデバイスを作ってみてください!