Picot チュートリアル14

■リモコン受信プログラム

まずは、受信したデータコードをシェル画面に出力してボタンに対するデータの値を確認するプログラムです。6番端子を「remote_in」という名前で入力に設定します。

remote_in = Pin(6, Pin.IN, Pin.PULL_UP)

入力端子のHigh/Lowが変化したタイミングを知るために「外部割込み」関数を使います(もうひとつの割り込みは「タイマー割り込み」です)。これを利用すると、端子の状態を勝手にチェックしてくれて変化があった場合には指定の関数を自動で実行してくれます。(下記の文は1行です。)

remote_in.irq(trigger = Pin.IRQ_RISING | Pin.IRQ_FALLING, handler = int_handler)

入力信号の立ち上がり(RISING)、立ち下がり(FALLING)をトリガーとして「int_handler」関数が呼ばれるように設定しています。

プログラムは少し長いですが、図5-3と見比べながら追ってみてください。リモコン受光部からの出力がHIGHやLOWに変化するたびに「int_handler」が呼ばれ、前回からのHIGH時間、LOW時間を測定し受信データが1なのか0なのかを調べていきます。今、プログラムが受信波形の時間軸上のどこにいるのかを「rm_state」という変数に保持しながら進んでいきます。ステートマシンという方法です。

リスト14-1 remote_test.py

from machine import Pin
import time

# 設定
remote_in = Pin(6, Pin.IN, Pin.PULL_UP)

# 変数
rm_received = False  #信号受信完了した
digit = 0             #受信データの桁
rm_state = 0          #信号受信状況
rm_code = 0           #コード全体(32bit)
prev_micros = 0       #時間計測用

# 割り込み関数
def int_handler(pin):
    global rm_state #関数の外側のrm_stateと同じ変数であることを示すためにglobalと記す
    global prev_micros
    global digit
    global rm_code
    global rm_received

    if rm_state != 0:
        #時間間隔を計算
        width = time.ticks_us() - prev_micros    
        if width > 10000:
            rm_state = 0    #長すぎ
        prev_micros = time.ticks_us()

    if rm_state == 0:    #信号未達
        prev_micros = time.ticks_us()    #現在時刻(microseconds)を記憶
        rm_state = 1    #最初のHIGH->LOW信号を検出した
        rm_code = 0
        digit = 0
    elif rm_state == 1:    #最初のLOW状態
        if width > 9500 or width < 8500:    #リーダーコード(9ms)ではない
            rm_state = 0
        else:
            rm_state = 2    #LOW->HIGHで9ms検出
    elif rm_state == 2:    #9ms検出した
        if width > 5000 or width < 4000:    #リーダーコード(4.5ms)ではない
            rm_state = 0
        else:
            rm_state = 3    #HIGH->LOWで4.5ms検出
    elif rm_state == 3:    #4.5ms検出した
        if width > 700 or width < 400:
            rm_state = 0    #データ棄却
        else:
            rm_state = 4    #LOW->HIGHで0.56ms検出した
    elif rm_state == 4:    #0.56ms検出した
        if width > 1800 or width < 400:   #長すぎ 短すぎ
            rm_state = 0    #データ棄却
        else:
            # 新しいデータを上位のビットに格納
            if width > 1000:    #HIGH期間長い -> 1
                rm_code |= (1 << digit)
            else:             #HIGH期間短い -> 0
                rm_code &= ~(1 << digit)
            digit += 1  #次のbit

            if digit > 31:   #完了
                rm_received = True
                return
            rm_state = 3    #次のLOW->HIGHを待つ

remote_in.irq(trigger = Pin.IRQ_RISING | Pin.IRQ_FALLING, handler = int_handler)

while True:
    if rm_received == True:    #リモコン受信した
        rm_received = False    #初期化
        rm_state = 0      #初期化
        #図とは左右が逆であることに注意
        #下16bitがcustomCode
        custom_code = rm_code & 0xffff   
        #下16bitを捨てたあとの下8bitがdataCode
        data_code = (rm_code & 0xff0000) >> 16   
        #下24bitを捨てたあとの下8bitがinvDataCode
        inv_data_code = (rm_code & 0xff000000) >> 24    
        #反転確認
        if (data_code + inv_data_code) == 0xff:    
            print(“data_code=” + str(data_code))

プログラムを実行して、リモコン送信でシェル画面に数値が出てくることを確認してください。

割り込み関数内ではひたすら受信データ(32ビットのデータ)を蓄積していき、32ビットそろった段階でwhileループ内でデータの解析を行います。なお図13-1の受信データは時間的に左側が先ですが、来たデータは順に「rm_code」変数の下の桁からセットしていきますので左右が逆になります。

表 14-1  リモコン受信データ(キット付属のリモコン)

 電源69 MENU  71
TEST68+6467
<<7>21>>9
022– 25C13
112224394
48528690
766882974

Picot チュートリアル インデックス >>
Picot チュートリアル 15 プログラムを分ける >>

コメント

タイトルとURLをコピーしました