*目次 [#od529227]
#contents
*課題3について [#b1f55a3c]
課題2で作成したコースを用いてタイムレースを行う。ルール等詳しい内容は[[課題3:http://yakushi.shinshu-u.ac.jp/robotics/?2016a%2FMission3]]へ。
*ロボットについて [#ab8211c1]
**ロボット全体 [#f5a88054]
&ref(課題3全体.jpg);&ref(課題3裏面.jpg);&br;マイコンは1つ使用した。目や口が備わっていてかわいい。また、底面は前回同様小回りが利くようになっており、ライントレースがしやすい。
**2つの光センサー [#m6f328ef]
&ref(光センサー.jpg);&br;ライントレース用の底面の光センサーのほかにアームの先に光センサーを取り付けることによって、紙コップを認識できるようにした。
**アーム [#s1a7ea3c]
今回のロボットは2本のアームがついており、これで紙コップを取り、ホールドすることができる。
*プログラムについて [#sfc6a3d2]
今回のプログラムは同じ班の黒河内君がほとんどを作成した。
**定義 [#c510a511]
***定数 [#a5321332]
 #define CROSS_TIME 40
 #define BALANCE_TIME 40
CROSS_TIME:交差点判別時間 黒部分がCROSS_TIMEより続いたら交差点として判別する。&br;BALANCE_TIME:姿勢制御用時間 境界部分がBALANCE_TIMEより続いたら機体がまっすぐとして判別する。
***マクロ [#l3618fb5]
 #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);//角度を右寄りにして外側の線に機体を移動
下3つは交差点認識後の動作である。
**ライントレース [#pfc2ad9c]
***光センサーの判別する値 [#v080246f]
白部分・・・・・光センサーの値:53以降&br;
弱白部分・・・光センサーの値:52以降〜53以下&br;
境界部分・・・光センサーの値:44以降〜52以下&br;
弱黒部分・・・光センサーの値:41以降〜44以下&br;
黒部分・・・・・光センサーの値:41未満
***タイマーについて [#z7ed8e6a]
FastTimer(0):交差点判別用のタイマー &br;
光センサーが黒部分の判定をしている時にカウントをして、0.4秒以上続いたら交差点として判別する。また、黒部分以外の時はClearTimer(0)でFastTimer(0)を初期化する。&br;
FastTimer(1):交差点誤判別防止用のタイマー&br;
小さなカーブを交差点として誤判別しないために指定秒数間交差点判別を行わないようにする。ここで、指定秒数を変数としてl_timeをグローバル変数として定義する。また、ライントレース開始時にClearTimer(1)でFastTimer(1)を初期化する。
***ライントレース [#y81d1c1f]
今回はラインの左側をトレースした。
 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秒待つ 
    }
  }
黒線上にいる時間をタイマーで計測し、一定時間(CROSS_TIME)を過ぎたら交差点と認識するようにした。急なカーブで誤認識しないようにもう1つタイマーを使い、指定秒数をカウントしなければ交差点と判別しないようにした。
**紙コップを取る [#caf52fd2]
下図のようにアームを上げ下ろしすることで、紙コップを持ち上げひっくり返しながら積み上げられる。
下図のようにアームを上げ下ろしすることで、紙コップを持ち上げひっくり返しながら積み上げられる。&br;
&ref(紙コップを取る.jpg);&size(65){→};&ref(紙コップ.jpg);&br;
紙コップを取得する一連の動作のプログラムはこのようになっている。
 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);
  }
**姿勢制御 [#f99c083f]
***タイマーについて [#r6b924f4]
FastTimer(0):姿勢判別用のタイマー&br;
光センサーが境界部分の判定をしている時にカウントをして、タイマーがBALANCE_TIME以上になったら機体の姿勢をまっすぐとして判別する。また、境界部分以外の時はClearTimer(0)でFastTimer(0)を初期化する。&br;
FastTimer(1):ライントレース時間判別用のタイマー 
ライントレースをする時間を指定しなければ、姿勢がまっすぐにならない場合ライントレースをし続けてしまい、C,D地点に置いてある紙コップをとることが出来なくなってしまうので追加した。また、姿勢制御プログラム開始時にClearTimer(1)でFastTimer(1)を初期化する。
***姿勢制御の方法 [#z3366ea9]
姿勢制御のプログラムは交差点判別プログラムを応用しているが、黒部分の判定ではなく境界部分の判定をしている。
-左境界部分での姿勢制御
 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;
          }
    }
  }
-右境界部分での姿勢制御
 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;
          }
    }
  }
境界部分が長く続いた時に機体がまっすぐであると判別するようにした。タイマーがBALANCE_TIME(0.4秒)より長い時間が経過した時に機体がまっすぐであると判別する。また、機体が一定時間(2秒)経過してもまっすぐにならない場合、一度後退してから姿勢制御プログラムを再開する。
**CD点間の移動 [#me94609f]
***C地点からD地点への移動 [#vc4db929]
C地点の紙コップを取得後、左回転し右境界部分で姿勢制御を開始する。
***D地点からC地点への移動 [#s2afd46b]
D地点の紙コップを取得後、後退をし交差点を超えてから左回転し右境界部分で姿勢制御を開始する。また右回転ではなく左回転をする理由は、左側にはアームだけしかストッパーがなく紙コップが転倒する可能性が上がるたので、左回転にした。
-左回転プログラム 
 sub turn(){
   OnFwd(OUT_C); //左回転
   OnRev(OUT_A);
   Wait(100);  //黒部分から白部分に出るための時間(D地点からC地点への移動時に特に必要)
   while(SENSOR_2>41); //白部分である場合は回転し続ける
   Off(OUT_AC); //停止
 }
光センサーで判別して回転するので、電池の消費による回転不足をなくすことができた。
*結果・反省 [#n83e8fba]
**基本点 [#p84b3a8d]
-1回目&br;
アーム先の光センサーの不具合によってうまく作動せずに紙コップを運べず、0点。
-2回目&br;
4つの紙コップを積んで運ぶことができ、30点を獲得。
**技術点 [#f6974519]
技術点は1回目の評価が採用されるので、5.2点とあまり高くなかった。
**反省と感想 [#g7ce37bc]

今回の課題は今までと違って6人で作業をするので、短い時間でどれだけ進めることができるか、内容の濃いことができるか、ということが重要だったように思う。はじめは2つのロボットを通信させる予定だったのが急きょ1つに変更になったり、動作の安定性に問題があったりといくつかアクシデントがあったが、それらを乗り越えて優勝を獲得できてよかった。私はあまり優勝に貢献できていなかったが、チームで作り上げたものが良い結果を取るというのはやはりうれしい。私は機械・ロボット学科なので、今後このように何人かでものを作り上げるという機会があるかもしれない。そのときはこの授業で培った、話し合いアイディアを練り上げてよいものを作る、という力を生かしたい。

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