#contents

* 課題2 [#n5b84371]

#ref(2015b/Member/cst321/Mission2/2015b-mission2.png,100%,コース);

次の経路を黒い線にそって動くロボットを作成する (他のメンバーとは別の経路になるようにする)。ただし、なるべく速く正確に動くロボットになるように工夫して、交差点では1秒間停止すること。

B地点からA地点へ 
B地点 → P右折 → Q右折 → P左折 → Q左折 → Q直進 → P直進 → A地点


* ロボット本体 [#y406f53e]
今回のロボットと前回の一番大きな違いはセンサーがついているということだ。
そして、少し調整して、本体を小さくし、センサーをより近く、ロボットの中心に設置した。

&ref(2015b/Member/cst321/Mission2/IMG_1023.JPG,10%,本体);
&ref(2015b/Member/cst321/Mission2/IMG_1025.JPG,10%,センサーの位置);

そうすると、ロボットの本体が、よりきれいに線に沿って動ける。

* プログラム [#ce0c7a74]
今回のプルグラムは前の課題より複雑で長い。今回の課題の中心がプログラムだと思う。

特徴としては、このプログラムは路線図に従って、細かくプログラムした。
たとえば、BからP交差点までのプログラムとP交差点を渡るプログラムとP交差点からQ交差点までのプログラムは違う。

これが全体のプログラムだ!長いと思うので飛ばして、次の目次から詳細を少しずつ説明する。


 #define THRE 39
 #define WHRE 48
 #define HBHRE 37
 #define HWHRE 46

 #define start1 SetPower(OUT_A,7);SetPower(OUT_C,7);OnFwd(OUT_AC);
 #define TR SetPower(OUT_A,5);SetPower(OUT_C,6);Off(OUT_AC);OnFwd(OUT_A);OnRev(OUT_C);
 #define TL SetPower(OUT_A,6);SetPower(OUT_C,5);Off(OUT_AC);OnFwd(OUT_C);OnRev(OUT_A);
 #define TRL SetPower(OUT_A,4);SetPower(OUT_C,1);Off(OUT_AC);OnFwd(OUT_A);
 #define TLL SetPower(OUT_A,1);SetPower(OUT_C,4);Off(OUT_AC);OnFwd(OUT_C);
 #define ST SetPower(OUT_A,4);SetPower(OUT_C,4);Off(OUT_AC);OnFwd(OUT_AC);

 #define Do 1047
 #define LaF 831
 #define SiF 932
 #define Si 988

 int x;
 sub music()
 {
     PlayTone(Do,20);
     Wait(30);
     PlayTone(Do,20);
     Wait(30);
     PlayTone(Do,20);
     Wait(30);
     PlayTone(Do,60);
     Wait(62);
     PlayTone(LaF,60);
     Wait(62);
     PlayTone(SiF,60);
     Wait(62);
     PlayTone(Do,20);
     Wait(42);
     PlayTone(Si,20);
     Wait(22);
     PlayTone(Do,90);
     Wait(92);
 }

 sub trace_1(){
  if(SENSOR_2>WHRE)
       {TR;ClearTimer(0);
        }        
  else if(SENSOR_2>HWHRE)
       {TRL;
        ClearTimer(0);
        }
  else if(SENSOR_2>THRE)
       {ST;
       ClearTimer(0);
        }
  else if(SENSOR_2>HBHRE)
       {TLL;ClearTimer(0);
        }
  else {TL;
        }
 }

 task main ()
 {   start1;
    Wait(120);
    SetSensor(SENSOR_2,SENSOR_LIGHT);
    x=0;
    ClearTimer(0);
 
 while (true)
 {
  while(FastTimer(0)<30&&x==0)
  {
 trace_1()
   }
  while(x==1)
   {TR;Wait(15);Off(OUT_AC);ClearTimer(0);x=x+1;}
  while(FastTimer(0)<22&&x==2)
   {
 trace_1()
   }
 while(FastTimer(0)<28&&x==3)
  {
  trace_1()
   }
 while(x==4)
  {TL;Wait(60);Off(OUT_AC);ClearTimer(0);x=x+1;}
 while(FastTimer(0)<27&&x==5)
  {
 trace_1()
   }
 while(x==6)
  {TL;Wait(60);Off(OUT_AC);x=x+1;ClearTimer(0);}
 while(FastTimer(0)<27&&x==7)          // route Q to Q
  {
  trace_1()
   }
 while(x==8)
  {ST;Wait(30);Off(OUT_AC);ClearTimer(0);x=x+1;}
 while(FastTimer(0)<27&&x==9)          // route Q to P
  {
  trace_1()
   }
 while(x==10)
  {ST;Wait(30);Off(OUT_AC);ClearTimer(0);x=x+1;}   // P cross
 while(FastTimer(0)<27&&x==11)          // route P to end
  {
  trace_1()
   }
 while(x==12)
  {TR;Wait(20);ST;Wait(100);Off(OUT_AC);Wait(100);music();ClearTimer(0);x=x+1;}
 Off(OUT_AC);Wait(100);x+=1;ClearTimer(0);
   }
 Off(OUT_AC);
   }

** Defineの応用 [#f1ee28b3]
まず、自分が書いた路線の意色の閾値を設定した。
より綺麗に動いてもらえるため、単に白、黒、と真ん中の閾値だけではなく、白と真ん中の間の閾値と黒と真ん中の閾値を設定した。
THREとは真ん中で、WHREとは白

 #define THRE 39
 #define WHRE 48
 #define HBHRE 37
 #define HWHRE 46

次に、
今回のロボットは小さいため、普通のパワーの出力で動かすと、早く動いてしまうので、コントロールするのが難しい。ギアを変えるより、パワーを変えることにした。

そして、大回りするとき、一つの車輪を動かすだけではなく、
もう一個の車輪がやや逆の方向へ回すように設定されている。

 #define start1 SetPower(OUT_A,7);SetPower(OUT_C,7);OnFwd(OUT_AC);
 #define TR SetPower(OUT_A,5);SetPower(OUT_C,6);Off(OUT_AC);OnFwd(OUT_A);OnRev(OUT_C);
 #define TL SetPower(OUT_A,6);SetPower(OUT_C,5);Off(OUT_AC);OnFwd(OUT_C);OnRev(OUT_A);
 #define TRL SetPower(OUT_A,4);SetPower(OUT_C,1);Off(OUT_AC);OnFwd(OUT_A);
 #define TLL SetPower(OUT_A,1);SetPower(OUT_C,4);Off(OUT_AC);OnFwd(OUT_C);
 #define ST SetPower(OUT_A,4);SetPower(OUT_C,4);Off(OUT_AC);OnFwd(OUT_AC);

start1は最初の出発するところで使うのだ。
TRとは turn rightで、TLとはturn leftで、
加えて、
TRLとは Turn right little,TLLとはTurn left little,
STとは straightだ。

** Fasttimerの応用  [#jf9c7087]
道に沿って行くようにするプログラムの一部だ。
これはBからP交差点までのプログラムだ。
ここで、ロボットを道の右側に置くと道に沿っていけます。


 while (true)
 {
  while(FastTimer(0)<30&&x==0)
  {
  if(SENSOR_2>WHRE)
       {TL;ClearTimer(0);
        }        
  else if(SENSOR_2>HWHRE)
       {TLL;
        ClearTimer(0);
        }
  else if(SENSOR_2>THRE)
       {ST;
       ClearTimer(0);
        }
  else if(SENSOR_2>HBHRE)
       {TRL;ClearTimer(0);
        }
  else
       {TR;
        }

ここではFasttimerとCleartimerを使う。つまり、Fasttimer<30というのは0.3秒以上で黒を探知すると、
このプログラムを飛ばして、次のプログラムに移る。

そして0.3秒以下だと、
センサーが白に触れると左回る、そしてCleartimerをする。

センサーが黒に触れると右回る、またCleartimerをする。

交差点に到着しなければ、次のプログラムには移らない。


** subの応用 [#f995041a]
ここで何回もラインライントレースをするので、その長いプログラムを短くするために、サブルーチンにしました。そうすると、プログラムのサイズが小さくなります。

 sub trace_1(){
  if(SENSOR_2>WHRE)
       {TR;ClearTimer(0);
        }        
  else if(SENSOR_2>HWHRE)
       {TRL;
        ClearTimer(0);
        }
  else if(SENSOR_2>THRE)
       {ST;
       ClearTimer(0);
        }
  else if(SENSOR_2>HBHRE)
       {TLL;ClearTimer(0);
        }
  else {TL;
        }
 }


** カウントの応用 [#q9a03612]
ロボットが多くのプログラムに混乱されないため、カウントを設置した。
Fastimerが各自の時間を超えた後、
Off(OUT_AC);Wait(100);x+=1;ClearTimer(0);
というプログラムに移る、つまり、Cleartimerをして、カウントが一個増える。
そうすると、また上の新しい while(x==1)のところへ行く、
それが終わった後、またカウントが一個増えて、
while(x==2)のところへ行く。

カウントを使って、路線のすべての道と交差点で、ロボットを迷わせず、違うプログラムが入れられるようになった。

** 二つの組み合わせ [#j9659a43]
この二つの応用の組み合わせで、違う道で、違うFasttimerの上限が使える。

例えば、Q交差点で右を回るのが異常に難しく、Fasttimerの上限を30に設置すると、たまに、交差点で止まらず、すぐ右へ回る場合が多い。

そのため、Fasttimerの上限を22に設置しなければ成功率が低い。

結果、
while(FastTimer(0)<22&&x==2)というプログラムを使った。xが2カウントの同時に、Fasttimerが22より低いという条件を付けることになった。


* 問題 [#f19136e8]
プログラムが長すぎて、ロボットへアップロードするのが時間がかかりすぎる。
なるべく短いプログラムがいいと思われる。

ロボット自体が小さく、早いので、どこでどのぐらいパワーが必要かを把握するには時間がかかりすぎる。


* 結果 [#xdf11e3d]
失敗するのが少なく、

道にそって綺麗に動いて、BからAまでに到着し、歌もきちんと出てるので、成功した!

* ボーナス、成功の歌 [#r6c9fa55]
この歌はFinal Fantasy の Victory Fanfareの前半だ。ロボットが終点に到着すると放送するようにプログラムした。
 #define Do 1047
 #define LaF 831
 #define SiF 932
 #define Si 988

 sub music()
 {
     PlayTone(Do,20);
     Wait(30);
     PlayTone(Do,20);
     Wait(30);
     PlayTone(Do,20);
     Wait(30);
     PlayTone(Do,60);
     Wait(62);
     PlayTone(LaF,60);
     Wait(62);
     PlayTone(SiF,60);
     Wait(62);
     PlayTone(Do,20);
     Wait(42);
     PlayTone(Si,20);
     Wait(22);
     PlayTone(Do,90);
     Wait(92);
 }
* 感想 [#ce4e7597]

今回すべてのプログラムが私一人で、書いたのではなく、同じロボットを使っている友達と一緒に閾値のことを検討し、そして、プログラムのことをお互いに意見を交換した。

友達が路線を書くから、プログラムまで、すべてをきちんととても細かくした。
私は逆におおざっぱですべてをやりたかったと思った。

結局

やはり、センサーが色を探知するには、路線をきちんと書かなきゃいけないと分かった。
そして、ロボットが綺麗に動くようにするためのプログラムは、やはりもっと細かく分ける必要があることが分かった。

二人で夜遅くまで10番教室で一緒に課題をやるのは、楽しかった。

今回の課題でいろいろなことが学んでいて、友達からも学んだ、ためになった。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS