電子工作 32 – 汎用リモコンのパルスを解読して利用する試み
- Reading IR signals from a remote control by a program written in PICBasic Pro -
概要
秋葉原のジャンクショップに行くと中古や新古品のリモコンが300円といった安い値段で売られている。何か利用できないか考えた末,一丁買って来て,その赤外線パルスを解析し,それに反応する受信ソフトをPICBasic Pro を使って作成してみることにした。これは後に電子工作31のトライアックのコントロールをリモコンの2個のキーを使ってやることを目指したものでもある。次のように行った。
1) 利用するリモコンのあるキーを押してIR受信モジュールで受け取り、その出力パルスの波形をオシロで読み取る。
2) 各パルスの大きさやパルス全体の並びを調べる。
3) 連続繰り返しパルスの1セットの”0”と”1”の並びを数え、2進と10進法で表わす。これをそのキー特有の理論値とする。
4) 受信側で、リモコンのあるキーを押した時に入ってくるパルスパターンを解析し、2進と10進法で表わすソフトを作成する。
5) 上の4)で作成したソフト(受信用PICに入っている)で、リモコンのあるキーを押した時に検知した数値と、上の3)の理論値を比較し一致するかどうかを調べる、一致すればLEDを点灯させる。
1) 使用したリモコンの写真
赤外線リモコンのキットとして7、8年以上も前に購入したものに付属してきたFUNAIのRC-7というもの。秋葉原のジャンクショップでもたまに見かける。
さまざまなキーの内の今回は”電源”と”テレビ/ビデオ”の2個のキーを使う(写真のキーの並びの最上段にある2個)。
2) 実験ボード回路図
”電源”と”テレビ/ビデオ”の2個のキーに反応し LED1、または、LED2 をそれぞれ点灯させる最も簡単な回路である。
3) リモコンのパルスパターンの解析
[”電源”と”テレビ/ビデオ”キー]
1チャンネルのPCオシロを使ってパルスパターンを読み取った。 すなわち、そのプローブの(+)を実験ボード上のIR受信モジュールの出力端子とPICのピン3との接続部と、また、その(−)をGNDにつないで行った。 その結果、下図に見られる様に、キーを押し続けると、同じパッターンが繰り返し出力されることが分かった。 これは“電源キー”を押し続けた時のオシロで検出された連続パルス群である。 繰り返される1パルスパターンの長さは110 ms、約10分の1秒。つまり、押し続けると同じパターンが約1秒間に10回繰返し出力される。
上記を5倍に拡大し、詳細に見ると以下の様になる。 最初に、リーダーと思われる39-40 msの幅の大きいパルスが現れる。 次いで 3.3 ms 位の中位の幅のパルス、それ以後はデジタルの“0”と“1”に相当する 0.7 ms と 2.5 ms の幅のパルスが連続する。
39-40 msの大きいパルスと 3.3 ms の中位のパルスは、このリモコンのどのキーを押しても共通して出力されるようで、それ以外の以下に示す24個のパルス(24 bits)を各キー特有のものと考え解読に使用する。 PICBasic Proでは 24 bitsを扱えないので、16 bits と 8 bits に分解して処理する。
リモコンの“電源”キーを押すと下の様なパルスが出力される。 この中でこのキー固有のパルスパターンは0 –23までの24個の“0”と“1”の並びで表わされると考える。つまり、別のキーからは別の並びのバルスパターンが出力される。 ここでは0 - 15 (16 bits) と 16 – 23 (8 bits)に分解して、理論固有値として表す。
a) 0 - 15 (16 bits)のパルス並びを2進と10進であらわすと %011110000010100030 = 30760
b) 16 – 23 (8 bits))のパルス並びを2進と10進であらわすと %01111101 = 125
同じように、リモコンの“テレビ/ビデオ”キーを押すと下の様なパルスが出力される。
a) 0 - 15 (16 bits)のパルス並びを2進と10進であらわすと %0111000000101000 = 28712
b) 16 – 23 (8 bits))のパルス並びを2進と10進であらわすと %11111101 = 253
プログラム
受信側の実験ボード回路で入力してくるパルスパターンを読み込むプログラムのロジック(要)は以下のようなものである。
1) Pulsinというパルス幅を読み込むユニークなコマンドを使う。
2) 合計4種類の違った幅のパルスを不等記号”<””>”を使って分類る。プログラム中で使われている範囲値はオシロで検討しながら半実験的に決めた。
3) 2進の”0”と”1”に相当する 約0.7msと 約2.5msの幅のパルス(全部で24 個/bits)をプログラム中で1個1個読み込んで16-bitと8-bit長さのCode (16 bit値)とCode1 (8 bit値)を合成する。 ここがこのプログラムのポイント。
4) 合成したCodeとCode1の2進値を10進値に変える。
5) 上記の各キー特有の理論値(30760, 125, 28712, 253)と実際に測定して作成したCodeとCode1の値を比較して、一致すれば対応するLED1、またはLED2をそれぞれ点灯させる。
‘************************ 'プログラミング備忘録 ****************************
‘Name of Program: IRrecTD.bas Works well !
'This program reads IR pulses from "DENGEN" and "TV/Video" keys of FUNAI RC-7 remote control.
'If those keys are pressed, LED1 or LED2 on the board flashes on and off. 2009.1.8
'*********************** Pin connection **********************
'12F629, 4MHz Internal Clock used
'Pin 1: Vdd (5.0V)
'Pin 8: Vss (GND)
'Pin 7: GPIO.0: output - connected to LED1
'Pin 6: GPIO.1: output - connected to LED2
'Pin 3: GPIO.4: input - connected to IR Receiver module
'Pin 4: GPIO.3: input - connected to MCLR via 10K resistor
'*********************** Main program ***********************
CMCON=7 'Comparator off
TRISIO=%011000 'all except GP3 and GP4 are outputs.
PlsWidth var word ’16-bit 値 #大きいリーダーパルスの幅の値を一時保存
PlsW300 var word ’16-bit 値 #3.3 ms パルスの幅の値を一時保存
PlsW var word ’16-bit 値 #0.7 msまたは 0,25 ms パルスの幅の値を一時保存
Code var word ’16-bit 値 #合成Code値を一時保存
Code1 var word ’16-bit 値 #合成Code1値を一時保存
LED1 var GPIO.0
LED2 var GPIO.1
Loop:
Code=0
Code1=0
Clear 'Clear the content of all variables -
Essential!
Low LED1
Low LED2
PlsWidth=0
Pulsin GPIO.4,1,PlsWidth 'Read the long leader pulse width at H level #GP4より取り入れたHレベル(+5V)のパルスの幅を変数PlsWidthに保存せよ、という意味
If (4200<PlsWidth) AND (4500>PlsWidth) then ‘Read the pulse with 39-40 ms #大きいリーダーパルスの検知
Pulsin GPIO.4,1,PlsW300 'Read the pulse with 3.3 ms #パルスの幅の読み込み
If (300<PlsW300) and (400>PlsW300) then #3.3 ms パルスの検知
Goto Countpls
Else
Goto Loop
Endif
Else
Goto Loop
Endif
Countpls: 'Formation of Code and Code1 #以下では “0”と“1”のパルスの並びを1個1づつ読んで16-bit値と8-bit値を合成する
'Checking Bit0 - 0-15 (16 bits) Power TV/Video
Pulsin GPIO.4,1,PlsW 'Read 24 working pulses Key Key
If 150>PlsW then Code.bit0=0 '0 is a small pulse (0.7 ms) 0 0 #16-bit値の最初の0.7 msパルスの検知 150>PlsWなら Codeの0-bit目を0とせよ
If 150<PlsW then Code.bit0=1 '1 is a large pulse (2.5 ms) #16-bit値の最初の0,25 ms パルスの検知 150<PlsWなら Codeの0-bit目を1とせよ
'Checking Bit1
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit1=0 '0 0
If 150<PlsW then Code.bit1=1
'Checking Bit2
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit2=0 '0 0
If 150<PlsW then Code.bit2=1
'Checking Bit3
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit3=0
If 150<PlsW then Code.bit3=1 '1 1
'Checking Bit4
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit4=0 '0 0
If 150<PlsW then Code.bit4=1
'Checking Bit5
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit5=0
If 150<PlsW then Code.bit5=1 '1 1
'Checking Bit6
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit6=0 '0 0
If 150<PlsW then Code.bit6=1
'Checking Bit7
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit7=0 '0 0
If 150<PlsW then Code.bit7=1
'Checking Bit8
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit8=0 '0 0
If 150<PlsW then Code.bit8=1
'Checking Bit9
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit9=0 '0 0
If 150<PlsW then Code.bit9=1
'Checking Bit10
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit10=0 '0 0
If 150<PlsW then Code.bit10=1
'Checking Bit11
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit11=0
If 150<PlsW then Code.bit11=1 '1 0
'Checking Bit12
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit12=0
If 150<PlsW then Code.bit12=1 '1 1
'Checking Bit13
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit13=0
If 150<PlsW then Code.bit13=1 '1 1
'Checking Bit14
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit14=0
If 150<PlsW then Code.bit14=1 '1 1
'Checking Bit15
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code.bit15=0 '0 0 #16-bit値の最後の0.7 msパルスの検知
If 150<PlsW then Code.bit15=1 #16-bit値の最後の0,25 ms パルスの検知
'Code=30760 in first 16 bits =%0111100000101000 (Power Key) #“電源”キーならこの値になる
'Code=28712 =%0111000000101000 (TV/Video Key) #“テレビ/ビデオ”キーならこの値になる
'Checking Bit16 - 16-23 (8 bits)
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code1.bit0=0 #8-bit値の最初の0.7 msパルスの検知 150>PlsWなら Code1の0-bit目を0とせよ
If 150<PlsW then Code1.bit0=1 '1 1 #8-bit値の最初の0,25 ms パルスの検知 150<PlsWなら Code1の0-bit目を1とせよ
'Checking Bit17
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code1.bit1=0 '0 0
If 150<PlsW then Code1.bit1=1
'Checking Bit18
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code1.bit2=0
If 150<PlsW then Code1.bit2=1 '1 1
'Checking Bit19
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code1.bit3=0
If 150<PlsW then Code1.bit3=1 '1 1
'Checking Bit20
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code1.bit4=0
If 150<PlsW then Code1.bit4=1 '1 1
'Checking Bit21
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code1.bit5=0
If 150<PlsW then Code1.bit5=1 '1 1
'Checking Bit22
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code1.bit6=0
If 150<PlsW then Code1.bit6=1 '1 1
'Checking Bit23
Pulsin GPIO.4,1,PlsW
If 150>PlsW then Code1.bit7=0 '0 1 #8-bit値の最後の0.7 msパルスの検知
If 150<PlsW then Code1.bit7=1 #8-bit値の最後の0,25 ms パルスの検知
'Code1=125 in last 8 bits =%01111101 (Power Key) #“電源”キーならこの値になる
'Code1=253 =%11111101 (TV/Video Key) #“テレビ/ビデオ”キーならこの値になる
Pause 20
If (Code=30760) and (Code1=125) then LED1ON ‘パルスを読んで合成したCodeとCode1の値が、理論値30760と125に一致したときLED1を点灯させる
If (Code=28712) and (Code1=253) then LED2ON ‘パルスを読んで合成したCodeとCode1の値が、理論値28712と253に一致したときLED2を点灯させる
Goto Loop
LED1ON:
High LED1 '0.1 ms 毎にLED1を点灯させる
Pause 100
Goto Loop
LED2ON:
High LED2 '0.1 ms 毎にLED2を点灯させる
Pause 100
Goto Loop
End
'*************** プログラムの終わり ******************
'Note:
'AKI Programmer's configurations:
'FOSC – INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable
'MCLR – MCLRpin, BODEN - Enable; CD - Disable; CDP – Disable
結論・余談
1) 汎用リモコンのIRパルスを読み込んでLEDを点灯させることが出来た。 24ビットのご利益か?誤動作全くなし。
2) 4種の異なる幅のパルスを判別・分類し、“0”と“1”のパルス並びを1個1個読んで16-bit値、8-bit値を合成する方法を明確に出来た。
3) 今回のプログラムでは5個ものWORDで領域を確保したので、12F629のメモリのほぼ95%消費した。 したがって、もっと多くのキーを使う場合は
メモリ2倍の12F683などを使う必要がある。
4) 電子工作31のトライアックのコントロールに、このリモコン受信回路を組み合わせて使う場合はソフトを多少変える必要がある。
5) スバラグぶりのエレキズズーのプロジェクト、熱中できたのがエガッタ!