周回コース(黒い線)を動くロボットを作成する。
黒をたどるプログラムを使用しロボットを作る。
後ろにタイヤを付けたら、曲がるとき、必ず元の位置から外れてしまう。そのため、センサーを曲がる動作の中心にするため、キャタピラを使用した。
光センサーを左右に並べたら、線を非常に太くする以外に、黒をたどるプログラムが使用出来なかった。そのため、上の写真のように互いの裏を合わせた。
今回は、ロボットを小さく作るために努力した。結局キャタピラを付けたので、多少大きくなってしまったのは仕方がないことだが、このデザインは誇りだ。
#define THRESHOLD1 40 #define THRESHOLD3 50 int move_time ; // 変数(move_time)を定義 sub std_move() //基準の動き { OnFwd(OUT_A+OUT_C) ; ClearTimer(0); // Timer(0) をリセット while ( Timer(0) <= move_time ) { if (SENSOR_3 > THRESHOLD3) //右センサーが白のとき黒まで右に旋回 { OnFwd(OUT_C); until(SENSOR_3 < THRESHOLD3); OnFwd(OUT_A); } else if (SENSOR_1 > THRESHOLD1) //左センサーが白のとき黒まで左に旋回 { OnRev(OUT_C); until(SENSOR_1 < THRESHOLD1); OnFwd(OUT_C); } } } sub right_pref() //右優先 { OnFwd(OUT_A+OUT_C) ; ClearTimer(0); // Timer(0) をリセット while ( Timer(0) <= move_time ) { if (SENSOR_3 < THRESHOLD3) { //右センサーが黒のとき右に旋回 OnFwd(OUT_A); } else { //右センサーが白のとき左に旋回 OnFwd(OUT_C); } } } sub left_pref() //左優先 { OnFwd(OUT_A+OUT_C) ; ClearTimer(0); // Timer(0) をリセット while ( Timer(0) <= move_time ) { if (SENSOR_1 < THRESHOLD1) { //左センサーが黒のとき左に旋回 OnFwd(OUT_C); } else { //左センサーが白のとき右に旋回 OnFwd(OUT_C); OnRev(OUT_A); } } } void rotary() //ロータリーの動き { OnFwd(OUT_A+OUT_C); until((SENSOR_1 > THRESHOLD1) && (SENSOR_3 > THRESHOLD3)); //白まで進む OnFwd(OUT_A); OnRev(OUT_C); until(SENSOR_1 < THRESHOLD1); //左センサーが黒まで右に旋回 move_time = 40 ; // (move_time)に「40」を代入 ClearTimer(0); // Timer(0) をリセット while(Timer(0) <= move_time ) { left_pref(); } //左優先 OnFwd(OUT_C); OnRev(OUT_A); until(SENSOR_3 > THRESHOLD3); //右センサーが白まで右に旋回 OnFwd(OUT_A); OnRev(OUT_C); until(SENSOR_3 < THRESHOLD3); //右センサーが黒まで左に旋回 } task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensor(SENSOR_3,SENSOR_LIGHT); SetPower(OUT_A+OUT_C,4); OnFwd(OUT_A+OUT_C); until((SENSOR_1 < THRESHOLD1) && (SENSOR_3 < THRESHOLD3)); //黒まで進む move_time = 140 ; // (move_time)に「140」を代入 ClearTimer(0); while(Timer(0) < move_time ) { std_move(); //基準の動き } rotary(); //ロータリー直進 move_time = 50 ; // (move_time)に「50」を代入 ClearTimer(0); // Timer(0) をリセット while(Timer(0) <= move_time ) { right_pref(); } //右優先 move_time = 30 ; // (move_time)に「30」を代入 ClearTimer(0); // Timer(0) をリセット while(Timer(0) <= move_time ) { left_pref(); } //左優先 move_time = 20 ; // (move_time)に「20」を代入 ClearTimer(0); // Timer(0) をリセット while(Timer(0) <= move_time ) { right_pref(); } //右優先 OnFwd(OUT_A); OnRev(OUT_C); until((SENSOR_1 < THRESHOLD1) && (SENSOR_3 < THRESHOLD3)); //黒まで左に旋回 move_time = 50 ; // (move_time)に「50」を代入 ClearTimer(0); while(Timer(0) < move_time ) { std_move(); //基準の動き } rotary(); //ロータリー直進 move_time = 20 ; // (move_time)に「20」を代入 ClearTimer(0); // Timer(0) をリセット while(Timer(0) <= move_time ) { right_pref(); } //右優先 OnFwd(OUT_A); OnRev(OUT_C); until((SENSOR_1 < THRESHOLD1) && (SENSOR_3 < THRESHOLD3)); //黒まで左に旋回 move_time = 150 ; // (move_time)に「150」を代入 ClearTimer(0); while(Timer(0) < move_time ) { std_move(); //基準の動き } Off(OUT_A+OUT_C); }
//一つ一つの光センサーの敷居の値 #define THRESHOLD1 40 #define THRESHOLD3 50 //コースをうまくたどるための時間 #define FIRST_LEG 45 #define SECOND_LEG 55 #define RUN_TIME1 40 #define RUN_TIME2 35 #define RUN_TIME3 13 //長く曲がることを数えるための値 int long_turn = 0; int turn_time1 = 0; int turn_time2 = 0; int turn_time3 = 0; int turn_time_total = 0; //音楽用の値 #define a 440 #define A 880 #define b 466 #define B 932 #define c 262 #define C 523 #define d 294 #define D 587 #define e 330 #define E 659 #define f 349 #define F 698 #define g 392 #define G 784 //コースをうまくたどったら、最後の成功のテーマを流す sub ffwin() { PlayTone(A,15); Wait(25); PlayTone(A,15); Wait(25); PlayTone(A,15); Wait(25); PlayTone(A,30); Wait(40); PlayTone(f,30); Wait(40); PlayTone(G,30); Wait(40); PlayTone(A,15); Wait(30); PlayTone(G,15); Wait(25); PlayTone(A,30); Wait(30); } //コースをたどりながら、BGMを流す task shiptheme() { while(true) { PlayTone(C,60); Wait(70); PlayTone(D,30); Wait(40); PlayTone(E,30); Wait(40); PlayTone(1000,60); Wait(70); PlayTone(A,60); Wait(70); PlayTone(C,30); Wait(40); PlayTone(D,30); Wait(40); PlayTone(E,30); Wait(40); PlayTone(G,30); Wait(40); PlayTone(F,30); Wait(40); PlayTone(C,30); Wait(40); PlayTone(D,30); Wait(40); } } //基準の動き方 sub std_move() { OnFwd(OUT_A+OUT_C); ClearTimer(1); //曲がる時間を計るため if (SENSOR_3 > THRESHOLD3) //右のセンサーが白を見たら、左に曲がる { OnRev(OUT_A); until(SENSOR_3 < THRESHOLD3); OnFwd(OUT_A); } else if (SENSOR_1 > THRESHOLD1) //左のセンサーが白を見たら、右に曲がる { OnRev(OUT_C); until(SENSOR_1 < THRESHOLD1); OnFwd(OUT_C); } if(Timer(1) > 5) //曲がる時間が十分長かったら、長く曲がるカウントに1を足す { long_turn++; } } //右の光センサーを使い、線の右側をたどる、右を優先する関数 sub right_pref() { OnFwd(OUT_A+OUT_C); ClearTimer(1); //前回と前々回の曲がる時間を保存する turn_time3 = turn_time2; turn_time2 = turn_time1; if(SENSOR_3 > THRESHOLD3) //センサーが白を見たら、黒まで曲がる { OnRev(OUT_A); until(SENSOR_3 < THRESHOLD3); OnFwd(OUT_A); Wait(1); turn_time1 = -Timer(1); //左に曲がったら、値をマイナスにする } else //センサーが黒を見たら、白まで曲がる { OnRev(OUT_C); until(SENSOR_3 > THRESHOLD3); OnFwd(OUT_C); Wait(1); turn_time1 = Timer(1); //右に曲がったら、値をプラスにする } turn_time_total = turn_time1 + turn_time2 + turn_time3; //今回+前回+前々回を合計するとどんな風に曲がっているかわかる if(turn_time_total > 6) //曲がる時間が十分長かったら、長く曲がるカウントに1を足す { long_turn++; turn_time_total = 0; turn_time1 = 0; turn_time2 = 0; } } //左の光センサーを使い、線の左側をたどる、左を優先する関数 sub left_pref() { OnFwd(OUT_A+OUT_C); ClearTimer(1); //前回と前々回の曲がる時間を保存する turn_time3 = turn_time2; turn_time2 = turn_time1; if(SENSOR_1 > THRESHOLD1) //センサーが白を見たら、黒まで曲がる { OnRev(OUT_C); until(SENSOR_1 < THRESHOLD1); OnFwd(OUT_C); Wait(1); turn_time1 = -Timer(1); //右に曲がったら、値をマイナスにする } else //センサーが黒を見たら、白まで曲がる { OnRev(OUT_A); until(SENSOR_1 > THRESHOLD1); OnFwd(OUT_A); Wait(1); turn_time1 = Timer(1); //左に曲がったら、値をプラスにする } turn_time_total = turn_time1 + turn_time2 + turn_time3; //今回+前回+前々回を合計するとどんな風に曲がっているかわかる if(turn_time_total > 6) //曲がる時間が十分長かったら、長く曲がるカウントに1を足す { long_turn++; turn_time_total = 0; turn_time1 = 0; turn_time2 = 0; } } task main() { SetSensor(SENSOR_1,SENSOR_LIGHT); SetSensor(SENSOR_3,SENSOR_LIGHT); SetPower(OUT_A+OUT_C,4); //電池は強すぎたから、パワーを減らさないとすぐコースからずれてしまう start shiptheme; //BGMを流す //だいたい同じスタートから始めるため、両方の光センサーが黒を見るまで進む。 OnFwd(OUT_A+OUT_C); until((SENSOR_1 < THRESHOLD1) && (SENSOR_3 < THRESHOLD3)); ClearTimer(0); while(Timer(0)< FIRST_LEG) { //std_moveで測った長く曲がるカウントを使い、コースの初めの部分を通るまで進む if(long_turn < 3) { ClearTimer(0); } std_move(); } //ロータリーまで続く OnFwd(OUT_A+OUT_C); until((SENSOR_1 > THRESHOLD1) && (SENSOR_3 > THRESHOLD3)); //左優先の関数がうまくいくために地位を変える OnRev(OUT_C); until(SENSOR_1 < THRESHOLD1); ClearTimer(0); // Timer(0) をリセット //ロータリの一番目の交差点を通るまでロータリーの内側をたどる while(Timer(0) <= RUN_TIME1) { left_pref(); } //右優先の関数がうまくいくために地位を変える OnRev(OUT_A); until(SENSOR_3 < THRESHOLD3); ClearTimer(0); // Timer(0) をリセットする long_turn = 0; //長く曲がることのカウントをリセットする //右優先を使い、ロータリーの次の交差点を曲がる while(Timer(0) <= RUN_TIME2) { if(long_turn == 0) { ClearTimer(0); } right_pref(); } //近道を飛ばす OnRev(OUT_C); OnFwd(OUT_A); Wait(120); OnFwd(OUT_A+OUT_C); until((SENSOR_1 < THRESHOLD1) || (SENSOR_3 < THRESHOLD3)); OnRev(OUT_C); Wait(70); OnFwd(OUT_A+OUT_C); until((SENSOR_1 < THRESHOLD1) && (SENSOR_3 < THRESHOLD3)); OnFwd(OUT_A+OUT_C); until(SENSOR_1 > THRESHOLD1); OnRev(OUT_C); until((SENSOR_1 < THRESHOLD1) && (SENSOR_3 < THRESHOLD3)); ClearTimer(0); //ロータリーに戻る while(Timer(0) < RUN_TIME3) { std_move(); } //ロータリーまで続く OnFwd(OUT_A+OUT_C); until((SENSOR_1 > THRESHOLD1) && (SENSOR_3 > THRESHOLD3)); //左優先の関数がうまくいくために地位を変える OnRev(OUT_C); until(SENSOR_1 < THRESHOLD1); ClearTimer(0); // Timer(0) をリセット //ロータリの一番目の交差点を通るまでロータリーの内側をたどる while(Timer(0) <= RUN_TIME1) { left_pref(); } OnRev(OUT_A);Wait(10); //右優先の関数がうまくいくために地位を変える OnFwd(OUT_A); until(SENSOR_3 < THRESHOLD3); ClearTimer(0); // Timer(0) をリセット //右優先を使い、ロータリーの次の交差点を曲がる while(Timer(0) <= RUN_TIME1) { right_pref(); } //基準の動き方の関数がうまくいくために地位を変える OnRev(OUT_A); until((SENSOR_1 < THRESHOLD1) && (SENSOR_3 < THRESHOLD3)); long_turn = 0; //長く曲がることのカウントをリセットする //コースの最後まで続く while(long_turn == 0) { std_move(); } stop shiptheme; //BGMを止める Off(OUT_A+OUT_C); //ロボットを止める ffwin(); //成功! }
今回の課題も、多くの時間をかけて作業を行ったが、非常に難しく大変だった。
今回こそ、デザインには満足し、コードには満足し、実際にはちょっとがっかりした。