コンテンツにスキップ

Raspberry Pi Pico で赤外線リモコンをつくる

赤外線信号を受信する

事前にCircuitPython を使った Raspberry Pi Pico の開発を済ませておく。

CircuitPython の赤外線リモコンライブラリをインストールする。

Introduction — Adafruit IRREMOTE Library 1.0 documentation

Releases · adafruit/Adafruit_CircuitPython_Bundle · GitHub

libディレクトリにadafruit_irremote.mpyをコピーする。

回路を組む。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Circuit Playground Express Demo Code
# Adjust the pulseio 'board.PIN' if using something else
import pulseio
import board
import adafruit_irremote

pulsein = pulseio.PulseIn(board.GP0, maxlen=500, idle_state=True)
decoder = adafruit_irremote.GenericDecode()

while True:
    print("Wait")
    pulses = decoder.read_pulses(pulsein)
    print("Heard", len(pulses), "Pulses:", pulses)
    try:
        code = decoder.decode_bits(pulses)
        print("Decoded:", code)
    except adafruit_irremote.IRNECRepeatException:  # unusual short code!
        print("NEC repeat!")
    except adafruit_irremote.IRDecodeException as e:     # failed to decode
        print("Failed to decode: ", e.args)

    print("----------------------------")

リモコンの電源ボタンを押しながらシリアルポートを確認すると、パルス幅の情報が出力される。

赤外線信号を解読する

赤外線信号の仕組みは以下が参考になる。

必要な情報は以下となる。

  • 赤外線信号は 点灯している時間[us] → 消灯している時間[us] → … を示している。
  • 先頭 2 つはリーダー信号の点灯時間、消灯時間を示す。
  • 赤外線信号のフォーマットはいくつか存在するので特定する必要がある。

エアコンのリモコンの電源 ON 操作を 3 回ほど行ってみて、信号を確認してみる。

最頻値より\(440us\)あたりが基準となるパルス幅と思われる。よって\(440us \approx 1T\)とする。

リーダー ON はおよそ\(8T\)、リーダー OFF はおよそ\(4T\)であるからフォーマットは家製協(AEHA)フォーマットと思われる。

補足: 赤外線リモコン受信モジュール OSRB38C9AA の出力波形

赤外線受信モジュールの出力をオシロスコープで観測し、赤外線受信モジュールにエアコンの赤外線信号を受信させてみる。

オシロスコープでサンプリングしたときのサンプリングレートが低いせいで波形がなまっているが、実際は矩形波である。

このモジュールは Active Low である。(何も受信していないとき、出力電圧は High ということ)

電圧が 0 のとき ON なので、ON の時間は約 3.5ms、直後の OFF の時間は約 1.7ms であることが分かる。

\(440us \approx 1T\)であるから、3.5ms は約 8T、1.7ms は約 4T であり、これらのパルスはリーダー信号であることがわかる。

赤外線信号を送信する

上記のコードのcode = decoder.decode_bits(pulses)が受信した信号である。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time

import adafruit_irremote
import board
import pulseio

pulsein = pulseio.PulseIn(board.GP0, maxlen=500, idle_state=True)
decoder = adafruit_irremote.GenericDecode()

# データを送信するときは38kHzに変調したパルスを送信する。これはライブラリがやってくれる。
# header: ヘッダーを指定する。AEHAフォーマットでは[8T, 4T]
# one: 1の信号を指定する。AEHAフォーマットでは[T, 3T]
# zero: 0の信号を指定する。AEHAフォーマットでは[T, T]
# ただしAEHAフォーマットでは1T=440us
pulseout = pulseio.PulseOut(board.GP1)
T = 440
transmitter = adafruit_irremote.GenericTransmit(header=[8 * T, 4 * T], one=[T, 3 * T], zero=[T, T], trail=T)

data = (196, 211, 100, 128, 0, 4, 24, 80, 108, 2, 0, 0, 0, 0, 0, 0, 0, 179)

while True:
    transmitter.transmit(pulseout, data)
    time.sleep(10)

エアコンは AEHA フォーマットで 照明は NEC フォーマットのため、以下で動く。

1
2
T = 562
transmitter = adafruit_irremote.GenericTransmit(header=[16 * T, 8 * T], one=[T, 3 * T], zero=[T, T], trail=T)
1
2
3
4
TOGGLE_LIGHT = (65, 182, 213, 42)
NIGHT_LIGHT = (65, 182, 61, 194)
BRIGHTEST_LIGHT = (65, 182, 101, 154)
TURN_ON_COOLING = (196, 211, 100, 128, 0, 4, 24, 80, 108, 2, 0, 0, 0, 0, 0, 0, 0, 179)

参考リンク

GenericTransmit incorrect param types · Issue #65 · adafruit/Adafruit_CircuitPython_IRRemote · GitHub

Adafruit_CircuitPython_IRRemote/examples/irremote_transmit.py at main · adafruit/Adafruit_CircuitPython_IRRemote · GitHub

照明制御

re0208.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import adafruit_irremote
import board
import pulseio


class RE0208:
    TOGGLE_LIGHT = (65, 182, 213, 42)
    NIGHT_LIGHT = (65, 182, 61, 194)
    BRIGHTEST_LIGHT = (65, 182, 101, 154)

    def __init__(self, pin: board.Pin) -> None:
        T = 562
        self.__pulseout = pulseio.PulseOut(pin)
        self.__transmitter = adafruit_irremote.GenericTransmit(header=[16 * T, 8 * T], one=[T, 3 * T], zero=[T, T], trail=T)

    def turn_off(self) -> None:
        self.__transmitter.transmit(self.__pulseout, RE0208.NIGHT_LIGHT)
        self.__transmitter.transmit(self.__pulseout, RE0208.TOGGLE_LIGHT)

    def turn_on(self) -> None:
        self.__transmitter.transmit(self.__pulseout, RE0208.BRIGHTEST_LIGHT)

    def set_night_light(self) -> None:
        self.__transmitter.transmit(self.__pulseout, RE0208.NIGHT_LIGHT)

赤外線信号送信を自身でやる

CircuitPython では 38kHz 変調が難しい。

赤外線リモコンの作り方

赤外線 LED を使った赤外線信号は 38kHz に変調されている。

赤外線信号を送信したい場合、ハードウェアは 38kHz で点滅させる必要がある。秒に直すと 26us である。

\[ 周期 = \frac{1}{38 \mathrm{kHz} \times 1000} = 2.63 \times 10^{-5} \mathrm{s} = 26 \mathrm{us} \]

26us のうちに点滅させないといけないらしいので、13us 単位で制御させないといけない。

Raspberry Pi Pico の CircuitPython では 1ms 間隔の制御も怪しい。