A地点から出発 → M → K(直進) → L(ピンポン玉をつかむ) → K(右折) → J(一時停止の後、左折) → I(直進) → H(直進) → G(左折) → F → E → D(一時停止の後、直進) → C(直進) → B(一時停止) → シュート→ A地点に入る(ゴール)
交差点では1秒間停止し、丁字路では直角方向に進入する時のみ一時停止すること。
↑全体のバランスを保つため,できるだけ部品を少なく,軽くした.一つのモーターで二つのアームが開閉するように作った.
↑急カーブでも小回りがきくように横幅を小さくした.後ろ側のタイヤは摩擦を減らすためだけなので一つだけつけるようにした.
光センサーの値が36から47の間で得られたので、これを5分割して、
47〜…白
43〜47…白灰
39〜43…灰
36〜39…黒灰
〜36…黒
とした。
黒色を判別している時間をblack_timeとして定義して,交差点の大きさや曲がり角の角度によって時間を変えた.何度も試した結果,Kなどの直角で270度の交差点で止まりたいときは30,つまり0,3秒に設定し,IやHの交差点のような,直角より曲がる角度が少し小さい交差点は光センサーが黒色を判別している時間が短いので20,つまり0,2秒に設定した.
プログラムを簡略化するため、defineを用いた。
int black_time=30; //黒色を判別している時間の設定 #define migisenkai OnFwd(OUT_A); OnFwd(OUT_C); //右に旋回 #define usetsu OnFwd(OUT_A); Off(OUT_C); //右折 #define chokushin OnFwd(OUT_A); OnRev(OUT_C); //直進 #define sasetsu Off(OUT_A); OnRev(OUT_C); //左折 #define hidarisenkai OnRev(OUT_A); OnRev(OUT_C); //左に旋回 #define koutai OnRev(OUT_A); OnFwd(OUT_C); //後退 #define close OnFwd(OUT_B); Wait(20); Off(OUT_B); Wait(100); //アームを閉じる(ボールを掴む) #define open OnRev(OUT_B); Wait(20); Off(OUT_B); Wait(100); //アームを開く
sub follow_line() { SetSensor(SENSOR_2,SENSOR_LIGHT); while(FastTimer(0)<black_time){ //black_timeが30より小さい間繰り返す if(SENSOR_2>=47){ //白色の時 migisenkai ClearTimer(0); //右に旋回、タイマー0をセット }else if((SENSOR_2>=43)&&(SENSOR_2<47)){ //白灰色の時 usetsu ClearTimer(0); //右折、タイマー0をセット }else if((SENSOR_2>=39)&&(SENSOR_2<43)){ //灰色の時 chokushin ClearTimer(0); //直進、タイマー0をセット }else if((SENSOR_2>=36)&&(SENSOR_2<39)){ /黒灰色の時 sasetsu ClearTimer(0); //左折、タイマー0をセット }else if(SENSOR_2<36){ //黒色の時 hidarisenkai } //左に旋回 } Off(OUT_AC); Wait(100); ClearTimer(0); }
sub follow_line2() { SetSensor(SENSOR_2,SENSOR_LIGHT); while(FastTimer(0)<black_time){ //black_timeが30より小さい間繰り返す if(SENSOR_2<36){ //黒色の時 migisenkai //右に旋回 }else if((SENSOR_2>=36)&&(SENSOR_2<39)){ //黒灰色の時 usetsu ClearTimer(0); //右折,タイマー0をセット }else if((SENSOR_2>=39)&&(SENSOR_2<43)){ //灰色の時 chokushin ClearTimer(0); //直進,タイマー0をセット }else if((SENSOR_2>=43)&&(SENSOR_2<47)){ //白灰色の時 sasetsu ClearTimer(0); //左折,タイマー0をセット }else if(SENSOR_2>=47){ //白色の時 hidarisenkai ClearTimer(0); //左に旋回,タイマー0をセット } } Off(OUT_AC); Wait(100); ClearTimer(0); }
sub cross_line() { SetSensor(SENSOR_2,SENSOR_LIGHT); while(SENSOR_2<47){ //白色になるまでの間 chokushin } //直進 while(SENSOR_2>36){ //黒色の間 usetu } //右折 Off(OUT_AC); Wait(100); ClearTimer(0); }
task main(){ SetPower(OUT_B,1);
アームの開閉はモーターを少し動かすだけでいいので,モーターの出力を下げた.
cross_line(); follow_line(); //MからK
最初,follow_lineが作動されなかったので前にcross_lineを書いてみると作動した.
cross_line(); //Kの交差点を渡る OnRev(OUT_C); Wait(60); Off(OUT_C); Wait(100); //ピンポン玉の正面への移動 close; //ピンポン玉をつかむ koutai Wait(150); Off(OUT_AC); Wait(100); //Kの,Lと反対の位置まで後退 cross_line(); follow_line(); //Kまで
最初と同じ理由でcross_lineを書いた.
follow_line(); //KからJまで black_time=20;follow_line(); //JからIまで cross_line(); //Iの交差点を渡る black_time=20;follow_line(); //IからHまで
直角ではないI,Hの交差点で止まるためにblack_timeを小さくした.
cross_line(); //Hの交差点を渡る follow_line(); //HからGまで chokushin Wait(40); Off(OUT_AC); Wait(100);
ここからはラインの右側をトレースしたかったので線GFの右側に出るまで直進した.
follow_line2(); follow_line2(); //線GFからDまで
この部分も最初と同じくfollow_line2ひとつだと動作しなかったので二つ書いてみるとちゃんとライントレースをした.
cross_line(); //Dの交差点を渡る follow_line(); //DからBまで open; //アームを開く hidarisenkai Wait(40); Off(OUT_AC); //ピンポン玉を出す }
アームを開いた状態で左に旋回することでピンポン玉をゴールにシュートした.
メインプログラムの中でなぜかfollow_lineが動作しないことが三か所あった.二回繰り返し書くことなどでちゃんとライントレースしたが,最後まで理由が分からなかった. defineやサブルーチンを用いて簡潔なプログラムを書けたと思う.また,Gからはラインの右側をトレースしたほうが楽だと思い,ライントレースのサブルーチンを左右それぞれについて書いた事でプログラムの後半がとても楽にできたと思う.