[[2016a/Member]] *目次 [#we314833] #contents *課題3 [#z07f8dc2] 課題2で使用したコースを用いてC地点とD地点に最大3つずつおいてある紙コップをC地点側から交互にQ地点に積み上げてその数や正確さ速さなどを他の班と競う *ロボット本体の説明 [#z4ce7b36] **ロボット本体 [#x9773074] 私たちの班は2つのロボット(1つは紙コップを積み上げるロボット。もう1つは紙コップを集めてくるロボット。)を最初に作っていたのですが、通信をする際にちゃんと向き合っていないとうまく通信できないことがわかり、ライントレースをしているとたとえば時間で止めたときに真っ直ぐ向き合う確率はとても低かったので、1つのロボットに変更しました。1つのロボットにモーターと光センサーを2つずつ使いました。 #ref(2016a/Member/Junnko/Mission3/IMG_7671[1].JPG,10%,ロボットを正面から見た写真) ロボットを正面から見た写真 積み上げた紙コップをルールに従い、ロボットに接していない状態でQ地点に置くために、紙コップが抜けられるように片側を空いた状態にしました。 #ref(2016a/Member/Junnko/Mission3/IMG_7669[1].JPG,10%,ロボットを横から見た写真) ロボットを真横から見た写真 **光センサーの位置 [#w4cdee7d] ***ライントレース用 [#j5098b3d] 紙コップを本体と持ち上げるためのアームとの間に入れるために、ライントレース用の光センサーを本体の外ではなく、内部につけました。 #ref(2016a/Member/Junnko/Mission3/IMG_7667[1].JPG,10%,ロボットを裏から見た写真) ロボットを裏から見た写真 ***紙コップの判断用 [#q9201449] もう一つの光センサーは紙コップをつかんだ(正確に言えば挟んだ)かどうかを判断するために使いました。下の写真のように、紙コップがあるときの光センサーの色判別の値を設定して、その値の間にあるとき紙コップをつかんでいるアームを持ち上げるという仕組みにしました。 #ref(2016a/Member/Junnko/Mission3/IMG_7663[1].JPG,10%,光センサーの写真) **アーム [#u4ece583] アームを動かす仕組みは、1つのモーターを重心の関係でロボットが倒れないようにするために、本体のやや中心に置き、先端のアームを動かすために歯車をいくつもつなげて調節しました。 #ref(2016a/Member/Junnko/Mission3/IMG_7666[1].JPG,10%,ロボットのアームの部分の写真) ロボットのアーム部分 最終的に下の写真のように積み上げていく感じになります。 #ref(2016a/Member/Junnko/Mission3/IMG_7661[1].JPG,10%,ロボットの写真) *プログラムの説明 [#iea09090] **光センサーの値 [#s0067cc5] ・白部分・・・・53〜 ・弱白部分・・・52〜53 ・境界部分・・・44〜52 ・弱黒部分・・・41〜44 ・黒部分・・・・〜41 **タイマーについて [#w6c353e9] ***Fasttimer(1) [#y6b09909] 光センサーが黒部分の判定をしている時にカウントをして、0.4秒以上続いたら交差点として判別する。また、黒部分以外の時はClearTimer(0)でFastTimer(0)を初期化する。 ***Fasttaimer(2) [#kc2ea43a] 小さなカーブを交差点として誤判別しないために指定秒数間交差点判別を行わないようにする。ここで、指定秒数を変数としてl_timeをグローバル変数として定義する。また、ライントレース開始時にClearTimer(1)でFastTimer(1)を初期化する。 **時間の定義 [#lff95a51] #define CROSS_TIME 40 #define BALANCE_TIME 40 **基本動作や決まっている動作の定義 [#h6aa94be] #define roll_left OnRev(OUT_A); OnFwd(OUT_C); //左回転 #define turn_left OnFwd(OUT_C); Off(OUT_A); //左旋回 #define go OnFwd(OUT_A); OnFwd(OUT_C); //前進 #define turn_right OnFwd(OUT_A); Off(OUT_C); //右旋回 #define roll_right OnFwd(OUT_A); OnRev(OUT_C); //右回転 #define back OnRev(OUT_A); OnRev(OUT_C); Wait(100); Off(OUT_AC); //後進 #define top OnRev(OUT_C); OnFwd(OUT_A); Wait(CROSS_TIME); OnFwd(OUT_AC); Wait(10); //交差点直進 #define left OnRev(OUT_A); OnFwd(OUT_C); Wait(20); //交差点左折 #define right OnRev(OUT_C); OnFwd(OUT_A); Wait(80); OnFwd(OUT_AC); Wait(20); //交差点右折 **左側をラインとレースするプログラム [#fd949803] sub line_l(){ int ch=0; //ループ脱出用変数 ClearTimer(0); //交差点判別用のタイマー初期化 ClearTimer(1); //交差点誤判別防止用のタイマー初期化 while(ch==0) //chが0の時はループを続ける { if(SENSOR_2 > 53) //白部分 右回転 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 roll_right; } else if(SENSOR_2 > 52) //弱白部分 右旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 turn_right; } else if(SENSOR_2 > 44) //境界部分 直進 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 go; } else if(SENSOR_2 > 41) //弱黒部分 左旋回 { ClearTimer(0); //黒部分ではないので交差点判別用のタイマーを初期化 turn_left; } else{ //黒部分 左回転 roll_left; } if(FastTimer(0)>CROSS_TIME&&FastTimer(1)>l_time){ //交差点判別 Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする } Wait(1); //0.01秒待つ } } **姿勢制御の方法 [#t4e6e6d5] 境界部分を判定して、ロボットが線に対して真っ直ぐ向くようにするものである。 真っ直ぐ向くまでライントレースを繰り返すようになっている。ただし、ライントレースできる範囲が決まっているので、一定時間内に真っ直ぐになれなかったら、一度後退してまた再びライントレースするようになっている。 ***左境界部分での姿勢制御 [#k2866517] sub balance_l(){ int ch=0; //ループ脱出用変数 ClearTimer(0); //姿勢判別用のタイマー初期化 while(ch==0) //chが0の時はループを続ける { ClearTimer(1); //ライントレース時間判別用のタイマー初期化 while(FastTimer(1)<200&&ch==0) //FastTimer(1)が2秒未満かつchが0の時はループを続ける { if(SENSOR_2 > 53) //白部分 右回転 { ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化 roll_right; } else if(SENSOR_2 > 52) //弱白部分 右旋回 { ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化 turn_right; } else if(SENSOR_2 > 44) //境界部分 直進 { go; } else if(SENSOR_2 > 41) //弱黒部分 左旋回 { ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化 turn_left; } else{ //黒部分 左回転 ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化 roll_left; } if(FastTimer(0)>BALANCE_TIME) //姿勢判別 { Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする } Wait(1); //0.01秒待つ } if(ch==0) { back; //約2秒分の後退 back; } } } ***右境界部分での姿勢制御 [#z2955700] sub balance_r(){ int ch=0; //ループ脱出用変数 ClearTimer(0); //姿勢判別用のタイマー初期化 while(ch==0) //chが0の時はループを続ける { ClearTimer(1); //ライントレース時間判別用のタイマー初期化 while(FastTimer(1)<200&&ch==0)//FastTimer(1)が2秒未満かつchが0の時はループを続ける { if(SENSOR_2 > 53) //白部分 左回転 { ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化 roll_left; } else if(SENSOR_2 > 52) //弱白部分 左旋回 { ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化 turn_left; } else if(SENSOR_2 > 44) //境界部分 直進 { go; } else if(SENSOR_2 > 41) //弱黒部分 右旋回 { ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化 turn_right; } else{ //黒部分 右回転 ClearTimer(0); //境界部分ではないので姿勢判別用のタイマーを初期化 roll_right; } if(FastTimer(0)>BALANCE_TIME) //姿勢判別 { Off(OUT_AC); //車輪を止める PlaySound(SOUND_UP); //音を鳴らす Wait(100); //1秒待つ ch=1; //ループ脱出の為にchを1にする } Wait(1); //0.01秒待つ } if(ch==0) { back; //約2秒分の後退 back; } } } **紙コップを積み上げる [#g4b1b4d8] sub cup(){ OnRev(OUT_B); //アームを下す Wait(50); Off(OUT_B); OnFwd(OUT_AC); //前進 while(SENSOR_1<42); //光センサーが紙コップを認識するまで前進する Off(OUT_AC); //停止 OnFwd(OUT_B); //アームを上げる Wait(50); Off(OUT_B); } **C地点、D地点への方向転換 [#h6c7933d] sub turn(){ OnFwd(OUT_C); //左回転 OnRev(OUT_A); Wait(100); //黒部分から白部分に出るための時間(D地点からC地点への移動時に特に必要) while(SENSOR_2>41); //白部分である場合は回転し続ける Off(OUT_AC); //停止 } **紙コップを置く [#j30b4cb6] Q地点までライントレースをしてたどり着いたら、次のように積み上げた紙コップを置く Q地点の交差点判別のあと、機体の姿勢を戻さずにそのまま前進する。その後、アームを紙コップから外す。その場で右回転させて、紙コップをロボットの外に出す。紙コップがロボット本体に触れないようにするために、後進する。 sub last(){ OnFwd(OUT_AC); //前進 Wait(50); //約0.5秒待つ Off(OUT_AC); OnRev(OUT_B); //アームを下す Wait(50); //約0.5秒待つ Off(OUT_B); OnFwd(OUT_A); //右回転 OnRev(OUT_C); Wait(100); //約1秒待つ back; //約2秒間後進する(1秒ではアームが紙コップに触れている時があるため) back; } **メイン [#ed566a9b] task main () { SetSensor(SENSOR_1, SENSOR_LIGHT); //光センサー1の初期設定(紙コップ認識用) SetSensor(SENSOR_2, SENSOR_LIGHT); //光センサー2の初期設定(ライントレース用) OnFwd(OUT_AC); //スタート地点の枠から脱出 Wait(60); //C地点までの移動 line_l(); //左側境界部分をトレース left; //P地点を左折 l_time=400; //次の交差点までの秒数を4秒に設定 line_l(); //左側境界部分をトレース right; //S地点を右折 balance_l(); //左境界部分での姿勢制御 //紙コップ回収作業 cup(); //1つ目の紙コップ取得 back; //後進 //D地点までの移動 turn(); //左回転 balance_r(); //右境界部分での姿勢制御 //紙コップ回収作業 cup(); //2つ目の紙コップ取得 back; //後進 //C地点までの移動 turn(); //左回転 OnFwd(OUT_AC); //前進 Wait(20); balance_r(); //右境界部分での姿勢制御 //紙コップ回収作業 cup(); //3つ目の紙コップ取得 back; //後進 //D地点までの移動 turn(); //左回転 OnFwd(OUT_AC); //前進 Wait(20); balance_r(); //右境界部分での姿勢制御 //紙コップ回収作業 cup(); //4つ目の紙コップ取得 back; //約4秒間後進 back; back; back; l_time=200; //次の交差点までの秒数を2秒に設定 //左境界部分へ移動 OnFwd(OUT_C); //左回転 OnRev(OUT_A); Wait(50); OnFwd(OUT_AC); //前進 Wait(30); //Q地点までの移動 line_l(); //左側境界部分をトレース left; //S地点を左折 line_l(); //左側境界部分をトレース left; //P地点を左折 line_l(); //左側境界部分をトレース //紙コップの設置 last(); } *課題3の結果 [#u65c3bdb] **基本点 [#qd7c8009] ***1回目<0点 [#u1724ed1] 紙コップ判断用のセンサーが断線しかかっていたのが原因 ***2回目<30点 [#yd9f3c1d] ***1回目→0点 [#u1724ed1] 紙コップ判断用のセンサーが断線しかかっていたのが原因だと考えられる ***2回目→30点 [#yd9f3c1d] 最初は6個積み上げようと思っていたがうまくいかず、進路変更で確実に積み上げられる4個までにしたのがうまくいき、しっかりコップ4個積み上げた分の得点が獲得できた。 **技術点→5.2点 [#e6a2dcb0] 1回目が光センサーの関係でうまくいかなかったし、他のグループよりもロボット本体の形が小さくシンプルすぎたので技術点が低めになってしまった。 *感想 [#fd1d2e0e] 今回は最初のロボットの形を作るところから苦戦しました。どうやって紙コップを持ち上げるかをみんなで考えました。プログラミングの方は、最初は通信することを考えてやっていてうまくいかないのでとても大変で、最終的には1台でする方法にみんな合意の上で変更しました。 みんなと話し合いながらいろんな意見をまとめたりするのが大変で、また逆に全然意見が出てこないこともあって大変でした。 テスト週間とかぶっていたこともあってみんなと時間を合わせるのは大変だったけど、みんな積極的に集まってくれたので、班員には感謝しています。 いろんな良いことがあって、みんなの知恵があったから今回の課題3は優勝できたんだなと思いました。 プログラミングは難しかったけれど、とても有意義な時間でした。ありがとうございました。