2021年4月15日木曜日

Raspberry Pi Picoと赤外線リモコン受信モジュールOSRB38C9AAで赤外線リモコンを受信する

Raspberry Pi Picoで赤外線リモコンで押されたボタンを取得するには、以下の手順を実行します。

〇Raspberry Pi Picoと赤外線リモコン受信モジュールOSRB38C9AAを接続した写真

実装手順

1. 部品の用意
以下の部品を用意します。

・赤外線リモコン受信モジュールOSRB38C9AA(2個入)
https://akizukidenshi.com/catalog/g/gI-04659/

・オプトサプライ赤外線リモコン
https://akizukidenshi.com/catalog/g/gM-07245/
※NECフォーマットの赤外線リモコンです。

〇オプトサプライ赤外線リモコンの写真

・コネクタ付コード 3P (黒赤黄)
https://akizukidenshi.com/catalog/g/gC-15384/
※これは必須ではないですが、配線がスッキリとできます。

2. Raspberry Pi Picoと赤外線リモコン受信モジュールを配線します
OSRB38C9AAのピン配列を受光面&足を下にした面から見て、
OSRB38C9AAの左側のピン -> Raspberry Pi PicoのGP2ピン
OSRB38C9AAの中央のピン -> Raspberry Pi PicoのGNDピン
OSRB38C9AAの右側のピン -> Raspberry Pi Picoの3V3(OUT)ピン(36番ピン)

3. 「Device drivers for IR (infra red) remote controls」モジュールの導入
Thonnyを利用する場合、mycropython_irモジュールのインストールは以下の手順を実行します。

3-1.micropython_irモジュールのダウンロード
以下のページからCode -> Download ZIPを選択して、モジュールのソースコードをダウンロードします。
ZIPファイルをダウンロード後、解凍しておきます。
https://github.com/peterhinch/micropython_ir

3-2.micropython_irモジュールのアップロード
Thonnyの「表示」メニューから→「ファイル」を選択します。Rapberry Pi Pico側に/libフォルダがなければ、ペイン下側のフォルダで右クリックメニューから[
New Directory...」を選択し、フォルダ名を入力して/libフォルダを作成します。

フォルダ作成ダイアログ

3.3.ローカルPCのフォルダ内のPythonモジュールをアップロード
Raspberry Pi Pico側の/libフォルダに移動後(左側ペインの下のlibフォルダをダブルクリックで移動)、ローカルPCのフォルダにあるir_rxフォルダで右クリックメニューから「upload to /lib」を選択してモジュールのライブラリをアップロードします。

4. プログラミングとプログラムのアップロード
以下のプログラムをmain.pyとしてRaspberry Pi Picoに保存して、実行します。実行後、オプトサプライ赤外線リモコンのボタンを押して、押したボタンに対応するメッセージがコンソールに表示されることを確認します。
main.py
import time
from machine import Pin
from ir_rx.nec import NEC_8

# オプトサプライ赤外線リモコンのデータと対応するボタンのメッセージ
keydata = {
0xD8:"Power button",
0xF8:"A button",
0x78:"B button",
0x58:"C button",
0xB1:"Upper left button",
0xA0:"Up button",
0x21:"Upper right button",
0x10:"Left button",
0x20:"Center button",
0x80:"Right button",
0x11:"Bottom left button",
0x00:"Down button",
0x81:"Bottom right button",
0xFF:"N/A"
}
last_code=0xFF

# 赤外線の信号を受信時に呼び出されるコールバック関数
def callback(data, addr, ctrl):
    global last_code
    if data < 0:  # repeat code -> 同じキーが繰り返しが押されたときの処理
        print(keydata[last_code])
    else:
        last_code = data
        print(keydata[data]) # キーデータに対応する文字列を表示します

# 2番ピンを使用するようにして、NEC 8bitクラスを初期化。上記のcallback関数を登録します。
ir = NEC_8(Pin(2, Pin.IN), callback)
# 無限ループ、信号を受信するとcallback関数が呼ばれます。
while True:
    time.sleep_ms(1000)

Q&A・応用編

Raspberry Pi Picoと赤外線リモコンモジュールと3つのLEDを接続した例です。コメント欄のQ&Aでのコードで使用した回路とコードは以下になります。

○回路図

○ブレッドボード上での実装例

※2022/02/28追記:001様のコメントに対するコード(その1)
A/B/Cボタンで点灯(BボタンLEDは点滅)、電源ボタンで消灯する例です。

import time
from machine import Pin
from ir_rx.nec import NEC_8
from machine import PWM

# オプトサプライ赤外線リモコンのデータと対応するボタンのメッセージ
keydata = {
0xD8:"Power button",
0xF8:"A button",
0x78:"B button",
0x58:"C button",
0xB1:"Upper left button",
0xA0:"Up button",
0x21:"Upper right button",
0x10:"Left button",
0x20:"Center button",
0x80:"Right button",
0x11:"Bottom left button",
0x00:"Down button",
0x81:"Bottom right button",
0xFF:"N/A"
}
last_code=0xFF


# 赤外線の信号を受信時に呼び出されるコールバック関数
def callback(data, addr, ctrl):
    global last_code
    if data < 0:  # repeat code -> 同じキーが繰り返しが押されたときの処理
        print(keydata[last_code])
    else:
        last_code = data
        print(keydata[data]) # キーデータに対応する文字列を表示します

pwm = PWM(machine.Pin(16, machine.Pin.OUT))
pwm.freq(1000)
#led1 = machine.PWM( machine.Pin(16, machine.Pin.OUT))
led2 = machine.Pin(17, machine.Pin.OUT)
led3 = machine.Pin(18, machine.Pin.OUT)


# 2番ピンを使用するようにして、NEC 8bitクラスを初期化。上記のcallback関数を登録します。
ir = NEC_8(Pin(2, Pin.IN), callback)
state_b = False
cnt = 0
# 無限ループ、信号を受信するとcallback関数が呼ばれます。
while True:
    time.sleep_ms(1)
    cnt = cnt + 1
    if last_code == 0x58:
        pwm.duty_u16(65535)
    elif last_code == 0xD8:
        pwm.duty_u16(0)
    if last_code == 0xF8:
        led3.value(1)
    elif last_code == 0xD8:
        led3.value(0)
    # last_codeはグルーバル変数でcallback関数にいつでも書き換えられるので、値をlocal_last_codeに保持
    #local_last_code = last_code
    #while local_last_code == 0x78:
    if last_code == 0x78:
        state_b = True
    elif last_code == 0xD8:
        state_b = False
        led2.value(0)
    if state_b == True:
        if cnt % 1000 < 500:
            led2.value(1)
        else:
            led2.value(0)

※2022/02/28追記: A/B/Cボタンを押している間のみ点灯(BボタンLEDは点滅)するように変更(その2)
import time
from machine import Pin
from ir_rx.nec import NEC_8
from machine import PWM

# オプトサプライ赤外線リモコンのデータと対応するボタンのメッセージ
keydata = {
0xD8:"Power button",
0xF8:"A button",
0x78:"B button",
0x58:"C button",
0xB1:"Upper left button",
0xA0:"Up button",
0x21:"Upper right button",
0x10:"Left button",
0x20:"Center button",
0x80:"Right button",
0x11:"Bottom left button",
0x00:"Down button",
0x81:"Bottom right button",
0xFF:"N/A"
}
last_code=0xFF
last_ticks = time.ticks_ms()


# 赤外線の信号を受信時に呼び出されるコールバック関数
def callback(data, addr, ctrl):
    global last_code
    global last_ticks
    last_ticks = time.ticks_ms() # callback関数が呼ばれた最後の時間を保存
    if data < 0:  # repeat code -> 同じキーが繰り返しが押されたときの処理
        print(keydata[last_code])
    else:
        last_code = data
        #print(keydata[data]) # キーデータに対応する文字列を表示します

pwm = PWM(machine.Pin(16, machine.Pin.OUT))
pwm.freq(1000)
#led1 = machine.PWM( machine.Pin(16, machine.Pin.OUT))
led2 = machine.Pin(17, machine.Pin.OUT)
led3 = machine.Pin(18, machine.Pin.OUT)


# 2番ピンを使用するようにして、NEC 8bitクラスを初期化。上記のcallback関数を登録します。
ir = NEC_8(Pin(2, Pin.IN), callback)
# 無限ループ、信号を受信するとcallback関数が呼ばれます。
state = False
state_cnt = 0
threshold = 400 # コールバック関数が最後に呼ばれて400ms経つと消灯処理を行います
while True:
    time.sleep_ms(100)
    # Bボタン
    if last_code == 0x78 and time.ticks_ms() - last_ticks < threshold:
        state_cnt = state_cnt + 1
        if state_cnt >= 10:
            state_cnt = 0
            if state:
                pwm.duty_u16(0)
                state = False
            else:
                pwm.duty_u16(65535)
                state = True
    # Aボタン
    elif last_code == 0xF8 and time.ticks_ms() - last_ticks < threshold:
        led2.value(1)
    # Cボタン
    elif last_code == 0x58 and time.ticks_ms() - last_ticks < threshold:
        led3.value(1)
    # 一定時間たったら消灯処理
    if time.ticks_ms() - last_ticks >= threshold:
        pwm.duty_u16(0)
        led2.value(0)
        led3.value(0)

※2022/02/28追記: Aボタンがトグル動作、B/Cボタンを押している間のみ点灯するように変更(その3)

import time
from machine import Pin
from ir_rx.nec import NEC_8
from machine import PWM

# オプトサプライ赤外線リモコンのデータと対応するボタンのメッセージ
keydata = {
0xD8:"Power button",
0xF8:"A button",
0x78:"B button",
0x58:"C button",
0xB1:"Upper left button",
0xA0:"Up button",
0x21:"Upper right button",
0x10:"Left button",
0x20:"Center button",
0x80:"Right button",
0x11:"Bottom left button",
0x00:"Down button",
0x81:"Bottom right button",
0xFF:"N/A"
}
last_code=0xFF
last_ticks = time.ticks_ms()


# 赤外線の信号を受信時に呼び出されるコールバック関数
def callback(data, addr, ctrl):
    global last_code
    global last_ticks
    last_ticks = time.ticks_ms()
    if data < 0:  # repeat code -> 同じキーが繰り返しが押されたときの処理
        print(keydata[last_code])
    else:
        last_code = data
        #print(keydata[data]) # キーデータに対応する文字列を表示します

pwm = PWM(machine.Pin(16, machine.Pin.OUT))
pwm.freq(1000)
#led1 = machine.PWM( machine.Pin(16, machine.Pin.OUT))
led2 = machine.Pin(17, machine.Pin.OUT)
led3 = machine.Pin(18, machine.Pin.OUT)


# 2番ピンを使用するようにして、NEC 8bitクラスを初期化。上記のcallback関数を登録します。
ir = NEC_8(Pin(2, Pin.IN), callback)
# 無限ループ、信号を受信するとcallback関数が呼ばれます。
state = False
state_cnt = 0
threshold = 400
state_a = False
while True:
    time.sleep_ms(100)
    # Bボタン
    if last_code == 0x78 and time.ticks_ms() - last_ticks < threshold:
        state_cnt = state_cnt + 1
        if state_cnt >= 10:
            state_cnt = 0
            if state:
                pwm.duty_u16(0)
                state = False
            else:
                pwm.duty_u16(65535)
                state = True
    # Aボタン
    elif last_code == 0xF8 and time.ticks_ms() - last_ticks >= 200:
        # トグル動作
        if state_a == True:
            led2.value(1)
            state_a = False
        else:
            led2.value(0)
            state_a = True
    # Cボタン
    elif last_code == 0x58 and time.ticks_ms() - last_ticks < threshold:
        led3.value(1)
    # 一定時間たったら消灯
    if time.ticks_ms() - last_ticks >= threshold:
        pwm.duty_u16(0)
        led3.value(0)
        last_code = 0xFF


2022/03/02追記:(その4)Aボタンで16ピンLEDが消灯・暗く光るのトグル動作にして、同じLEDがBボタンを押したときに明るく光るサンプル
import time
from machine import Pin
from ir_rx.nec import NEC_8
from machine import PWM

# オプトサプライ赤外線リモコンのデータと対応するボタンのメッセージ
keydata = {
0xD8:"Power button",
0xF8:"A button",
0x78:"B button",
0x58:"C button",
0xB1:"Upper left button",
0xA0:"Up button",
0x21:"Upper right button",
0x10:"Left button",
0x20:"Center button",
0x80:"Right button",
0x11:"Bottom left button",
0x00:"Down button",
0x81:"Bottom right button",
0xFF:"N/A"
}
last_code=0xFF
last_ticks = time.ticks_ms()


# 赤外線の信号を受信時に呼び出されるコールバック関数
def callback(data, addr, ctrl):
    global last_code
    global last_ticks
    last_ticks = time.ticks_ms()
    if data < 0:  # repeat code -> 同じキーが繰り返しが押されたときの処理
        print(keydata[last_code])
    else:
        last_code = data
        #print(keydata[data]) # キーデータに対応する文字列を表示します

pwm = PWM(machine.Pin(16, machine.Pin.OUT))
pwm.freq(1000)


# 2番ピンを使用するようにして、NEC 8bitクラスを初期化。上記のcallback関数を登録します。
ir = NEC_8(Pin(2, Pin.IN), callback)
# 無限ループ、信号を受信するとcallback関数が呼ばれます。
threshold = 400
half_light=False
while True:
    time.sleep_ms(100)
    # Bボタン:押している間は最大点灯
    if last_code == 0x78 and time.ticks_ms() - last_ticks < threshold:
        pwm.duty_u16(65535)
    # Aボタン
    if last_code == 0xF8 and time.ticks_ms() - last_ticks >= 200:
        # トグル動作
        if half_light == True:
            half_light = False
            last_code = 0xff
        else:
            half_light = True # 暗く光るようにフラグ設定
            last_code = 0xff
    # 一定時間たったらクリア
    if time.ticks_ms() - last_ticks >= threshold:
        if half_light == True:
            pwm.duty_u16(5000) # 消灯時に暗く光るように設定
        else:
            pwm.duty_u16(0)

18 件のコメント:

  1. このコードの解説を頂けると幸いです。

    返信削除
    返信
    1. コメントありがとうございます!ソースコードにコメントを追記してみました。

      削除
  2. オプトサプライのリモコンではない他の赤外線リモコンのコードを受け取って表示するというのは可能でしょうか?
    可能でしたら教えていただきたいです!

    返信削除
    返信
    1. 書き込みありあがとうございます!オプトサプライ製でなくても、データシートが公開されている製品であれば、コード値を書き換えれば対応できる可能性があるかと思います。

      削除
  3. 貴方様のソースコードに追加で
    while True:
    time.sleep_ms(1)
    if last_code == 0x58:
    led1.duty_u16(65535)
    elif last_code == 0xD8:
    led1.duty_u16(0)
    if last_code == 0xF8:
    led3.value(1)
    elif last_code == 0xD8:
    led3.value(0)
    while last_code == 0x78:
    led2.value(1)
    time.sleep(0.55)
    led2.value(0)
    time.sleep(0.55)

    を追加しLEDを点灯または点滅をさせているのですが。Bボタン【0x78】の点滅点灯ループ中【0x78】以外のボタンを押すとループから外れるのですがなぜか分かりますでしょうか。差し支えなければ教えていただけないでしょうか

    返信削除
    返信
    1. ピン設定は
      led1 = machine.PWM( machine.Pin(16, machine.Pin.OUT) )
      led2 = machine.Pin(17, machine.Pin.OUT)
      led3 = machine.Pin(18, machine.Pin.OUT)
      led1.freq(1000) 

      こちらです

      削除
    2. 書き込みありあがとうございます!led1に代入したオブジェクトはled2/led3と異なりPinオブジェクトではなく、PWMオブジェクトとなります。動作を確認したコードをレイアウトに崩れないために本ページに追記しましたので、ご参照ください。

      削除
  4. コードありがとうございます。
    新しいコードを反映させたのですがled2の点滅点灯進行中、ほかのボタンが入力されるとled2点滅ループから外れ消灯してしまいます。「time.sleep」の無いコードは、他のボタンに影響はありません


    すみません、追加で行き詰まりしてしまったのですが、同じボタンでledのON.OFF作業させたいのですが
    if last_code == 0x58:
    pwm.duty_u16(65535)
    elif last_code == 0x58:
    pwm.duty_u16(0)
    だと点灯されず同じボタンでON、OFFさせる方法はありますでしょうか。
    それと、ボタンを押しているときのみ点灯、ボタンを離すと消灯させるにはどのようなコードにするとよいのでしょうか。

    返信削除
    返信
    1. ごめんなさい間違えていました。last_codeはグローバル変数で、コールバック関数によって随時書き換えられるのでループから抜けてしまいます。本文の※その1のソースコードに抜けないように変更してみましたのでご確認ください。
      また、※その2のコードでボタンを押下している間に点灯し、信号を受信しなくなってから(=離してから)閾値時間以降に消灯処理を実行するプログラムも作成しましたので合わせてご確認お願いします。

      削除
    2. コードありがとうございます。説明不足ですみませんでした。度々すみません。今回のコードで別のボタンでループから抜けなくなったのですが、今度は先にled2を点滅させると他のledか点灯しなくなってしました。すみませんがお願いいたします。
      その2コードありがとうございます。苦戦していたので感動しました!

      もう1つすみません。on,をAボタン。off,をPowerボタンにしていたのですが
      同じボタンでon,をAボタンoff,もAボタンに処理したいのですがどのようにしたらよいですか。
      すみませんがよろしくお願いいたします。

      削除
    3. その1を変更して、電源ボタンが押されるまでled2が点滅するようにしてみました。また、その3で、Aボタンだけトグル動作にするようにしてみました。上記の3つのパターンを改造して、お好みの動作をするようにしてみてください。

      削除
    4. しっかりコントロールできるようになりました。カープラモデルにプログラムして点灯させてみたいと思います!
      ありがとうございました。

      削除
    5. このコメントは投稿者によって削除されました。

      削除
    6. すみません、再びわからないところがあるのですが 押しているときのみ点灯させるコードで、同じピンを違うボタンでコントロールし合う方法はありますか?
      【pwm = PWM(machine.Pin(16, machine.Pin.OUT))#16番ピン出力
       pwm1 = PWM(machine.Pin(16, machine.Pin.OUT))#16番ピン出力

      if last_code == 0x00:
      pwm1.duty_u16(20000)←ONで点灯
      elif last_code == 0xD8:
      pwm1.duty_u16(0)←OFFで消灯

      if last_code == 0x58:
      pwm.duty_u16(65535)←押したときの点灯
      elif last_code == 0xD8:
      pwm.duty_u16(0)】

      if time.ticks_ms() - last_ticks >= threshold:
      pwm.duty_u16(0)

      テールランプのように消灯時ブレーキを押すとブレーキ点灯、またスモールバルブ点灯時ブレーキを押すとスモール点灯しながらブレーキ点灯を同じLEDで行いたいです。よろしければよろしくお願いいたします

      貴方様引用コードでアレンジしたのがこちらです。

      import time
      from machine import Pin
      from ir_rx.nec import NEC_8
      from machine import PWM

      # オプトサプライ赤外線リモコンのデータと対応するボタンのメッセージ
      keydata = {
      0xD8:"Power button",
      0xF8:"A button",
      0x78:"B button",
      0x58:"C button",
      0xB1:"Upper left button",
      0xA0:"Up button",
      0x21:"Upper right button",
      0x10:"Left button",
      0x20:"Center button",
      0x80:"Right button",
      0x11:"Bottom left button",
      0x00:"Down button",
      0x81:"Bottom right button",
      0xFF:"N/A"
      }
      last_code=0xFF
      last_ticks = time.ticks_ms()


      # 赤外線の信号を受信時に呼び出されるコールバック関数
      def callback(data, addr, ctrl):
      global last_code
      global last_ticks
      last_ticks = time.ticks_ms()
      if data < 0: # repeat code -> 同じキーが繰り返しが押されたときの処理
      print(keydata[last_code])
      else:
      last_code = data
      print(keydata[data]) # キーデータに対応する文字列を表示します

      pwm = PWM(machine.Pin(16, machine.Pin.OUT))
      pwm1 = PWM(machine.Pin(16, machine.Pin.OUT))
      pwm.freq(1000)
      #led1 = machine.PWM( machine.Pin(16, machine.Pin.OUT))
      led2 = machine.Pin(17, machine.Pin.OUT)
      led3 = machine.Pin(18, machine.Pin.OUT)
      led4 = machine.Pin(15, machine.Pin.OUT)
      led5 = machine.Pin(14, machine.Pin.OUT)
      # 2番ピンを使用するようにして、NEC 8bitクラスを初期化。上記のcallback関数を登録します。
      ir = NEC_8(Pin(2, Pin.IN), callback)
      state_b = False
      cnt = 0
      state = False
      state_cnt = 0
      threshold = 200
      state_a = False
      state_c = False
      state_d = False
      state_e = False
      # 無限ループ、信号を受信するとcallback関数が呼ばれます。
      while True:
      time.sleep_ms(1)
      cnt = cnt + 1

      if last_code == 0x00:
      pwm1.duty_u16(20000)
      elif last_code == 0xD8:
      pwm1.duty_u16(0)

      if last_code == 0x58:
      pwm.duty_u16(65535)
      elif last_code == 0xD8:
      pwm.duty_u16(0)

      elif last_code == 0xF8 and time.ticks_ms() - last_ticks >= 200:
      if state_b == True:
      led3.value(1)
      state_b = False
      else:
      led3.value(0)
      state_b = True
      # last_codeはグルーバル変数でcallback関数にいつでも書き換えられるので、値をlocal_last_codeに保持
      # local_last_code = last_code
      #while local_last_code == 0x78:

      # Aボタン
      elif last_code == 0x78 and time.ticks_ms() - last_ticks >= 200:
      # トグル動作
      if state_b == True:
      led4.value(1)
      state_b = False
      else:
      led4.value(0)
      state_b = True

      if last_code == 0x80:
      state_a = True
      elif last_code == 0x20:
      state_a = False
      led2.value(0)
      if state_a == True:
      if cnt % 600 < 320:
      led2.value(1)
      else:
      led2.value(0)

      if last_code == 0x10:
      state_c = True
      elif last_code == 0x20:
      state_c = False
      led5.value(0)
      if state_c == True:
      if cnt % 600 < 320:
      led5.value(1)
      else:
      led5.value(0)

      if last_code == 0xA0:
      state_d = True
      elif last_code == 0x20:
      state_d = False
      led5.value(0)
      if state_d == True:
      if cnt % 600 < 320:
      led5.value(1)
      led2.value(1)
      else:
      led5.value(0)
      led2.value(0)

      if time.ticks_ms() - last_ticks >= threshold:
      pwm.duty_u16(0)
      last_code = 0xFF

      削除
    7. すいません、車のことは良くわかりませんが、Aボタンで16ピンLEDが消灯・暗く光るのトグル動作にして、同じLEDがBボタンを押したときに明るく光るサンプルを作成しましたので(その4)、これを参考に別ボタンで同一LEDを制御してみてください。

      削除
    8. 迅速な対応ありがとうございます。
      度々すみません。
      16ピンLEDをAボタンで消灯・暗く光るのトグル動作にして、同じLEDをB、Cボタンを押したときに明るく光る作動を、ほかのボタン(パワーボタン、ダウンボタンで出力は18ピン)にも採用させたのですが、 
      16ピンをON作動中、18ピンをON(トグル、押したときのみどちらも)したときライトがともったままフリーズしてしまいます。ピンが逆でも同じになってしまいます。(それ以外のピンには影響なしです)【True、False】の使い方が違うのでそうか。
      何か直すべき箇所や対策はありますでしょうか、


      import time
      from machine import Pin
      from ir_rx.nec import NEC_8
      from machine import PWM


      last_code=0xFF
      last_ticks = time.ticks_ms()


      # 赤外線の信号を受信時に呼び出されるコールバック関数
      def callback(data, addr, ctrl):
      global last_code
      global last_ticks
      last_ticks = time.ticks_ms()
      if data < 0: # repeat code -> 同じキーが繰り返しが押されたときの処理
      print(keydata[last_code])
      else:
      last_code = data
      print(keydata[data]) # キーデータに対応する文字列を表示します

      pwm = PWM(machine.Pin(16, machine.Pin.OUT))
      pwm2 = PWM(machine.Pin(16, machine.Pin.OUT))
      pwm3 = PWM(machine.Pin(18, machine.Pin.OUT))
      pwm.freq(1000)
      pwm2.freq(1000)
      pwm3.freq(1000)
      #led1 = machine.PWM( machine.Pin(16, machine.Pin.OUT))
      led2 = machine.Pin(17, machine.Pin.OUT)
      led4 = machine.Pin(15, machine.Pin.OUT)
      led5 = machine.Pin(14, machine.Pin.OUT)
      # 2番ピンを使用するようにして、NEC 8bitクラスを初期化。上記のcallback関数を登録します。
      ir = NEC_8(Pin(2, Pin.IN), callback)
      state_b = False
      cnt = 0
      state = False
      state_cnt = 0
      threshold = 200
      state_a = False
      state_c = False
      state_d = False
      state_e = False
      half_light=False
      half_light2=False
      half_light3=False
      # 無限ループ、信号を受信するとcallback関数が呼ばれます。
      while True:
      time.sleep_ms(1)
      cnt = cnt + 1
      # Cボタン
      if last_code == 0x58 and time.ticks_ms() - last_ticks < threshold:
      pwm.duty_u16(65535)
      #下ボタン
      if last_code == 0x00 and time.ticks_ms() - last_ticks < threshold:
      pwm3.duty_u16(65535)

      # トグル動作Aボタン
      if last_code == 0xF8 and time.ticks_ms() - last_ticks >= 200:

      if half_light == True:
      half_light = False
      last_code = 0xff
      else:
      half_light = True
      last_code = 0xff
      #Bボタン
      if last_code == 0x78 and time.ticks_ms() - last_ticks >= 200:
      if half_light2 == True:
      half_light2 = False
      last_code = 0xff
      else:
      half_light2 = True
      last_code = 0xff
      #電源ボタン

      if last_code == 0xD8 and time.ticks_ms() - last_ticks >= 200:
      if half_light3 == True:
      half_light3 = False
      last_code = 0xff
      else:
      half_light3 = True
      last_code = 0xff
      # last_codeはグルーバル変数でcallback関数にいつでも書き換えられるので、値をlocal_last_codeに保持
      # local_last_code = last_code
      #while local_last_code == 0x78:

      # 左下
      if last_code == 0x11 and time.ticks_ms() - last_ticks >= 200:
      # トグル動作
      if state_b == True:
      led4.value(1)
      state_b = False
      else:
      led4.value(0)
      state_b = True
      #右ボタン
      if last_code == 0x80:
      state_a = True
      elif last_code == 0x20:
      state_a = False
      led2.value(0)
      if state_a == True:
      if cnt % 600 < 320:
      led2.value(1)
      else:
      led2.value(0)
      #左ボタン
      if last_code == 0x10:
      state_c = True
      elif last_code == 0x20:
      state_c = False
      led5.value(0)
      if state_c == True:
      if cnt % 600 < 320:
      led5.value(1)
      else:
      led5.value(0)
      #上ボタン
      if last_code == 0xA0:
      state_d = True
      elif last_code == 0x20:
      state_d = False
      led5.value(0)
      if state_d == True:
      if cnt % 600 < 320:
      led5.value(1)
      led2.value(1)
      else:
      led5.value(0)
      led2.value(0)

      if time.ticks_ms() - last_ticks >= threshold:
      if half_light2 == True:
      pwm.duty_u16(65535)
      elif half_light == True:
      pwm.duty_u16(15000)
      elif half_light3 == True:
      pwm3.duty_u16(15000)
      else:
      pwm.duty_u16(0)
      pwm3.duty_u16(0)
      last_code = 0xFF

      削除
  5. うーん、ちょっとインデントが無いコードだと、どこでif-elseになっているかわからないですね。。。フリーズしそうな箇所の前にprint文でフラグやメッセージなどを入れてみて、原因を追求してみてください。

    返信削除
  6. ありがとうございます!インデントの整理をして if-elseを整理したところ影響なくボタンの操作ができるようになりました!

    返信削除