えみちゃんも、だいぶマイコンの気持ちが分かってきたようですね。それでは、いよいよ迷路を自律走行するプログラムを作成していきましょう。
本稿では、「右手法」で迷路内を走るプログラムを作成します。しかし、実際は、連載第1回でも説明した通り、マイクロマウス競技の迷路は中央にゴールがあり、迷路内に回廊もあるため、基本的に右手法ではゴールに到達できる可能性はほとんどありません。
ここでは機体調整のために、“あえて右手法を採用”することにします。ゴールの概念は持たずに、迷路内を走り回ります。この右手法のロジックでどんな迷路も自由自在に走行できることを検証してから、迷路探索ロジックを搭載する方が、問題が発生したときに原因の切り分けが容易になります。
迷路走行(右手法)のフローチャートは画像2の通りです。
まず、走行中に壁の有無を判断するための関数を「ctrl.c」内に作成します(ソースコード5)。前壁は2つのセンサーで見ているので、前右センサーと前左センサーの平均値が閾値を超えているかをチェックします。
/************************************************/ /* 右壁チェック (ctrl_wall_chk_r) */ /************************************************/ /* 右センサーの値を取得し、閾値を超えているか */ /* チェックする */ /*----------------------------------------------*/ /* IN :int i_threshold … 閾値 */ /* RET:int … WALL_OFF(0):壁なし*/ /* WALL_ON(1) :壁あり*/ /************************************************/ int ctrl_wall_chk_r(int i_threshold) { //右壁チェック int ret; //右センサーの値が閾値を超えているかチェックする if (G_SensorR > i_threshold) { ret = WALL_ON; //壁あり } else { ret = WALL_OFF; //壁なし } return ret; } /************************************************/ /* 前壁チェック (ctrl_wall_chk_f) */ /************************************************/ /* 前右、前左センサーの値を取得し、平均値が閾値*/ /* を超えているかチェックする */ /*----------------------------------------------*/ /* IN :int i_threshold … 閾値 */ /* RET:int … WALL_OFF(0):壁なし*/ /* WALL_ON(1) :壁あり*/ /************************************************/ int ctrl_wall_chk_f(int i_threshold) { //前壁チェック int ret; //前右センサー、前左センサーの平均値が閾値を超えているかチェックする if ((G_SensorFR + G_SensorFL) / 2 > i_threshold) { ret = WALL_ON; //壁あり } else { ret = WALL_OFF; //壁なし } return ret; }
フローチャートに従って、モード6に迷路走行のプログラムを作成します(ソースコード6)。
/************************************************/ /* モード6の処理 (app_mode6) */ /************************************************/ /* 迷路走行 右手法 */ /************************************************/ void app_mode6(void) { //迷路内を右手法で走行する int wall_right; //右壁の有無 int wall_left; //左壁の有無 int wall_front; //前壁の有無 //MTUの周期を最低速度に設定する ctrl_mtu(MIN_SPEED, MIN_SPEED); //モーター励磁ON ctrl_mtr_pw(MTR_ON); //0.5秒wait ctrl_wait_ms(500); while(1) { //wait ctrl_wait_ms(100); //1区画進む ctrl_mtr_forward(ONE_BLOCK, NORMAL_SPEED); //横壁をチェックする wall_right = ctrl_wall_chk_r(WALL_THRESHOLD_R); //右壁チェック wall_left = ctrl_wall_chk_l(WALL_THRESHOLD_L); //左壁チェック //前壁をチェックする wall_front = ctrl_wall_chk_f(WALL_THRESHOLD_F); //前壁チェック //wait ctrl_wait_ms(100); //進行方向を決定(右手法) if(wall_right == WALL_OFF) { //右壁なし ⇒ 右に曲がる ctrl_mtr_turn(90); } else if(wall_front == WALL_OFF) { //前壁なし ⇒ そのまま } else if(wall_left == WALL_OFF) { //左壁なし ⇒ 左曲がる ctrl_mtr_turn(-90); } else { //袋小路 ⇒ 戻る ctrl_mtr_turn(180); } } //モーター励磁OFF ctrl_mtr_pw(MTR_OFF); }
それでは、プログラムをビルドして、迷路内でマイクロマウスを走らせてみましょう!
>>ソースコード(Mouse201306.lzh)のダウンロードはこちら
センパイ! センパイ! マイクロマウスが迷路を走りましたよっ!!
うん。やったね!
あっ! きゃー!! 壁にぶつかっちゃう!
……。
……あーあ。
まぁ、最初にこれだけ走れば上出来だよ!
10秒足らずで壁にぶつかるようじゃ、ゴールまで走るのは無理ですね……。どうしたらいいんでしょう?
今は、まだ“走行中の制御”をしていないからね。
モード6のソースコードを見て、気が付くことないかな?
……。1区画分進んだときに壁の有無を判断してますね。
そう。ということは?
えっとぉ〜。「CMT1」で0.25秒ずつ割り込みしている意味がないんじゃないかな?
ピンポーン! これから走行中に左右の壁を見ながら走るようにすれば、もっと安定して走るようになるよ。
ヤッター! じゃあ、すぐにプログラム組みましょう!!
そっか。休憩用にシュークリームを買っておいたけど……。
プログラムの修正を先にやろうか!
いや、シュークリームを先にお願いします!!
連載14回目にして、ようやくマイクロマウスが迷路内を自律走行しました(パチパチ〜!)。マイクロマウスが走れるようになると、すぐに迷路探索をしてゴールを目指したくなりますね。
しかし、ここが肝心です。動画2でご覧いただいたように、まだ制御ロジックを組み込んでいないので、すぐに壁にぶつかってしまいます。この段階で迷路探索をしても、ゴールにたどり着けないのは明らかです。そこで次回は、迷路内を安定して走行するための制御ロジックを組み込みます。お楽しみに!! (次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.