センサーで壁の有無を判断し、迷路内を自律走行!!マイクロマウスで始める組み込み開発入門(14)(2/3 ページ)

» 2013年06月03日 09時30分 公開
[三月兎,MONOist]

 連載第10回で、センサー値を取得するプログラムを作成しました。今回は、それをベースに走行中に壁の有無を判断するプログラムを作成します。

 走行中に常に壁をチェックするので、割り込み処理を使います。これまで「CMT0」で1msの割り込み処理をしてきました。この1ms間に4つのセンサー値を取得します。「LEDをONにし、センサー値をA/D変換して、LEDをOFFにする」を行うのに90μsかかります。4つのセンサー値を次々に取得すると、トータルで360μs間は他の処理が何もできなくなってしまいます。4つのセンサーで値を1度に取得すると、その間は他の処理が何もできなくなってしまいます。そこで、新たな割り込み処理「CMT1」を作成し、4つのセンサー値を0.25msごとに順次取得します。


A)のようにCMT0内でセンサーを処理…… 画像1 A)のように「CMT0」内で4つのセンサーを処理しようとすると、その間に他の処理ができなくなる。センサー処理を「CMT1」に振り分けることで、長時間の割り込み処理を避ける

 それでは、センサー用の割り込み処理プログラムを作成しましょう。

 まず、CMT1を使う準備です。連載第8回でCMT0を扱ったときと同様に、「intprg.c」の中のCMT1を追記し、使用できるようにします(ソースコード2)。これで「CMT1」のコンペアマッチ割り込みが発生した際に、「int_cmt1」関数が実行されます。

// 188 CMT1 CMI1
//void INT_CMT1_CMI1(void){/* sleep(); */}
//CMT1割り込み(センサー)
extern void int_cmt1(void);
void INT_CMT1_CMI1(void){
    int_cmt1();
}
ソースコード2 「intprg.c」の自動生成ソースコードをコメントアウトし、これから作るタイマー割り込み関数「int_cmt1」を宣言する

 続いて、「init.c」内の「init_cmd」関数に、CMT1の初期化処理記述を追加します(ソースコード3)。

void init_cmt(void)
{
 
    (……中略……)
 
    //CMT1はセンサーチェック用タイマー
    CMT1.CMCSR.BIT.CMIE = 1;        //割り込みを許可
    CMT1.CMCSR.BIT.CKS = 0;         //カウントクロックPφ/8=3MHz
    CMT1.CMCSR.BIT.CMF = 0;         //フラグクリア
    CMT1.CMCOR = (3000/4)-1;        //0.25msごとに割り込み
    //
    INTC.IPRJ.BIT._CMT1 = 0x0e;     //割り込み優先度を次点に設定
 
    (……中略……)
 
    //
    CMT.CMSTR.BIT.STR1 = 1;         //CMT1カウント開始
    //
}
ソースコード3 「init.c」のCMT初期化関数「init_cmt」に、CMT1の初期化処理を追加する

 これでCMT1を使う準備ができました。次に画像1のフローチャートを参照して、「intrpt.c」にCMT1割り込み処理のint_cmt1関数を作成します(ソースコード4)。ここで使用するG_SensorRや他のグローバル変数は、「Mouse2012.h」で宣言したものを、「intrpt.h」で外部参照します。このとき、volatileを付けて宣言することに注意してください。「intrpt.h」には、タイマー1割り込みフラグ「CMT1_INT_F」の宣言も必要です。

/************************************************/
/*  CMT1割り込み処理            (int_cmt1)    */
/************************************************/
/*  センサーチェック用タイマー割り込み(0.25ms)*/
/*  0:右壁チェック                              */
/*  1:左壁チェック                              */
/*  2:前右壁チェック                            */
/*  3:前左壁チェック                            */
/************************************************/
void int_cmt1(void)
{
    //センサー用タイマー割り込み(0.25ms)
    static int state = 0;    //読み込むセンサーのローテーション管理用変数
    //
    CMT1_INT_F = 0;          //フラグクリア
    //
    switch(state)
    {
        case 0:             //右壁チェック
            G_SensorR = ctrl_adc_r();                 //右センサー値取得
            break;
        case 1:             //左壁チェック
            G_SensorL = ctrl_adc_l();                 //左センサー値取得
            break;
        case 2:             //前右壁チェック
            G_SensorFR = ctrl_adc_fr();               //前右センサー値取得
            break;
        case 3:             //前左壁チェック
            G_SensorFL = ctrl_adc_fl();               //前左センサー値取得
            break;
    }
    //
    state++;        //4回ごとに繰り返す
    if(state >= 4)
    {
        state = 0;
    }
}
ソースコード4 「intrpt.c」にCMT1割り込み処理を記述する

右手法で迷路を攻略

北上

よし! これでセンサー用の割り込み処理はOKだ。


えみ

「CMT0」と「CMT1」。2つの割り込み処理を使うのがポイントなんですね。


北上

そうなんだよ。4つのセンサー値を読み込む間も、マイクロマウスは走り続けているし、その間に他の処理を止めるわけにはいかないからね。


えみ

1度に4つの値を読まずに分割することで、待ち時間を分散しているんですね。


北上

うん。そういうことだよ。


えみ

360μsって、ほんの一瞬って思っちゃうけど……。


北上

そうだよね。でも、マイコンの処理スピードは速いからね〜。


えみ

“マイコンの世界”の時間感覚を意識してプログラミングするのが大事なんですね!


北上

うん。それじゃあ、迷路走行のプログラムを作ろうか!


えみ

はーい。



Copyright © ITmedia, Inc. All Rights Reserved.