PICマイコンで赤外線リモコンを受信する。

秋月電子で、赤外線リモコンが\300であった。面白そうなので、PICマイコンで受信するプログラムを書いたが、意外と苦戦したので、備忘録として書いておこう。

卓球の練習マシンを作っていたが、上ローラー、下ローラー、発射角度、発射周期、首振りなど調整項目が多く、アナログボリュームだと配線が大変だし、なによりマイコンのアナログ入力のピン数が増える。赤外線リモコンが使えれば、入力はデジタル×1で済むし、パラメーターを記録しておける。

で、使用したPICは16F1503 14pinDIPパッケージ。PWMが4つあり、モーター制御に向いている。ただ、DCモーターとラジコンサーボでは、PWM周期が違いすぎて両立はできない。よって、サーボはタイマ割り込みを使うこととする。

上記のことから、赤外線の受信には16F1503を内蔵オシレーターでの最高周波数16MHzで使用、タイマ1のゲート機能を使うこととする。赤外線受信モジュールは、常時Highで受信するとLowと逆転するが、かえって都合がいい。Highの部分だけを見れば受信可能だ。

リーダーが4500us、0が560us、1が1600us、リピートが2300usということで、16ビットタイマの上位8ビットのみを使いカウントする。

//リモコン受信データ
unsigned char IRBUFF[4];
unsigned char read_state=0;
unsigned char ir_repeat;

void interrupt isr(void){
    unsigned static char byte_pos;
    unsigned static char bit_pos;
    unsigned static char skip=0;
    unsigned char cnt;

    if (TMR1IF){            //タイマ1がオーバーフローした場合。
        read_state = 0;     //読み取り状態をリセットする。
        ir_repeat = 0;
        skip = 1;           // タイマがオーバーフローしたら、そのときのパルスは無効。
        TMR1IF = 0;
    }
    if (TMR1GIF){
        cnt = TMR1H;    //パルス High時間を取得 2us/count(L) 512us/count(H)
        TMR1L = 200;    //タイマの値を初期化。0.5ms程度のパルスでカウントできるよう下駄はかせ
        TMR1H = 0;
        if (skip) skip = 0;
        else switch (read_state){
            case 0:     //ヘッダ待ちモード
                if(7<cnt && 11>cnt){  //3.8ms~4.9ms ならヘッダ
                    IRBUFF[0]=IRBUFF[1]=IRBUFF[2]=IRBUFF[3]=0;
                    read_state = 1;
                    bit_pos = 0;
                    byte_pos = 0;
                    ir_repeat = 0;
                }
                break;
            case 1:     //ヘッダ完了。データ待ちモード
                if(1 > cnt || 4 < cnt){
                    read_state = 0;
                }else{
                    IRBUFF[byte_pos] |= (cnt > 2) << bit_pos++;
                    if (bit_pos==8){ //8bit読んだら、次のバイトへ
                        byte_pos++;
                        bit_pos = 0;
                    };
                    if (byte_pos == 4){ //4byte読んだら終了、次のパルスは無視
                        skip = 1;
                        read_state = 2;
                    }
                }
                break;
            case 2:     //読み込み完了。リピート待ち。
                 if (6 > cnt && cnt > 3){
                    skip=1;
                    ir_repeat = 1;
                }else ir_repeat = 0;
            break;
        }
        TMR1GIF = 0;    //割り込みフラグを解除して
        T1GGO_nDONE = 1;//ゲート待機モードに
    }

}

 

PICマイコンで赤外線リモコンを受信する。」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)