C言語

赤外線リモコン受信処理の設計

赤外線リモコンからのデータを受信する処理を設計していきます。
今回の仕様では、NECフォーマットのみとするため、NECフォーマット以外は考慮しませんが、NECフォーマットでない場合は、どうすればよいかは参考になるように説明していこうと思います。
また、この受信処理は、赤外線センサから信号の立ち下がりが発生したときに割り込み処理を起動し、この割り込み処理内で、受信処理を行います。
ただし、受信データの解析までは行いません。ここでは、受信したデータを設定し、受信が完了したらメイン処理に通知することを想定します。
受信データの解析はメイン処理で行います。

赤外線リモコンのフォーマットを確認

オシロスコープがない方が多いと思いますので、デバッグにてフォーマットを確認する方法を紹介します。
CS+のプロジェクトを新規に作成します。CS+のプロジェクト作成方法がわからない方は、「CS+を使ってマイコン基板と接続する」を参照ください。
また、オプション・バイトの設定の高速オンチップ・オシレーターは、32MHzを前提としますので、「RL78マイコンで必ず必要な設定(オプション・バイト)」を参照に設定してください。
赤外線リモコンのフォーマットを確認するために、main.cファイルに次のようなプログラムを作成します。

#include "iodefine.h"
#pragma interrupt timerCtrl(vect=INTTM01)

unsigned int cnt;
unsigned int debug[500];

void main(void);

void main(void)
{
    PM1 = 0x40U;
    TAU0EN = 1U;
    TPS0 = 0x0005;	/* CK00:1cnt=1us */
    TMR01 = 0x02CC;	/* HIレベル幅測定 */
    TMMK01 = 0;
    TS0 = 0x0002;
    __EI();

    while(1)
    {
        ;	/* 処理なし */
    }
}

static void __near timerCtrl(void)
{
    debug[cnt] = TDR01;
    cnt++;
    if( cnt >= 500 )
    {
        cnt = 0;
    }
}

このプログラムは、赤外線センサ受信の立ち下がり(HI→LO)になったときに、timerCtrl関数を実行します。
TDR01レジスタは、赤外線センサ受信の立ち上がりからタイマカウントを開始して、立ち下がりまでカウントを行います。このため、HI区間の時間がわかるようになっています。そして、その間のカウント値がTDR01レジスタに格納されているので、その値を読み出します。カウント値は、1カウントで1μsです。これで、立ち上がりの時間がどのようになっているかわかるため、そこから、リーダ部の時間、データの1の時間や0の時間がどのようになっているかを調べます。
LO区間の時間を知りたい場合は、TMR01 = 0x02CCをTMR01 = 0x028Cに変更することにより、赤外線センサ受信の立ち下がりからタイマカウントを開始して、立ち上がりまでカウントを行うようになります。このため、LO区間の時間がわかるようになります。

赤外線リモコン受信処理の設計

上記のプログラムから私の赤外線リモコンは、NECフォーマットに近いことがわかったので、それを基準に設計を行いたいと思います。
ただし、完全に一致しているかは判断が付かなかったので、
最初に、フォーマットについて、私の赤外線センサの受信機については、なにも受信していない場合、HIとなっており、最初のHI区間の時間は約4.5msでした、その後、約0.55msと約1.65msのどちらかが、32個ありました。それから、ボタンを押し続けた場合、約40msのHI区間があり、その後、約2.25msがありました。このため、NECフォーマットに似ていたため、NECフォーマットに準拠して受信処理を作成しようと判断しました。

リーダーコードは、4496μsがtypみたいなので、そこから、誤差として、38kHzの変調がかかっていると考えると、1Hzに約26μsと4496μsに高速オンチップ・オシレーターの誤差2%の約90μsを考慮して、4496μs±116μsとなるので、4380~4620の範囲ならリーダーコードと判断することとしました。
これと同じ考えで、リピートコードは、2248μsがtypみたいなので、 変調誤差の26μsと高速オンチップ・オシレーターの誤差2%の約45μsで、2170~2320の範囲ならリピートコードと判断することとしました。
同様の考えで、0と1の範囲を求めると、0が562μs(typ)、1が1686μs(typ)みたいなので、0が520~600μs、1が1620~1750μsで判定を行いたいと思います。
ただし、環境により想定通りでない可能性があるので、一旦は、上記の考えで設計してみたいと考えています。

次に受信の完了の判定ですが、リーダコードの後、32個の0/1のデータを受信したら受信完了とし、メイン処理に通知します。
このとき、受信したデータをメイン処理が参照するデータにコピーします。これは、メイン処理がデータを参照したときに、赤外線リモコン受信処理が割り込み処理なので、メイン処理が参照中にデータを書き換える可能性があるためです。
受信完了を通知したメイン処理側で受信データを取得したら、受信完了フラグを未完了の状態にする設計とします。

ボタンを押しっぱなしにした場合、私が使用するリモコンでは、リーダコードを受信してから、約98~100ms経過してからリピートコードが繰り返し送信される。このリピートコードは、40ms毎に繰り返されるように見えました。
仮にボダンを離してからすぐに次のボタンを押下しても、リーダーコードを受信するまでに9msのLO区間後にリーダコードの4.5ms経過してからでないと、次の受信を開始しないため、98ms+9msの107ms経過しても次のリーダーコードか、リピートコードを受信できなかった場合は、連続で押下していないものと判断することにします。
また、リピートコードを受信した後は、押しっぱなしだと、約31msの後、9msのLO区間後にリピートコードの2.25ms経過してからでないと次のリピートコードの受信を開始しないため、31ms+9msの40ms経過しても次のリピートコードを受信できなかった場合は、連続で押下していないものと判断することにします。

この赤外線リモコンにて、107msや40msの時間が経過して、押しっぱなしでないと判断した場合は、メイン処理にモータ停止指示を送ります。
赤外線リモコン受信処理では、あくまで、受信処理のみを行うことにより、役割分担を明確にします。

もし、107ms経過しても受信完了とならなかった場合は、受信データを破棄します。

簡単ではありますが、赤外線リモコン受信処理の設計は以上となります。
文書のみで分かりにくいとは思いますが、これから図を用いるなど改善していきたいと思いますので、今しばらくお待ちいただけると幸いです。


-C言語