PR

ラズパイPico Wで赤外線リモコンを自作!送受信回路とPWM制御のやり方

ハードウェア制御 / 電子工作
スポンサーリンク

はじめに:ラズパイPico Wでエアコンを遠隔操作!自作スマートリモコンへの道

こんにちは、ニンジンです🥕
本記事は「愛犬を守る!格安IoT温湿度見守りLINE Botの作り方」の第4回になります。これまでの連載をまだお読みでない方は、ぜひ以下の記事からチェックしてみてくださいね。

スポンサーリンク

LINE通知の限界:外出先からの「エアコン遠隔操作」がどうしても必要だった理由

前回までの作業で、「室温が28度を超えたらLINEに通知が来る」という監視システムが無事に完成しました。 しかし、実際に運用してみて一つの大きな問題に気が付きました。

「危険な温度になった通知が来ても、結局その場に行かないとリスク回避(エアコンON)ができない!」

外出先で通知を受け取ったとき、遠隔でサッとエアコンをつけられたら最高ですよね。というわけで今回は、完成したシステムをさらにアップグレードし、Pico Wに「エアコンの赤外線リモコン機能」を追加してみたいと思います!

スポンサーリンク

今回やりたいこと:スマホのLINEから赤外線を飛ばしてエアコンを自由自在に操る!

今回具現化したい仕様は以下の3点です。

  • エアコンのリモコン信号を、学習リモコンのようにPico Wで読み取る
  • 読み取った信号を、Pico Wから赤外線(IR)として発信する
  • 発信するトリガーは、スマホのLINEから「冷房ON」とメッセージを送信すること(※LINE連携は次回の第5回の記事で実装します)

まずは物理的に「赤外線を読み取って、飛ばす」というハードウェアのハッキングから進めていきましょう!

スポンサーリンク

自作スマートリモコンに必要な電子部品リスト(赤外線LED・受光モジュール等)

今回は電子工作感がグッと増します。以下の部品を準備してください。

▼ メイン部品

赤外線受信モジュール:
  • 商品名: 赤外線受信モジュール 37.9kHz
    (PL-IRM1838B)
  • URL:https://akizukidenshi.com/catalog/g/g131157/
    ※在庫切れの場合は、同じ38kHz帯の「SPS-440-1(通販コード: 100614)」も定番として使えます。
赤外線LED:
トランジスタ(C1815):
抵抗①(保護用):
抵抗②(LED用):

▼ あると便利なグッズ

ブレッドボード:(配線が圧倒的に楽になります)

Pico W用ブレイクアウトボード:
(ピンの番号が一目でわかる優れもの)

スポンサーリンク

【結線図あり】ラズパイPico Wと赤外線パーツの配線・組み立て手順

部品が揃ったら、さっそく結線していきましょう。

各パーツの足の向き(極性)には注意が必要です。

■ 赤外線受信モジュール(PL-IRM1838B)のピン配置

正面(丸いレンズの突起がある面)を自分に向け、ピンを下にした状態のとき、左から以下の配置になります。

  1. OUT(信号出力)
  2. GND(グランド)
  3. VCC(電源)

■トランジスタ(C1815)のピン配置

平らな面(「C1815」と文字が印字されている面)を自分に向け、ピンを下にしたとき、左から以下の配置になります。

  1. エミッタ (E)
  2. コレクタ (C)
  3. ベース (B)

■ ブレッドボードへの接続手順

  1. 受信モジュールの OUTピン を、Pico Wの GP16(21番ピン)に接続します。
  2. 受信モジュールの GNDピン を、Pico Wの GND(38番ピンなど)に接続します。
  3. 受信モジュールの VCCピン を、Pico Wの 3V3(OUT)(36番ピン)に接続します。
  4. Pico Wの GP17(22番ピン)から 4.7kΩの抵抗 を経由して、トランジスタの 3番ピン(ベース) に接続します。(※これがPicoのピンを守る保護抵抗になります)
  5. トランジスタの 1番ピン(エミッタ) を、Pico Wの GND に接続します。
  6. Pico Wの VBUS(40番ピン・5V出力)から 100Ωの抵抗 を経由して、赤外線LEDの 長い足(アノード) に接続します。
  7. 赤外線LEDの 短い足(カソード) から、トランジスタの 2番ピン(コレクタ) に接続します。

💡 ワンポイント:なぜ3.3VではなくVBUS(5V)を使うの? 遠くまで届く強い赤外線を出すためには、より高い電圧と電流が必要です。そのため、3.3Vピンではなく、USBから直接きている5V(VBUS)からLEDの電源を取るように工夫しています。

スポンサーリンク

Pythonで実践!エアコンの赤外線(IR)信号の読み取りと発信テスト

回路が組めたら、実際にエアコンの信号をハッキング(読み取り)してみましょう!

リモコン信号の取得テスト(Get_IR.py)

Thonnyを開き、以下の受信用プログラムを実行します。

#Get_IR.py

import machine
import time

# 受光センサを接続したピンを GPIO 16 に変更
IR_PIN = 16
ir_sensor = machine.Pin(IR_PIN, machine.Pin.IN, machine.Pin.PULL_UP)

MAX_BUFF = 500 # 記録するパルスの最大数

print("=== 赤外線信号レコーダー準備完了 (GPIO16) ===")
print("リモコンをセンサに向けてボタンを押してください...")

while True:
# 信号がLO(0)になるのを待つ
if ir_sensor.value() == 0:
t_start = time.ticks_us()
times = []
last_val = 0

while True:
t_now = time.ticks_us()
val = ir_sensor.value()

if val != last_val:
elapsed = time.ticks_diff(t_now, t_start)
times.append(elapsed)
t_start = t_now
last_val = val

# 信号が約200ms途切れたら終了とみなす
if val == 1 and time.ticks_diff(time.ticks_us(), t_start) > 200000:
break

if len(times) >= MAX_BUFF:
break

print("\n--- 信号を受信しました! ---")
print(f"データ長 (パルス数): {len(times)}")
print("以下データをコピーして保存してください:")
print(times)
print("----------------------------")

time.sleep(1)
print("\n次の信号を待っています...")

実行すると、Thonnyのターミナルに「リモコンをセンサに向けてボタンを押してください…」と表示されます。

お手持ちのエアコンのリモコンを受信モジュールに近づけ(2cm以内)、「冷房ON」のボタンを押してください。ターミナルにズラッと「数字のリスト」が表示されれば、信号のコピー成功です!この数字のリストは後で使うので、メモ帳などにコピーしておいてください。

IR発信テスト(IR_Transmission.py)

次に、読み取った信号をPico Wから発信してみます。以下のプログラムの COOL_ON_DATA の部分に、先ほどコピーした数字のリストを貼り付けてから実行してください。

# IR_Transmission.py

import machine
import time

# 送信ピン(GPIO 17)の設定
TX_PIN = 17

# 先ほど取得したエアコン信号データ(冷房ON)
COOL_ON_DATA = [
####################ここを書き換えてください。
4307, 4535, 480, 1667, 523, 540, 483, 1619, 528, 1659, 516, 581, 469, 569, 529, 1607,
521, 610, 474, 586, 474, 1680, 518, 578, 488, 578, 473, 1606, 523, 1676, 473, 575,
537, 1616, 519, 1602, 525, 1685, 467, 1616, 525, 568, 568, 565, 528, 510, 522, 576,
472, 575, 522, 572, 478, 582, 523, 570, 540, 1613, 466, 1661, 482, 1682, 475, 1618,
523, 1647, 521, 564, 530, 578, 478, 581, 480, 575, 584, 504, 525, 575, 472, 572,
527, 580, 531, 1568, 527, 1624, 527, 1664, 526, 1614, 474, 1679, 477, 1665, 520,
1616, 477, 1681, 473, 8031, 4350, 4448, 532, 1667, 478, 576, 528, 1622, 484, 1662,
486, 574, 521, 565, 530, 1590, 574, 510, 583, 511, 528, 1605, 524, 579, 575, 505,
526, 1600, 525, 1619, 573, 506, 578, 1544, 622, 1623, 527, 1602, 521, 1601, 529,
506, 581, 580, 516, 568, 485, 582, 478, 571, 538, 582, 471, 580, 528, 567, 474,
1666, 473, 1670, 480, 1661, 479, 1679, 474, 1681, 475, 576, 520, 564, 527, 568,
473, 569, 518, 570, 523, 563, 520, 571, 479, 586, 479, 1668, 523, 1612, 531, 1590,
533, 1677, 482, 1615, 526, 1605, 522, 1674, 474, 1661, 527, 8558, 4399, 4457, 519,
1672, 478, 576, 524, 1603, 529, 1629, 530, 513, 527, 585, 521, 1615, 538, 498,
578, 574, 472, 1599, 576, 578, 478, 581, 481, 1600, 570, 1599, 534, 579, 523, 1545,
573, 1607, 538, 574, 519, 1596, 583, 1608, 523, 1625, 521, 1612, 535, 1543, 575,
1676, 477, 504, 577, 1653, 521, 573, 487, 553, 520, 560, 531, 568, 477, 578, 527,
504, 578, 1604, 531, 1612, 527, 575, 531, 511, 534, 561, 521, 576, 480, 573, 508,
581, 530, 568, 478, 581, 531, 1604, 530, 1618, 529, 1607, 527, 1600, 570, 1610,
531, 1605, 519, 8020, 4321, 4526, 479, 1666, 479, 563, 529, 1618, 527, 1621, 526,
584, 482, 577, 487, 1676, 468, 585, 519, 578, 524, 1608, 517, 570, 479, 571, 522,
1627, 521, 1657, 478, 584, 521, 1613, 532, 1617, 520, 567, 530, 1598, 514, 1666,
482, 1668, 475, 1667, 475, 1665, 480, 1664, 540, 507, 529, 1666, 478, 573, 528,
571, 477, 579, 521, 568, 521, 567, 473, 580, 523, 1596, 523, 1689, 478, 586, 479,
568, 527, 561, 528, 563, 476, 576, 530, 568, 522, 572, 482, 583, 474, 1621, 527,
1670, 480, 1674, 477, 1667, 476, 1618, 528, 1664, 481
]

def send_ir(data):
# 38kHzのPWMキャリア信号を設定(Duty比を約33%に設定)
pwm = machine.PWM(machine.Pin(TX_PIN))
pwm.freq(38000)

# 状態(ON=38kHzパルス出力、OFF=完全停止)を切り替える関数
def pwm_on():
pwm.duty_u16(21845) # 65535 の約1/3
def pwm_off():
pwm.duty_u16(0)

# データの長さに合わせてON/OFFを繰り返す
is_on = True
for us in data:
if is_on:
pwm_on()
else:
pwm_off()
time.sleep_us(us)
is_on = not is_on

# 送信終了後は必ずOFFにする
pwm_off()
pwm.deinit()

print("赤外線信号を送信します...")
send_ir(COOL_ON_DATA)
print("送信完了しました!")

「ピッ!」という音と共に、エアコンが冷房ONになれば大成功です!

🛠 トラブルシューティング(届かない原因と対策)

もし「赤外線が出ているはずなのにエアコンが反応しない!」という場合は、以下の3点を確認してみてください。

① 配線の再確認

初歩的ですが、抵抗の値(4.7kΩと100Ω)が逆になっていないか、トランジスタの向きが合っているかをもう一度確認しましょう。

② LEDの指向性(物理の要因)

一般的な赤外線LEDは「指向角(光が広がる角度)」が15度〜30度と非常に狭く、スポットライトのように真っ直ぐしか飛びません。LEDの先端が少しでもエアコンの受光部からズレると届かなくなります。テストする際は、LEDの頭をエアコンの受光部(黒い窓のような場所)へ正確に向けてみてください。

③ 5V(VBUS)電源の容量不足(回路の要因)

現在、Pico Wの「VBUS」ピンから電源を取っていますが、PCのUSBポートから供給されている電流の制限により、LEDの最大出力が出ていない可能性があります。自宅で実運用する際は、PCのUSBポートではなく、2A(アンペア)以上出力できるスマホ用の急速充電器(ACアダプタ)からPico Wに給電してください。これだけで赤外線の飛距離がグッと上がります!(当ラボの環境では5mまで届くことを確認済みです)

スポンサーリンク

【ちょっと脱線】なぜリモコンは「38kHz」じゃないとダメなの?

ここで少しだけ、マニアックだけど面白い電子工作の裏話をさせてください。「エアコンを動かすには、赤外線を38kHzで振動させないと認識しないよ」という話を聞いたことはありませんか?

そもそも、私たちの部屋の中には、蛍光灯の光や太陽光など、目に見えない赤外線がそこら中に飛び交っています。もし、ただ赤外線LEDを「ピカーッ」と光らせるだけだと、エアコン側は「これはリモコンの命令? それともただの部屋の明かり?」と区別がつきません。

そこで、リモコンの光を「1秒間に3万8000回(38kHz)という超猛スピードで点滅する特殊な光」にすることで、エアコンに「これは間違いなくリモコンからの暗号だ!」と認識させているんです。

では、今回の小さな回路の中で、一体誰がそんな超絶技巧をこなしているのでしょうか?実は、3つのパーツが見事な連携プレーを見せています。

① Pico WのPWM機能(頭脳と心臓)

プログラムの中にある pwm.freq(38000) というたった1行のコード。これがPico Wへの「1秒間に38,000回の電気の波を作れ!」という絶対命令です。Pico Wは内部の超高速タイマーを使い、Pythonの処理速度とは無関係に、正確無比な38kHzの波を自動生成してくれます。

② トランジスタ C1815(筋肉)

Pico Wから出た38kHzの波は、そのままでは電流が弱すぎてLEDを遠くまで光らせることができません。そこで「C1815」の登場です。Pico Wからの弱い波を受け取ると、このトランジスタが強力な5V電源を高速でカチカチとスイッチングし、強い電流の波に増幅してくれます。

③ 赤外線LED(発声器官)

増幅された強い38kHzの電流を受け取り、最終的に激しく点滅する「光の波」に変えてエアコンへと届けます。

つまり、Pico Wが波のタイミングを作り、トランジスタがパワーを増幅し、LEDが光として放つ。 この完璧なチームワークがあるからこそ、小さな電子部品の集まりで巨大なエアコンを意のままにコントロールできるんです! 仕組みが分かると、ブレッドボード上の小さな部品たちが急に頼もしく見えてきませんか?

スポンサーリンク

次回予告

今回は、ハードウェアを組み上げてエアコンの信号をハッキングし、Pico Wから直接赤外線を飛ばすところまで完成しました。
しかし、このままではまだ「PCからプログラムを実行しないと動かない」状態です。

次回(第5回)は、いよいよ今回の回路とLINEを連携させます!
Google Apps Script(GAS)を使ってネットワークの壁を越え、スマホから遠隔操作できる「完全自作スマートリモコン」を完成させますので、お楽しみに!



ニンジン🥕アイコン

Follow me on X

本ブログの中の人「ニンジン🥕」はXやってます。新着記事はいち早くポストでお知らせしているので、見逃したくない方は @ninjin_py_vba をフォローしてみてください🥕

@ninjin_py_vba をフォロー

この記事が役に立ったら、シェアしてもらえると嬉しいです🥕

Xでポスト はてブ LINE Pocket

PROJECT LOG — SERIES INDEX
スポンサーリンク

シリーズ記事一覧

電子工作・自動化ツールの製作記録をシリーズごとにまとめています。気になるテーマからお読みください。


Tapo P110Mの消費電力をExcelレポート化する【年次集計・電気代試算・セキュリティ判断編】
FastAPI+openpyxlでTapo P110Mの消費電力をExcelレポート化。15秒間隔の生ログを日次集計する設計や、31円/kWhでの電気代試算、外部公開を見送った理由まで解説します。
Tapo P110M × FastAPIで電力監視ダッシュボードを作る【SQLite記録・リアルタイム堅牢化編】
Tapo P110MのデータをSQLiteに記録し、FastAPI+Uvicornでリアルタイム電力監視ダッシュボードを作る方法を解説。通信失敗時の自動復旧など堅牢化のポイントも紹介します。
Tapo P110M × python-kasaで自作PDUを作る【環境構築・Unsupported device(TPAP)エラー解決編】
Tapo P110Mをpython-kasaで自作PDU化。「Unsupported device」TPAPエラーの原因と対処法、MACアドレスでIP変動に強くする設計、個別/一括ON-OFFの実装コードまで解説します。
Raspberry Pi Pico Wで作る熱中症警戒アラート表示器
Raspberry Pi Pico WとDHT11、0.96インチOLEDで熱中症警戒アラート表示器を自作。気温・湿度から簡易的な暑さ指数を計算し、5段階の顔アイコンで危険度を表示する作り方をコード付きで解説します。
CustomTkinterでオリジナルのメニューバー(File・表示・設定・Help)を自作する
CustomTkinterには無いメニューバー(File・表示・設定・Help)を、CTkFrameとCTkButtonで自作する方法を、5段階のサンプルコードとダウンロード付きで解説します。

コメント