目次 #contents * 課題 [#gedde2d3] #ref(./course.jpg,50%,コース) ~今回私が担当した課題は次の通り。 ~・次の経路を黒い線にそって動くロボットを作成する。 ~・A地点をスタートしてQ付近の3/4円周上でピンポン玉をつかみ、そのピンポン玉をD地点においたゴールへシュートする。 ~・Aスタート → P直進 → Q直進 → (ピンポン玉をキャッチ) → Q直進 → R右折 → P直進 → S左折 → Dへシュート ~ただし、 ~・なるべく速く正確に動くロボットになるように工夫して、交差点では1秒間停止すること。 ~・ピンポン玉はQ近くの3/4円周上ならどこにおいてもよい ~・可能であればC,Dのゴールエリアライン上からシュートする * ロボットの説明 [#qd17066d] #ref(./robot.JPG,50%,全体像) ~今回はとにかく課題を達成するために、バランスが悪くとも車輪がコースの紙からはみ出さない大きさに完成させた。 #ref(./counterweight.JPG,50%,カウンターウェイト) ~あまりにもバランスが悪いので写真右のモーターのカウンターウェイトとしてタイヤ2個を本体の反対側につけた。 #ref(./sensor&gear.JPG,50%,センサーとギア) ~車輪のギア比は1:2でパワーが出るようにした。 ~モーターを上部に取り付けたことでライントレース用の光センサーとボール判別用の超音波センサーを本体前部に集中させることが出来た。 * プログラムの説明 [#x73161a1] ** define [#sdc161e0] #define SPEED 100 //モーターのスピードを100(MAX)に設定 #define SPEED2 60 //モーターのスピードを60に設定 #define SPEED3 30 //モーターのスピードを30に設定 #define GO_LEFT Off(OUT_AC);OnRev(OUT_A,SPEED3);OnFwd(OUT_C,SPEED); //進路を左に向けつつ前進 #define GO_RIGHT Off(OUT_AC);OnFwd(OUT_A,SPEED);OnRev(OUT_C,SPEED3); //進路を右に向けつつ前進 #define GO_LEFT2 Off(OUT_AC);OnRev(OUT_A,20);OnFwd(OUT_C,50); //GO_LEFTよりスピードを落として左方向に前進 #define GO_RIGHT2 Off(OUT_AC);OnFwd(OUT_A,50);OnRev(OUT_C,10); //GO_RIGHTよりスピードを落として右方向に前進 #define TURN_LEFT Off(OUT_AC);OnRev(OUT_A,SPEED2);OnFwd(OUT_C,SPEED); //左に旋回 #define TURN_RIGHT Off(OUT_AC);OnFwd(OUT_A,SPEED);OnRev(OUT_C,SPEED2); //右に旋回 ~ロボットがラインから外れないようにするために前進のプログラムを二種類に分けた。 ** subその1 [#na8ff313] sub GO1() { long t0=CurrentTick(); while(CurrentTick()-t0<350){ //黒線を踏み続けた秒数が0.35秒より長くなったとき終了 if(SENSOR_1>45){ //黒線でない場合右方向に進みカウントをリセット、黒線の場合左方向に進む GO_RIGHT; t0=CurrentTick(); }else{ GO_LEFT; } } Off(OUT_AC); PlaySound(SOUND_UP); //subの終了をお知らせ } ~今回は黒線の左を沿って進むプログラムを作った。 ** subその2 [#af7b722d] sub GO2() { long t0=CurrentTick(); while(CurrentTick()-t0<400){ //黒線を踏み続けた秒数が0.4秒より長くなったとき終了 if(SENSOR_1>45){ //黒線でない場合右方向に進みカウントをリセット、黒線の場合左に旋回 GO_RIGHT; t0=CurrentTick(); }else{ TURN_LEFT; } } Off(OUT_AC); PlaySound(SOUND_UP); } ~その1より左カーブがきつい際に使用。 ** subその3 [#k18546fd] sub GO3() { long t0=CurrentTick(); while(CurrentTick()-t0<350){ //黒線を踏まなかった秒数が0.35秒より長くなったとき終了 if(SENSOR_1>45){ //黒線でない場合右方向に進み、黒線の場合左方向に進みカウントをリセット GO_RIGHT; }else{ GO_LEFT; t0=CurrentTick(); } } Off(OUT_AC); PlaySound(SOUND_UP); } ~右カーブに差し掛かるまでのライントレースに使用。右カーブを判別。 ** subその4 [#va786835] sub GO4() { long t0=CurrentTick(); while(CurrentTick()-t0<200){ //黒線を踏み続けた秒数が0.2秒より長くなったとき終了 if(SENSOR_1>45){ //黒線でない場合右に旋回しカウントをリセット、黒線の場合左方向に進む TURN_RIGHT; t0=CurrentTick(); }else{ GO_LEFT; } } Off(OUT_AC); PlaySound(SOUND_UP); } ~その1より右カーブがきつい際に使用。 ** subその5 [#p55f0a0b] sub GOmin() { OnFwd(OUT_A,SPEED); OnFwd(OUT_C,SPEED3); Wait(200); Off(OUT_AC); } ~交差点を越えるため右方向にちょっと前進するプログラム。 ** subその6 [#s77181aa] sub TURN_H_RIGHT() { OnFwd(OUT_A,SPEED); OnRev(OUT_C,SPEED3); Wait(400); Off(OUT_AC); } ~丁字路で右に旋回するプログラム。 ** subその7 [#f3af0d7f] sub TURN_H_LEFT() { OnFwd(OUT_C,SPEED); OnRev(OUT_A,SPEED2); Wait(500); Off(OUT_AC); } ~丁字路で左に旋回するプログラム。 ** subその8 [#e33e7427] sub CATCH() { long t0=CurrentTick(); while(CurrentTick()-t0<350){ if(SensorUS(S2)<10){ //超音波センサーでボールがあるかどうかを判別 Off(OUT_AC); OnFwd(OUT_C,50); //ボールがとれるように本体の向きを変更 Wait(500); Off(OUT_C); OnFwd(OUT_B,SPEED3); //アームを下ろす Wait(500); Off(OUT_B); OnRev(OUT_C,50); //変更した本体の向きを元に戻す Wait(600); Off(OUT_C); }else if(SENSOR_1>45){ GO_RIGHT2; //subその1よりモータースピードを落とした t0=CurrentTick(); }else{ GO_LEFT2; //subその1よりモータースピードを落とした } } Off(OUT_AC); PlaySound(SOUND_UP); } ~ボールを発見し掴むプログラム。基本はsubその1と同じプログラムだが超音波センサーを扱うプログラムが入っている。 ~超音波センサーを使用した事により発生するラグにモーターのスピードを変更することで対応した。 ** プログラム本体 [#k5e1a6f6] task main() { SetSensorLight(S1); SetSensorLowspeed(S2); OnFwd(OUT_AC,SPEED); //スタート地点からコースに入るために前進 Wait(400); Off(OUT_AC); GO1(); //ライントレース開始、その後左カーブを判別 GO2(); //左カーブを曲がり、その後交差点を判別 GOmin(); //Pの交差点を越える GO1(); //ライントレース再開、その後交差点を判別 GOmin(); //Qの交差点を越える CATCH(); //ライントレースをしつつボールを判別し掴む GO2(); //ライントレース再開、その後交差点を判別 OnFwd(OUT_A,SPEED); //再度Qの交差点を越えるがカーブの直後の交差点のため本体の向きが通常と異なるので別途用意したプログラムで交差点を越える OnFwd(OUT_C,20); Wait(400); Off(OUT_AC); //交差点越え終了 GO3(); //ライントレース再開、その後右カーブを判別 GO4(); //右カーブを曲がり、その後直線を判別 GO1(); //直線に入りライントレース再開、その後丁字路を判別 TURN_H_RIGHT(); //Rの丁字路を右に旋回 GO1(); //ライントレース再開、その後交差点を判別 GOmin(); //Pの交差点を越える GO1(); //ライントレース再開、その後丁字路を判別 TURN_H_LEFT(); //Sの丁字路を右に旋回 GO1(); //ライントレース再開、その後ゴールを判別 OnRev(OUT_B,SPEED3); //アームをあげる OnFwd(OUT_AC,SPEED); //ボールをゴールに押し込む Wait(600); Off(OUT_AC); } ~その場その場に対応するために少しゴチャっとしたプログラムになってしまった。 * まとめ [#b3555d29] ~今回は黒線とそれ以外の値の中央をとらず黒線かそれ以外かだけでライントレースをしたが、前進のプログラムを比較的真っ直ぐにしたことで速く進んだ。 ~超音波センサーの使用に手こずったが最終的には使いこなせて良かったと思う。 ~また普通のカーブと交差点をどのように判別したかについてだが、どちらの判別方法にも変わりは無く、何回目に判別した物が何かを予めプログラムに入れて判別した。