[[2019a/Member]] 目次 #contents *課題2 [#ja858b37] A地点を出発し、次のいずれかの経路を黒い線にそって動くロボットを作成する &br; (他のメンバーとは別の経路になるようにする)。 ・A地点から出発 → B → C(直進) → D(一時停止の後、直進) → E → F → G(一時停止の後、右折) → H → I&br; → J(右折) → K(左折) → L(ピンポン玉をつかむ) → K(直進) → M(一時停止) → シュート→ A地点に入る(ゴール) &br; ・A地点から出発 → M → K(直進) → L(ピンポン玉をつかむ) → K(右折) → J(一時停止の後、左折) → I(直進) &br; → H(直進) → G(左折) → F → E → D(一時停止の後、直進) → C(直進) → B(一時停止) → シュート→ A地点に入る(ゴール) 交差点では1秒間停止し、丁字路では直角方向に進入する時のみ一時停止すること。 **選んだコース [#y421ea0d] 私は下のコースをやりました。 *ロボットの説明 [#of46aaab] **構造について [#ud45fb8e] -全体図 ***全体図 [#q4da8e04] #ref(./P_20190715_201218 - コピー.jpg,54.1,全図) できるだけ小さくすることが出来ました。しかし、はじめは小さくしすぎたため、&br; バッテリーの重みに耐えることが出来ませんでした。だから、補強して強くすることにより、&br; 耐えることが出来るようになりました。 -アーム部分 ***アーム部分 [#uf404ac6] #ref(./P_20190715_202505_LL.jpg,66.4,アーム) モーターとアーム部分はゴムによってつながっています。簡単な構造に&br; 出来たため重量も小さく済みました。アーム部分と本体はバッテリーのところでつながっています。&br; そのため、取れやすいですが、ミッションに支障は来さなかったので良かったです。 -車体 ***車体 [#l262ec25] #ref(./P_20190715_210355_NT.jpg,68.6,車体) モーターを直列につなげることにより車体を小さくすることが出来ました。しかし、&br; 前輪が弱かったため写真のように2✕1のパーツをつけて、モーターの高さに近づけて&br; 外れにくいようにすることが出来ました。 -ボールをつかむ ***ボールをつかむ [#c77bfa4b] #ref(./P_20190718_134818.jpg,53.9,ボール) ボールを掴んでいるときの写真です。ボールを掴むことに支障を来すことがないように&br; 本体とアーム部分の距離を何度か試してから決めました。 *制御について [#r8389748] **#defineについて [#i7c9ac39] #define go OnFwd(OUT_AC); #define turn_left OnRev(OUT_A);OnFwd(OUT_C); #define turn_right OnFwd(OUT_A);OnRev(OUT_C); #define right OnFwd(OUT_A);Off(OUT_C); #define left OnFwd(OUT_C);Off(OUT_A); これらのプログラムは移動に関するものです。&br; 上から、直進、左旋回、右旋回、右、左というものです。&br; また、turn_left,turn_right は、left,right よりも大きく曲がるプログラムです。 #define w_gray 51 #define gray 47 #define b_gray 45 #define black 41 これらのプログラムは色の値に関するものであり、&br; 実際に値を測って設定しました。 **交差点の判断方法 [#w60a64a9] 交差点と認識するためには、連続して黒、又は黒よりの灰色、と認識している時間が、&br; ある時間よりも大きくなることが必要です。&br; その時間の測り方は、黒、黒寄りの灰色が連続して感知されるとFastTimer(0)が増えます。&br; 下の sub follow_line()では、FastTimer(1)<tの条件下では、ClearTimer(0)というものが働き、&br; FastTimer(0)がリセットされます。FastTimer(1)>tで、光センサーが黒と認識したときには、&br; ClearTimer(0)が働かずに、FastTimer(0)が増えます。また、黒寄りの灰色のときも同じです。&br; 灰色よりも薄い色のときには、移動したあとにClearTimer(0)が働き&br; FastTimer(0)がリセットされます。上記のようにするときに、FastTimer(0)がある時間を&br; 超えると、交差点と認識します。&br; また、円形のときの交差点と直角の交差点とでは交差点と認識するために&br; 必要な時間が異なるため、時間を変える必要がありました。 **サブルーチンについて [#cc572bf5] ルーチンは、一連の命令をまとめたものを意味し、 一番最初に実行されるものをメインルーチン、 &br; そのメインルーチンから呼び出させるものをサブルーチンと呼びます。 sub follow_line() { while(FastTimer(0)<turn_t){ if ((SENSOR_1 < black)&&(FastTimer(1)<t)){ //センサー1が黒より濃く、 turn_left;ClearTimer(0); //タイマー1がtより小なら実行 } else if (SENSOR_1 < black){ //ClearTimer(0)によりタイマー0をリセット turn_left; } else if ((SENSOR_1 < b_gray)&&(FastTimer(1)<t)){ left;ClearTimer(0); } else if (SENSOR_1 < b_gray){ left; } else if (SENSOR_1 < gray){ go;ClearTimer(0); } else if (SENSOR_1 < w_gray){ right;ClearTimer(0); } else { turn_right;ClearTimer(0); } } sp;Wait(WT); } これは、線の左側をライントレースするために用いたサブルーチンです。 &br; ・センサー1が41よりも小さい値なら、左旋回。 &br; ↓ &br; ・センサー1が41以上45よりも小さい値なら、左。 &br; ↓ &br; ・センサー1が45以上47よりも小さい値なら、直進。 &br; ↓ &br; ・センサー1が47以上51よりも小さい値なら、右。 &br; ↓ &br; ・それ以外なら右旋回。 &br; ↓ また、&&(FastTimer(1)<t)を用いることにより、FastTimer(1)がtを超えるまでは&br; カーブを交差点と認識しないようにすることができました。&br; また、WTは一時停止をしなければならないところでは WT=100として、&br; 一時停止をする必要のないところでは WT=0としてから下の ST()を用いました。 &br; このサブルーチンは、最初はSENSOR1がblack以下のときにだけFastTimer(1)が&br; 増えるようにしていましたが、交差点と認識してほしいときに認識してくれないことが多かったため、&br; b_gray以下でもFastTimer(1)が増えるようにしました。そうしたら、交差点と認識しやすくなりました。 sub ST() { turn_right;Wait(turn_t);go;Wait(FT);sp; } これは、交差点と認識してから、交差点を直進したいときに使うプログラムです。 &br; 右に曲がり、直進するというものです。&br; ここでFTを用いたのは、回転の具合によって前に進む時間を変える必要があったからです。 sub follow_l_r() { while(FastTimer(0)<turn_t){ if ((SENSOR_1 < black)&&(FastTimer(1)<t)){ turn_right;ClearTimer(0); } else if (SENSOR_1 < black){ turn_right; } else if ((SENSOR_1 < b_gray)&&(FastTimer(1)<t)){ right;ClearTimer(0); } else if (SENSOR_1 < b_gray){ right; } else if (SENSOR_1 < gray){ go;ClearTimer(0); } else if (SENSOR_1 < w_gray){ left;ClearTimer(0);; } } sp;Wait(WT); } これは、線の右側をライントレースするために用いたプログラムです。 &br; ・センサー1が41よりも小さい値なら、右旋回。 &br; ↓ &br; ・センサー1が41以上45よりも小さい値なら、右。 &br; ↓ &br; ・センサー1が45以上47よりも小さい値なら、直進。 &br; ↓ &br; ・センサー1が47以上51よりも小さい値なら、左。 &br; ↓ &br; ・それ以外なら左旋回。 &br; ↓ このサブルーチンの目的は、FからDの区間を曲がり切ることです。それは、&br; FからDの区間を曲がり切ることができなかったからです。&br; それを改善するために、Gに着いたら線の右側に出て、その後は線の右側を走行できるようにしました。&br; これにより、FからDの区間を曲がり切ることができました。さらに、Dを超えてから交差点がなかったため、&br; 変数なども気にすることなく、プログラムを書くことができました。 sub curve() { while(FastTimer(0)<turn_t){ if ((SENSOR_1 < black)&&(FastTimer(1)<t)){ turn_left;ClearTimer(0); } else if (SENSOR_1 < black){ turn_left; } else if ((SENSOR_1 < b_gray)&&(FastTimer(1)<t)){ left;ClearTimer(0); } else if (SENSOR_1 < b_gray){ left; } else if ((SENSOR_1 < gray)&&(FastTimer(1)<t)){ go;ClearTimer(0); } else if (SENSOR_1 < gray){ go; } else if (SENSOR_1 < w_gray){ right;ClearTimer(0); } else { turn_right;ClearTimer(0); } } turn_right;Wait(turn_t-10);go;Wait(FT);sp; } これは、JからGのカーブを曲がるために作りました。&br; 動き方は、sub follow_line() と同じです。 この区間では交差点の認識がうまく出なかったためfollow_line()よりも&br; 交差点と認識しやすいように、SENSOR1がgrayよりも小さい値である時間が長ければ交差点と認識するように設定しました。&br; これにより、うまく回ることが出来るようになりました。 sub ball_c() { while(FastTimer(1)<t){ if (SENSOR_1 < black){ turn_right; } else if (SENSOR_1 < b_gray){ right; } else if (SENSOR_1 < gray){ go; } else if (SENSOR_1 < w_gray){ left; } else { turn_left; } } repeat(3){ OnFwd(OUT_B);Wait(1);Off(OUT_B); go;Wait(50);sp; } } これは、ボールをつかむためのものです。 &br; 動き方はsub follow_l_r()と同じです。それから、ボールを掴むものです。&br; KからLの区間の秒数を測り、その時間をtとしました。&br; それによりKからLまでライントレースすることができ、ボールの&br; 位置に合わせやすくなりました。ここで繰り返しを使っているのは、モーターの動力を&br; ギアなどを使ってちょうどいい回転にすることができなかったため、&br; 連続してモーターを動かすと強く回りすぎてしまったため、少しずつ回るようにしました。 sub ball_l() { OnRev(OUT_B);Wait(10);sp; } モーターを逆に動かして、ボールを離すためのものです。 **task mainについて [#x8e06d98] -MからK ClearTimer(0); //黒、黒寄りの灰色と連続して認識した時間が0.24秒より長く、 ClearTimer(1); //発進から19秒間は交差点と認識しない turn_t=24;t=1900;WT=0; follow_line(); FT=25;ST(); これは、線の左側を走行してKで交差点と認識するというものです。&br; この区間では、turn_tがどれぐらいにだと丁度いいか、&br; ということを何度か試行してみて決めました。 -KからL ClearTimer(0); ClearTimer(1); t=250;ball_c(); これはボールに近づき、ボールをつかむというものです。&br; Kに到達したときに、Lの方に思っていたよりも進んでいたため、tの値を短めにしました。 -LからK ClearTimer(0); ClearTimer(1); turn_left;Wait(173);sp; go;Wait(240);sp; 何度か実際に試して、回る時間と直進する時間を決めました。 -KからJ t=0;WT=100;turn_t=20; //連続して黒、黒寄りの灰色を0.2秒認識したら follow_line(); //そこは交差点と認識 -JからG FT=10;WT=0;turn_t=30;t=70; repeat(3){ ClearTimer(0); ClearTimer(1); curve(); } ここでは、繰り返しを使うことにより何度も同じプログラムを書く必要を&br; 無くすことができました。 -FからD ClearTimer(0); ClearTimer(1); turn_t=33;WT=100;t=640;FT=20; follow_l_r(); これは、線の右側に出るようにしてから、線の右側を沿うようにしました。 -DからB ClearTimer(0); ClearTimer(1); turn_left;Wait(turn_t-10);sp; go;Wait(50);sp; follow_l_r(); turn_left;Wait(turn_t-10);sp; Dで一時停止してから直進し、そのままBまで沿って行くというものです。&br; そして、Bでゴールの方向を向くというプログラムです。 -BからA ball_l(); go;Wait(150);sp; ボールを離して、ゴールに押し込み、Aに入るというプログラムです。 *まとめ [#sfdbc67b] 出来たこと ・コース通り走行することの出来るロボットの作成 &br; ・プログラムの簡略化 &br; ・ボールを掴むこと 出来なかったこと ・FからDの区間を、線の左側を走行したまま通過すること 改善可能な点 ・カーブ、線を沿うプログラムを変数を駆使して一つにすることが出来るのではないかと思います。 &br; ・もっと簡単に、交差点と認識するためには、光センサーをより近づける必要があったのではないかとおもいました。