下図に、マイコンATtiny44Aを使った赤外線リモコン受信回路の例を示します。
16ビットタイマ/カウンタ1(以降タイマ1)を使って解析するため、赤外線受信モジュールの出力をICP1端子に入力します。
ここでは、赤外線リモコンの信号を解析・デコードした結果どのような動作をするか、あるいはどのような機能を果たすかなどについては触れません。
ATtiny44Aは一つの例です、製作する場合は、目的とする動作や機能を実現できるマイコンを選定することが必要です。
2.NECフォーマットとは
下図にNECフォーマットを示します。
図のように、LOW(キャリア有)とHI(キャリア無し)のパルス幅の組み合わせで、リーダーコード/リピートコード,データ0/1を表します。したがって、パルス幅を測ることがリモコン信号の解析に必要です。
扱えるデータはカスタムコード(メーカーコードともいう)とデータコードの計2バイトで、それぞれ反転データを送ることによってエラーチェックするようになっています(下図のデータ部参照)。ちなみに、反転データとはビットごとに'0'と'1'を反転したデータで、例えば0xAAの反転は0x55となります。
下図は、赤外線受信モジュールの出力信号をイメージしているので、38kHzの赤外線キャリアがあるところがLOWになっています。
参考:
カスタムコード(メーカーコード)はルネサスエレクトロニクスで管理されているようですが、その割り当て内容は公開されていないようです。
赤外線リモコンを自作するような場合、既存のカスタムコードと重複してしまう可能性があるのでご注意ください。
カスタムコード(メーカーコード)はルネサスエレクトロニクスで管理されているようですが、その割り当て内容は公開されていないようです。
赤外線リモコンを自作するような場合、既存のカスタムコードと重複してしまう可能性があるのでご注意ください。
3.リモコン信号の解析方法
以降で紹介するプログラム例では、リモコン信号の解析を、マイコンATtiny44Aのタイマ1のインプットキャプチャ機能を使って、受信信号のパルス幅を測ることによって行っています。
下図は、インプットキャプチャ機能を使ってパルス幅を測定する方法を、リモコン信号の先頭部分を例に説明する図です。
タイマ1のインプットキャプチャ機能は、ICP1端子のH/Lが変化したときのタイマカウンタの値を保持するので、前回の変化からの時間つまりパルス幅を測ることができます。しかも、割り込みを発生できるので、メインの処理にほとんど影響を与えずに動作可能です。
ただ、AVRマイコンのタイマ1には立上りと立下りの両エッジを検知する機能がないので、インプットキャプチャ割り込みによってエッジを検知する都度、検知するエッジの方向を再設定しています。
リモコン信号の解析は、どのような幅のパルスが、どのような順に受信されたかによって行っています。文章ではわかりにくいので、以降に示すフローチャートやソースリストをご覧ください。
プログラムでは、パルス幅にある程度の許容範囲をもって判定していますが、ノイズのような規定にない幅のパルスが含まれていた場合は無視するようにしているため、場合によってはリモコンのボタンが効かないとかリピートが止まるというようなことが発生します。
データ部のエラーチェックは、メーカーコードとデータコードそれぞれについて、反転コードをさらに反転したものと一致するかで判断します。一致しなければ受信エラーとして無視します。
4.プログラム例
下記に、NECフォーマット赤外線リモコンの解析プログラム例を示します。
システムクロック8MHzのATtiny44A用に作ったものですが、若干の修正で、ほかのAVRマイコンで使用できると思います。
・解析プログラムのフローチャート
・解析プログラムのソースファイル(IrRcReceive.c)
・解析プログラムのヘッダファイル(IrRcReceive.h)
注意:必ずしも正常にコンパイルおよび正常に動作することを保証するものではありません。
■独自型宣言など
BYTE → unsigned char
WORD → unsigned short
BOOL → int
FALSE = 0
TRUE = 1
NULL = 0
これらは、ヘッダファイル"hdwareInfo.h"で宣言していますが、このプログラム例には含まれていません。
BYTE → unsigned char
WORD → unsigned short
BOOL → int
FALSE = 0
TRUE = 1
NULL = 0
これらは、ヘッダファイル"hdwareInfo.h"で宣言していますが、このプログラム例には含まれていません。
5.関数の説明
前記ソースファイルにある関数について、使用方法を説明します。
(1)タイマ1の初期化と赤外線リモコン信号の受信準備
void Init_TIMER1(void)
タイマ1の初期化と受信準備を行います。
マイコンの起動後に、割り込みマスク状態で一度だけ呼ぶ必要があります。
割り込みマスクは、メインループに入るまでに解除してください。
(2)赤外線リモコンのカスタムコードとデータコードを取得
BYTE Get_IrRcCode(BYTE* pbyMaker, BYTE* pbyData)
受信したカスタムコードとデータコードを取得します。
リモコン信号を受信していない場合、またはエラーがある場合は0を返します。
引数の意味は次のようになっています。
pbyMaker = カスタムコードを格納するアドレス。
pbyData = データコードを格納するアドレス。
なお、リピートコードを受信した場合は、直前に受信したカスタムコードとデータコードを再度受信したものとみなし、通常と同じように返します。したがって、リピートコードを受信したかどうかは判別できません。
(3)赤外線リモコンのデータコードを取得
BYTE Get_IrRcButton(BYTE* pbyData)
受信したデータコードを取得します。ただし、カスタムコードがヘッダファイル"IrRcReceive.h"で定義されているRC_MAKERと一致しているもののみを取得します。この関数を使用する場合は、使用するリモコンのカスタムコードをRC_MAKERとして定義しておいてください。
リモコン信号を受信していない場合、またはカスタムコードが一致しない場合、あるいはエラーがある場合は0を返します。
引数の意味は次のようになっています。
pbyData = データコードを格納するアドレス。
通常は一つのメーカーコードのリモコン信号だけ受け付ければよいと思うので、関数Get_IrRcCodeを使わずに、この関数のみで問題ないと思います。
なお、リピートコードを受信した場合は、直前に受信したカスタムコードとデータコードを再度受信したものとみなし、通常と同じように返します。したがって、リピートコードを受信したかどうかは判別できません。
備考:
プログラム例は、オプトサプライの赤外線リモコン「OE13KIR」を想定して作られています。そのため、ヘッダファイル"IrRcReceive.h"でRC_MAKERは0x10となっているほか、各押しボタンのコードが定義されています。
プログラム例は、オプトサプライの赤外線リモコン「OE13KIR」を想定して作られています。そのため、ヘッダファイル"IrRcReceive.h"でRC_MAKERは0x10となっているほか、各押しボタンのコードが定義されています。
6.使用上の注意
前出の図にもあるように、NECフォーマットでは、リモコンのボタンを押すと108mS間隔でリピートコードを送信します。そのため、ON/OFFボタンが共通のリモコンの場合、その信号をそのまま素直に受け付けると、ON/OFFを繰り返してしまうのでご注意ください。
もう1点、リピートコードに関するものですが、最初のリピートコードはデータ部の終わりから数十mSで送信され、以後のリピートコードより短い時間でやってきます。そのため、108mS間隔でリピート信号が来ると期待していると、思わぬ動作をすることもあるのでご注意ください。
そのような場合、筆者としては最初のリピートコード、つまりデータ部の次のリピートコードを無視することを提案します。