2006a/C2/課題3左


光源を見失った時には曲を演奏しながらぐるっと旋回して光源を探すプログラム

カウンタ804

プログラムの簡単な説明

  • 光を追う部分、光を見つける部分はサブルーチンを用いて、演奏部分はtaskを用いました。
  1. まず最初に、一周まわって光源を見つけます
  2. 光センサーに光があたっているならば、その光を追っかけるサブルーチンを実行。
  3. 光センサー1・3のどちらにも光があたっていないならば、演奏しながら光源を見つけるサブルーチンを実行します。
  4. 以後2と3を繰り返します

プログラム全体

#define Standard_of_light 55 //懐中電灯の光の強さの定義
#define turn_time 200        //一回転にかかる時間

task play_Ride_of_the_Vallyries()
{
#define vfa3 349*vk //Vallyriesのファ(低) 
#define vra 440*vk   //Vallyriesのラ (低)
#define vsi 494*vk   //Vallyriesのシ

#define vDo 523*vk   //Vallyriesのド
#define vre 587*vk   //Vallyriesのレ
#define vmi 659*vk   //Vallyriesのミ
#define vfa 698*vk   //Vallyriesのファ(中)
 
#define vfa2 740*vk  //Vallyriesのファ(高)
#define vra2 880*vk  //Vallyriesのラ  (高)
#define vn 3         //曲の速さを調節するための数値
#define vt 5         //曲の速さを調節するための数値
#define vk 1         //音の高さを調節するための数値
 
      while(true){

    PlayTone(vsi,6*vn);Wait(6*vn+vt);
    PlayTone(vfa3,2*vn);Wait(2*vn+vt);
    Wait(vn);                           //休符
    PlayTone(vsi,3*vn);Wait(3*vn+vt);
    Wait(vn);                           //休符
    PlayTone(vre,12*vn);Wait(12*vn+vt);
    PlayTone(vsi,12*vn);Wait(12*vn+vt);
 
    PlayTone(vre,6*vn);Wait(6*vn+vt);
    PlayTone(vsi,2*vn);Wait(2*vn+vt);
    Wait(vn);                           //休符
    PlayTone(vre,3*vn);Wait(3*vn+vt);
    Wait(vn);                           //休符
    PlayTone(vfa2,12*vn);Wait(12*vn+vt);
    PlayTone(vre,12*vn);Wait(12*vn+vt);

    PlayTone(vfa2,6*vn);Wait(6*vn+vt);
    PlayTone(vre,2*vn);Wait(2*vn+vt);
    Wait(vn);                          //休符
    PlayTone(vfa2,3*vn);Wait(3*vn+vt);
    Wait(vn);                          //休符
    PlayTone(vra2,12*vn);Wait(12*vn+vt);
    PlayTone(vra,12*vn);Wait(12*vn+vt);

    PlayTone(vre,12*vn);Wait(12*vn+vt);
    PlayTone(vra,4*vn);Wait(4*vn+vt);
    Wait(vn*2);                        //休符
    PlayTone(vre,6*vn);Wait(6*vn+vt);
    Wait(vn*2);                        //休符
    PlayTone(vfa2,24*vn);Wait(24*vn+vt);
              }
 }

sub follow_light()           //光を追う事を命ずるサブルーティン
{
#define Borderline_S 4       //小さい境界線
#define Borderline_L 20      //大きな境界線 詳しい説明は下記
    while((SENSOR_1>Standard_of_light)|| (SENSOR_1>Standard_of_light))
     //光センサー1・光センサー3のどちらかに光が当たっている場合

     {     int d;          //dという変数を定義する
           d=SENSOR_1-SENSOR_3;//dは光センサー1と光センサー3のとる値の差である

        if((-Borderline_S <= d) && (d <= Borderline_S))
               {OnFwd(OUT_A+OUT_C);}        //go
 
        if((Borderline_S <d) && (d< Borderline_L))
               {OnFwd(OUT_C);Float(OUT_A);} //sllowly_turn_right

        if(( Borderline_L <=d) && (d<= 100))
                 {OnFwd(OUT_C);OnRev(OUT_A);} //rapidly_turn_rigth

        if((-Borderline_L <=d) && (d<-Borderline_S))
                 {OnFwd(OUT_A);Float(OUT_C);} //sllowly_turn_left

        if((-100 <=d) && (d< -Borderline_L))
                  {OnFwd(OUT_A);OnRev(OUT_C);} //rapidly_turn_left
       }
     }

sub look_for_light()        //光源を見つけるサブルーティン
 {
 
        int light_max=0; //変数light_maxを定義、0を代入
        int time=0;      //同じく変数itmeを定義、0を代入
  
   ClearTimer(0);      //タイマー(0)をリセット
       time=FastTimer(0);  //timeにFastTimerの値を代入する
       light_max=SENSOR_1; //light_timeにSENSOR_1の値を代入する
       start play_Ride_of_the_Vallyries ;  //ワルキューレの騎行の演奏を開始する
        
    while(FastTimer(0)<=turn_time){         //マシンが一回する間、実行し続ける
    
          OnFwd(OUT_C);OnRev(OUT_A);       //右に回りましょう

       if(SENSOR_1>light_max)            //もし光センサー1の値が光の最大値よりおおきいならば
         { time=FastTimer(0);   //そのときのタイマー(0)の値がtimeとなり
         light_max=SENSOR_1;}   //そのときのセンサー1の値が光の最大値となります

        }

   Off(OUT_A+OUT_C); Wait(50);                     //0,5秒間停止
   OnFwd(OUT_A);OnRev(OUT_C); Wait(turn_time-time);左に回転
   Off(OUT_A+OUT_C); Wait(50);                    //0.5秒間停止
               }
 		 
task main()
  {
   SetSensor(SENSOR_1,SENSOR_LIGHT);//センサー1が光センサーであることを定義
   SetSensor(SENSOR_3,SENSOR_LIGHT);//センサー3が光センサーであることを定義

          look_for_light();         //いよいよメインタスクです
      
   while(true){          
               if((SENSOR_3>Standard_of_light)||(SENSOR_1>Standard_of_light)) {//どちらかのセンサーに光が当たっている場合、
                 follow_light(); //光を追うサブルーティンを実行
               }if((SENSOR_1<Standard_of_light) && (SENSOR_3<Standard_of_light)){//どちらのセンサーにも光が当たっていない場合
                look_for_light();//光源を見つけるサブルーティンを実行
                stop play_Ride_of_the_Vallyries;}//演奏を中止
               }
   }

プログラムの各部分の事細かな解説

演奏部分

  • task task play_Ride_of_the_Vallyries()
    • vn・vk・vtnなどといった数値を変化させることにより簡単に曲の速さ・音の高さを変えることができる。
  • vn・vk・vtn・vfa・vdo・vra…などの頭についているvはVallyriesの頭文字です。 君が代で用いるドレミと混同することを避けるための処置です。
  • int vt(vn); vt(vn)=SENSOR_1/5;などを用いれば、光の強さに応じて曲の速さを変化させることが出来きます
  • #define vk 1 の変わりに、
    while(){
    int vk;
    vk=1 ; 
    〜演奏部分〜
    vk =vk/2 ;
       }
            とおけば再生を繰り返すごとに音が低くなり、より本物っぽい演奏ができる

光を追っかける部分

  • sub follow_light()
  • 旋回速度を2種類用意することで、滑らかにかつどこまでも光を追い続けることが出来る
    • ……予定でしたが、正直なところ自分の立ち位置、作業場所、使用する光源などの条件により、光の量差の基準の調整をこまめにせねばならず、難しく、使いにくいものとなってしまいました。
  • 一見すると、とってもとってもややこしく見えますので、分かりやすくするために、表を作りまとめてみます。
    • dは光センサー1と光センサーのとる値の差
    • dが正の数となるならば、マシンは右に動く
    • dが負の数となくならば、マシンは左に動く
  • Borderline_Sが4でBorderline_Lが20の場合
条件式とその意味マシンの行動
if( (-Borderline_S <= d) && (d <= Borderline_S) )差が4以内ならば左右のタイヤを順回転ささて前進する
if( (Borderline_S <d) && (d< Borderline_L) )差が4より高く20未満であるならば左タイヤを順回転、右タイヤを停止させ右に旋回する
if( ( Borderline_L <=d) && (d<= 100) ) ))差が20以上であるならば左タイヤを順回転、右タイヤを逆回転させ右に急旋回する
if( (-Borderline_L <=d) && (d<-Borderline_S) )差が4より高く20未満であるならば右タイヤを順回転、左タイヤを停止させ左に旋回する
if( (-100 <=d) && (d< -Borderline_L) )差が20以上であるならば右タイヤを順回転、左タイヤを逆回転させ左に急旋回する
  • int d; d=SENSOR_1-SENSOR_3;をwhile(……)のなかに入れないとうまくマシンが働かない
  • 差が50を超えるような事態はまずないと思われますが、念のため100を上限としています

光源を見つける部分

  • sub look_for_light()
    • int light_max=0;の部分の=0を抜かしていることになかなか気づくことが出来ず、相当苦労した。=0なしには光を見つけることは出来ない

以上3つをつなげる過程で生じた問題

  • 意外と3つのプログラムを上手につなげるのは難しい。
  • 当初、演奏部分もサブルーティンを用いてつなげようとしたため、演奏が終わるまで次の命令を聞かないといった問題が発生した
  • task main()のなかのwhile(true)とsub follow_light()の中のwhile(true)の条件を合わせないと、マシンは思うように働いてくれない。

感想

  • 非常に難しい課題でした。
  • 上記の=0の問題などほんの些細なことで、プログラム全体が狂ってしまいます。とても難しかったです。
  • おまけに今週は忙しく作業時間もうまく確保することが出来ませんでした。自宅でも作業が出来るように、myPCにbricx command centerをインストールしました。
  • 期限の前日は午前3時まで、作業をしてました。

プログラム・レポートの書き方に関するコメント


  • ご指摘の通りかなり難しい問題だと思います。それだけになるべく分かりやすい構造のプログラムを書くことが重要ですが、シェイプアップできるところがもうないかどうか考えてみてください。 -- 松本(教員)? 2006-07-11 (火) 10:28:04



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2006-07-12 (水) 00:18:33 (4793d)