H8 MCUボードにイロイロつないでみる/1 - マザーボード?にMCUボードを乗せる
H8 MCUボードにイロイロつないでみる/2 - I/Oポートを増やす+温度センサーを付ける
H8 MCUボードにイロイロつないでみる/3 - ロータリーエンコーダをつけてみる
H8 MCUボードにイロイロつないでみる/4 - 赤外線リモコン受信素子をつけてみる
H8 MCUボードにイロイロつないでみる/5 - 周波数カウンタにしてみる
H8 MCUボードにイロイロつないでみる/6 - ・・・
ここまで、既にNET上に出尽くしたようなモノをつないできた訳で、いたずらにページを増やしているようにも見えてきましたが…
そもそも、このカテゴリでやってみたい事があったのですが、それには部品箱のパーツでは賄えない*1ので、只今、部品を注文中となっています。
で、先日、赤外線リモコン受光部で書いたように、赤外線受信素子を見つけましたので、ついでにつないでみようとなりました。
当該記事の通り、結構、出力に余計なパルスが出るみたいな感じなので、どうなる事やら?でのスタートです。
つなぐと言っても、Vcc、GND、OUTしか信号がないので、どうという事もないのですが、ソフト側でどう処理するか?によって、つなぐポートも変わってきます。
今回は、読み込みを割込み処理で行おうと考えましたので、以下のとおり、空いている割込みポートへ接続しました。
上図の電源に入っている100Ωと47μFは、入れないと余計なノイズで動作不能になる可能性があります。
また、以下の画像のとおり、受光素子にはフィルタを装着した方が良いです。
詳しいことは、NET上にいっぱいありますし、また、メーカーによってもイロイロなので、キチンとしたい場合は、別に情報を探してください。
ざっくりと基本的な感じは以下の図のとおりになります。
という決まりです。
尚、送信は38KHzで変調された信号*2ですが、受光素子の出力は、単にLパルスとHパルスに整形されたものになります。
さて、受光素子をつないで、リモコンから受信される波形が分かったところで、送られてきた信号をデータに直す方法を考えます。
これは、ソフトで行う訳ですが、今回は割込みを使う事にしたので、各パルスの始まりは割込みで検出、パルスの長さはタイマーを1個利用して計ってみます。
① 初期化
② IRQ処理
③ タイマー・オーバーフロー割込み
データ取り込みは、割込み処理で行う為、メイン処理は、①初期化を行い、状態が「取得終了」になるのを待てば良い。
再度、受信したい場合は、①初期化を行うだけで良い。
動作フローを貼り付けておきます(クリックで拡大)。
初期化部分と、割込み処理を中心に載せます。メイン処理は、一例です。
■ ヘッダ
※ ir_cdata[] を short から ushortに変更しました。
#define IR_MAX_CDATA_NUM (48) extern short ir_state; /* 処理状態フラグ */ extern short ir_ovfct; /* オーバーフローカウンタ */ extern short ir_wrptr; /* データ書込みポインタ */ extern ushort ir_cdata[IR_MAX_CDATA_NUM]; /* データ格納領域 */ enum { IR_WAIT, /* 最初のパルス待ち状態 */ IR_SAMPLE, /* パルス取得中 */ IR_DONE /* データ取得終了 */ }; void init_irrecv(void); bool is_irrecv_done(void);
■ 初期化処理
/* 赤外線素子ポート P94/#IRQ4 ITU-4を使用 */ short ir_state; /* 受信状態フラグ */ short ir_ovfct; /* オーバーフローカウンタ */ short ir_wrptr; /* データ書込みポインタ */ ushort ir_cdata[IR_MAX_CDATA_NUM]; /* データ格納領域 */ /************************************************************************/ /* */ /* 赤外線受信の初期化 */ /* */ /************************************************************************/ void init_irrecv(void) { ir_state = IR_WAIT; /* 受信状態フラグ */ ir_ovfct = 0; /* オーバーフローカウンタ */ ir_wrptr = 0; /* データ書込みポインタ */ /*------------------------------------------------------------ ITU-4をφ÷8でフリーラン(3.125MHz 20mSでOVF)で動作 するように準備しておく。 ------------------------------------------------------------*/ ITU4.TCR.BYTE = 0x83; /* クロック選択 1000 0011 */ ITU4.TIER.BIT.OVIE = 1; /* オーバーフローで割り込み */ ITU4.TCNT = 0; /* カウンタ値 */ /*------------------------------------------------------------ IRQ4を受付可能にして最初のパルスを待つ ------------------------------------------------------------*/ INTC.ISCR.BIT.IRQ4SC = 1; /* 立下りエッジで割り込む */ INTC.IER.BIT.IRQ4E = 1; /* IRQ4割り込み許可 */ } /************************************************************************/ /* */ /* 赤外線受信終了か? */ /* */ /************************************************************************/ bool is_irrecv_done(void) { return (ir_state == IR_DONE); }
■ 割込み処理
/************************************************************************/ /* vector 16 IRQ4 */ /************************************************************************/ __interrupt(vect=16) void INT_IRQ4(void) { /* 割り込み要因フラグクリア(読み込んでから"0"を書き込む) */ if(INTC.ISR.BIT.IRQ4F) INTC.ISR.BIT.IRQ4F = 0; /* 最初のパルス待ちの場合 */ if(ir_state == IR_WAIT) { ITU4.TCNT = 0; /* カウンタ値 */ ITU.TSTR.BIT.STR4 = 1; /* カウント開始 */ ir_state = IR_SAMPLE; /* 受信中 */ // 受信中のLED ON } /* 受信中の場合 */ else if(ir_state == IR_SAMPLE) { ir_cdata[ir_wrptr++] = ITU4.TCNT; /* カウンタ値取得 */ ITU4.TCNT = 0; /* カウンタクリア */ /* データが書き込めなくなったら終わり */ if(ir_wrptr >= IR_MAX_CDATA_NUM) { INTC.IER.BIT.IRQ4E = 1; /* IRQ4 Disable */ ITU.TSTR.BIT.STR4 = 0; /* カウンタ停止 */ ir_state = IR_DONE; /* 受信完了 */ // 受信中のLED OFF } } /* オーバーフローカウンタをクリア */ ir_ovfct = 0; } /************************************************************************/ /* vector 42 OVI4 */ /************************************************************************/ __interrupt(vect=42) void INT_OVI4(void) { /* TSRのOVFをクリア(読み込んでから書き込む) */ if(ITU4.TSR.BIT.OVF) ITU4.TSR.BIT.OVF = 0; /* OVFカウンタを+1した結果、OVFカウンタが2を超えていた場合 */ if(++ir_ovfct >= 2) { ITU.TSTR.BIT.STR4 = 0; /* カウンタ停止 */ INTC.IER.BIT.IRQ4E = 1; /* IRQ4 Disable*/ ir_state = IR_DONE; /* 受信完了 */ // 受信中のLED OFF } }
■ メイン処理例
#include "irrecv.h" /* IR recieve */ void main(void) { short ii; init_irrecv(); /* IR RECV 初期化*/ while(1) { /* IR受信 */ if(is_irrecv_done()) { if(ir_wrptr > 16) { printf("\r\nLeader = %d", ir_cdata[0]); for(ii = 1 ; ii < ir_wrptr ; ++ii) { /* テストでは、しきい値が4500となった */ if(ir_cdata[ii] < 4500) printf("0"); else printf("1"); } } init_irrecv(); } /* 他にメインループで行う処理を書く */ } }
以下に、手元にあったリモコン4種で取得したデータを載せます。
L は、リーダー部、その後のデータは、"0"か"1"の判断とカウント値です。
リーダー部の長さが違いますが、データとしては、ほぼ理屈通りとなっているようです。
Ori | Pana | LCD TV | CATV |
L = 41550 | L = 16412 | L = 42096 | L = 16385 |
0 - 3482 | 0 - 2742 | 0 - 3520 | 0 - 2746 |
0 - 3478 | 1 - 5461 | 0 - 3516 | 1 - 5394 |
0 - 3478 | 0 - 2741 | 1 - 7004 | 0 - 2745 |
0 - 3478 | 0 - 2738 | 0 - 3520 | 0 - 2741 |
0 - 3478 | 0 - 2737 | 0 - 3516 | 0 - 2741 |
0 - 3478 | 0 - 2738 | 0 - 3515 | 0 - 2740 |
0 - 3479 | 0 - 2738 | 0 - 3515 | 0 - 2741 |
0 - 3480 | 0 - 2738 | 1 - 7004 | 0 - 2741 |
1 - 6921 | 0 - 2739 | 0 - 3518 | 0 - 2741 |
0 - 3482 | 0 - 2739 | 0 - 3516 | 0 - 2741 |
0 - 3479 | 0 - 2738 | 0 - 3515 | 0 - 2741 |
1 - 6921 | 0 - 2738 | 0 - 3516 | 0 - 2741 |
1 - 6925 | 0 - 2739 | 0 - 3516 | 0 - 2740 |
1 - 6924 | 1 - 5460 | 1 - 7005 | 1 - 5395 |
1 - 6925 | 0 - 2742 | 1 - 7008 | 0 - 2743 |
1 - 6990 | 0 - 2739 | 1 - 7008 | 0 - 2741 |
1 - 6924 | 0 - 2738 | 1 - 7009 | 0 - 2740 |
0 - 3481 | 0 - 2739 | 0 - 3520 | 0 - 2742 |
0 - 3480 | 0 - 2738 | 0 - 3515 | 0 - 2741 |
1 - 6920 | 0 - 2739 | 0 - 3515 | 0 - 2740 |
0 - 3482 | 1 - 5459 | 0 - 3516 | 0 - 2741 |
0 - 3478 | 1 - 5464 | 0 - 3515 | 0 - 2741 |
0 - 3479 | 0 - 2743 | 0 - 3515 | 0 - 2741 |
0 - 3555 | 1 - 5460 | 0 - 3514 | 1 - 5394 |
0 - 3480 | 0 - 2741 | 0 - 3516 | 0 - 2745 |
1 - 6922 | 0 - 2739 | 1 - 7004 | 1 - 5394 |
1 - 6924 | 0 - 2737 | 1 - 7009 | 1 - 5398 |
0 - 3482 | 0 - 2739 | 1 - 7009 | 0 - 2745 |
1 - 6921 | 0 - 2737 | 1 - 7008 | 0 - 2741 |
1 - 6925 | 0 - 2740 | 1 - 7008 | 1 - 5394 |
1 - 6925 | 0 - 2738 | 1 - 7009 | 0 - 2745 |
1 - 6933 | 0 - 2739 | 1 - 7009 | 0 - 2742 |
1 - 63398 | 0 - 2738 | 0 - 2741 | |
1 - 34601 | 0 - 2738 | 0 - 2741 | |
0 - 2738 | 0 - 2742 | ||
0 - 2737 | 0 - 2741 | ||
1 - 5461 | 0 - 2741 | ||
0 - 2741 | 1 - 5394 | ||
0 - 2739 | 1 - 5399 | ||
0 - 2738 | 0 - 2745 | ||
0 - 2738 | 0 - 2740 | ||
0 - 2738 | 1 - 5394 | ||
0 - 2738 | 1 - 5398 | ||
0 - 2738 | 0 - 2745 | ||
0 - 2737 | 0 - 2742 | ||
1 - 5461 | 0 - 2741 | ||
0 - 2742 | 1 - 5395 |