課題2は「ライントレーサー」。ただ線上を動くのではなく点P、Qで停止しつつピンポン玉を運び、それをゴールで打ち出すことが条件になる。私が担当したのはCからAのルート。
以下、ロボットとプログラムを説明していく。
光センサー自体はキットに付属されていたものだが、工夫したのはセンサーを取り付ける位置である。
上図のようにセンサーはロボットの内側に組み込んだ。最初センサーをヘッドの部分に取り付け際、ロボットの本体の位置とセンサーの位置にズレが生じ、ロボットがラインからはみ出してしまった。そのためセンサーを内側に組み込みズレをなくし、ロボットがライントレースを確実にできるようにした。
続いてピンポン玉をつかむアームの部分。私たちのチームはつかんで運ぶのではなく、カバーのようなものでピンポン玉を覆い、押し運ぶようにした。
ギアを2つ使い、アームの上げ下げが可能になった(上左図)。
また、シュートがまっすぐ放たれなかったため、ロボの下側にバンパーをつけシュート時にピンポン玉がまっすぐ進むように改善した(上右図)。シュートに関しては、ピンポン玉をシュートするときはアームを上げたままにして、ロボが一度後ろに下がりそこから前進してピンポン玉を押す形でできる。
こうしてできたロボットが左図である。かなりシンプルでコンパクトな形となった。
まずはプログラムの中で使用する一定の動きや数値を定義する。
#define threshold 45 #define hipower 7 #define lowpower 2 #define set_power_H SetPower(OUT_AC,hipower); //モータを動かす力 #define set_power_L SetPower(OUT_AC,lowpower); //モータを動かす力 #define go_forward set_power_H;OnRev(OUT_AC); //前進 #define turn_left1 set_power_L;OnRev(OUT_C);OnFwd(OUT_A); //左折1 #define turn_left0 set_power_L;OnRev(OUT_C);Off(OUT_A); //左折0 #define turn_right0 set_power_L;OnRev(OUT_A);Off(OUT_C); //右折0 #define turn_right1 set_power_L;OnRev(OUT_A);OnRev(OUT_C); //右折1 #define step 1 #define nMax 3 #define short_break Off(OUT_AC);Wait(20); //休止 #define cross_time 30 //交差点を渡る時間 #define cross_line OnRev(OUT_AC);Wait(cross_time);short_break;Wait(200); //交差点を渡る #define Qmade 1100 #define Pmade 1600 #define Pkara 2600 #define ageru OnRev(OUT_B);Wait(9);Off(OUT_B); //アームを上げる #define sageru OnFwd(OUT_B);Wait(15);Off(OUT_B); //アームを下げる #define utsu OnFwd(OUT_AC);Wait(50);ageru;OnRev(OUT_AC);Wait(50);Off(OUT_AC); //シュート
左折と右折は、片方のタイヤを止めて曲がるものと進行方向に対して逆回転させて曲がるという2種類のプログラムを定義した。QmadeはCからライントレースを開始してからの時間、PmadeはQからPまでの時間、Pkaraは地点Pからの時間となっている。
サブルーチンを使用して通常のライントレースと交差点を渡る場合のプログラムを書いた。
この時のプログラムは以下の通り。
sub line_traceN() //通常のトレース { if (SENSOR_2 < threshold -8) { turn_left1; //37以下の時左折 } else if (SENSOR_2 < threshold -3) { go_forward; //37以上42より下の時前進 } else if (SENSOR_2 < threshold -1) { turn_right0; //42以上44より下の時右折0 } else { turn_right1; //それ以外の場合右折1 } Wait(step); }
数値で少し細かく場合を分け、よりなめらかにトレースできるようにした。
プログラムは以下の通り。
sub line_traceK() //交差点でのトレース { int nOnline=0; //続けて黒になった回数(カウンタ) sageru; while (FastTimer(0) <= Pmade+1) { while (nOnline < nMax) { //黒を続けてnMax回繰り返さない間 if (SENSOR_2 < threshold -8) { turn_left1; //37以下の時左折1 nOnline++; //カウンタを増やす } else { if (SENSOR_2 < threshold -6) { turn_left0; //37以上39より下の時左折0 } else if (SENSOR_2 < threshold -3) { go_forward; //39以上42より下の時前進 } else if (SENSOR_2 < threshold -1) { turn_right0; //42以上44より下の時右折0 } else { turn_right1; //それ以外の場合右折1 } nOnline=0; //カウンタをリセット } Wait(step); } short_break; turn_right1;Wait(nMax*step); //進行方向修正 cross_line; //交差点を渡る nOnline=0; //カウンタをリセット } }
ここではカウンタを利用し、交差点の判断をさせる。
以上からメインルーチンは以下のようになる。
task main() { SetSensor(SENSOR_2, SENSOR_LIGHT); ClearTimer(0); while(FastTimer(0) <= Qmade) { line_traceN(); //Qまで通常のトレース } PlaySound(SOUND_UP); while (FastTimer(0) <= Pmade) { line_traceK(); //QからPまで交差点のトレース } PlaySound(SOUND_UP); while (FastTimer(0) <= Pkara) { line_traceN(); //Pを通過するとき通常のトレース } PlaySound(SOUND_UP); utsu; }
タイマーでトレース方法の切り替えを行う。Pmade、Qmadeとは地図の地点P,Qのことで二つの地点までのおよその時間である。交差点の判断はカウンタとタイマーを併用することで精度を上げるようにしたが、ロボットの走った様子から考えると最終的にタイマーが交差点判断の主な方法になった。 この時間が少し違うだけでロボが誤って旋回してしまったりと思い通りにいかなかった。微調整するのに時間がかかった。
トレース方法が実際に変わっているのか分かりにくかったので、トレース方法が変更する際には音が鳴るように改善した。
今回、自分にとって最も困難だったのはプログラムを理解することである。課題1の時に比べて複雑でどう利用すればいいのかわからない時が多々あった。特に理解できなかったのがカウンタとタイマー。利用すべきところはわかるのだが、プログラムにどう入れればいいか分からず苦労した。チームのメンバーに助けてもらいながら少しは理解に至ったと思う。けれども、自分一人でタイマーなどを使ってプログラムを書くというのはまだ厳しいので、場数を踏んで書けるようにしたい。
ロボットを作るにあたっては、チーム内でアイデアを出しながら試行錯誤し完成に至れた。私もアイデアを提案でき、少しはチームに貢献できたかなと思う。グループワークであるので、次の課題でもチームのために役立てることはしていきたい。