目次

黒い線に沿って動くロボット

各チームで次のようなコースを作成し、コースを2周するようなロボットを完成させよ

  • 黒い線の幅は15〜25ミリの範囲で一定にすること
  • 交差点を3か所以上設置すること
  • 直角のコーナーを2か所以上設置すること
  • 近道を2か所以上設置(直角のコーナーのショートカットも可)
  • スタートにはコースに直角に5センチ程度の線を引く

ただし

  • 速さと正確さを追求する
  • 2周目はスタート地点の直前で自動ストップ
  • 近道を走るものと正規ルートを走るものを作成

メンバー

  • なかむ
  • (わん)

ロボットの紹介

ロボットの工夫点

  • なるべく小型化できるようにした。
  • 前回の課題でギア比に失敗したため、ギア比にも気をつかった。
  • ロボットは、黒い線をトレースするというよりは、黒い線の両端の白い部分をトレースするようにした。

写真

  • ロボット全体
    DSCN0441.JPG
    実は元のドライブベースはほとんど変えていなくて、車身を短くした程度。
  • 光センサーの部分
    DSCN0447.JPG
    なるべくホイールの近くにつけられるようにした。 光センサーの情報とホイールの部分で誤差が出ないようにしたかったからである。
  • 回転センサーの部分
    DSCN0442.JPG
    回転センサーは右ホイールに写真のように取り付けた。 このように取り付けたので、マシンが前進したら回転センサーはマイナスの値を刻むようになっている。
    DSCN0446.JPG
    回転センサーにギアをもう1枚使用したため、ギアによる誤差が出るのではないかと危惧して取り付けた。  結果としては意味をなさなかったので『左右対称の美学』ってことにしておく。
  • おまけ
    DSCN0445.JPG
    『左右対称の美学』じゃなかった...

コース

DSCN0450.JPG

プログラム

近道をたどるプログラム (担当:なかむ)

     #define TH 40     //光センサーの閾値
     #define go OnFwd(OUT_A+OUT_C);     //まっすぐ進む
     #define sasetu SetPower(OUT_A,1);SetPower(OUT_C,1);OnRev(OUT_A);OnFwd(OUT_C);Wait(1);     //左折
     #define usetu SetPower(OUT_A,1);SetPower(OUT_C,1);OnFwd(OUT_A);OnRev(OUT_C);Wait(1);     //右折
     #define migi SetPower(OUT_A,1);SetPower(OUT_C,4);OnFwd(OUT_A);OnRev(OUT_C);Wait(1);     //右にカーブ
     #define hidari SetPower(OUT_A,4);SetPower(OUT_C,1);OnRev(OUT_A);OnFwd(OUT_C);Wait(1);     //左にカーブ
     #define teisi Off(OUT_A+OUT_C);     //停止
     #define taiki Wait(1)     //100分の1秒間停止
    
     task play_music ()     //1秒に1回音がなるタスク
       {
          while (true) {
          PlaySound(0);Wait(100);
                                }
       }
     
     task main ()     //1周目のタスク
       {
          SetPower(OUT_A,2);     //左のトルクを2に設定
          SetPower(OUT_C,2);     //右のトルクを2に設定
          SetSensor(SENSOR_1,SENSOR_ROTATION);     //回転センサー定義
          SetSensor(SENSOR_2, SENSOR_LIGHT);     //左の光センサー定義
          SetSensor(SENSOR_3, SENSOR_LIGHT);     //右の光センサー定義
          
          ClearSensor(SENSOR_1);     //回転センサーを0に戻す
          go;     //まっすぐ進む
          start play_music;     //音を鳴らすタスクを連動させる
         
          while (true) {    go;
                        if ((SENSOR_2 < TH)&&(SENSOR_3 > TH)) {
                                      hidari;
                                               }     //左が黒、右が白で左にカーブ
                        if ((SENSOR_3 < TH)&&(SENSOR_2 > TH)) {
                                      migi;
                                               }     //左が白、右が黒で右にカーブ
                        if ((SENSOR_3 < TH)&&(SENSOR_2 < TH)) {
                                      teisi;
                                      taiki;
                                               }     //交差点を判定
                        if ((SENSOR_1 < -300)&&(SENSOR_3 < TH)&&(SENSOR_2 > TH)){ 
                                      usetu;
                                               }     //マシンが中の四角のエリアに入り、左が白、右が黒なら右折
                        if ((SENSOR_1 < -300)&&(SENSOR_3 > TH)&&(SENSOR_2 < TH)){
                                      sasetu;
                                               }     //マシンが中の四角のエリアに入り、左が黒、右が白なら左折
                        if ((SENSOR_1 < -160)&&(SENSOR_1 > -175)&&(SENSOR_3 < TH)){
                                      OnFwd(OUT_A);
                                      OnRev(OUT_C);
                                      Wait(25);
                                      go;
                                      Wait(10); 
                                               }     //近道に入る
                        if ((SENSOR_1 < -1070)&&(SENSOR_1 > -1080)&&(SENSOR_3 < TH)){
                                      OnFwd(OUT_A);
                                      OnRev(OUT_C);
                                      Wait(30);
                                      go;
                                      Wait(10); 
                                               }     //近道に入る
                        if ((SENSOR_1 < -1430)&&(SENSOR_1 > -1470)){
                                      go;
                                      Wait(10);
                                               }     //下部の円のエリアに入る
                        if ((SENSOR_1 < -1900)&&(SENSOR_1 > -1940)){
                                      go;
                                      Wait(10);
                                               }     //下部の円のエリアから出る
                        if ((SENSOR_1 < -1980)&&(SENSOR_2<TH)&&(SENSOR_3<TH)){
                                      ClearSensor (SENSOR_1);
                                      start follow_line;
                                               }     //スタート地点に戻ったら回転センサーをリセットし、2周目のタスクを起動
                                     }
       }
     
     task follow_line ()     //2周目のタスク
       {
          SetPower(OUT_A,2);     //左のトルクを2に指定
          SetPower(OUT_C,2);     //右のトルクを2に指定
          SetSensor(SENSOR_1,SENSOR_ROTATION);     //回転センサー定義
          SetSensor(SENSOR_2, SENSOR_LIGHT);     //光センサー定義
          SetSensor(SENSOR_3, SENSOR_LIGHT);     //光センサー定義
          ClearSensor(SENSOR_1);     //回転センサーをリセット
          stop main;     //1周目のタスクを停止
          
          while (true) {     go;
          
                       if ((SENSOR_2 < TH)&&(SENSOR_3 > TH)) {
                                      hidari;
                                               }     //左が黒、右が白で左にカーブ
                       if ((SENSOR_3 < TH)&&(SENSOR_2 > TH)) {
                                      migi;
                                               }     //右が黒、左が白で右にカーブ
                       if ((SENSOR_3 < TH)&&(SENSOR_2 < TH)) {
                                      teisi;
                                      taiki;
                                               }     //交差点を判定
                       if ((SENSOR_1 < -300)&&(SENSOR_3 < TH)&&(SENSOR_2 > TH)){ 
                                      usetu;
                                               }     //図の内部の四角のエリアに入り、左が白、右が黒で右折
                       if ((SENSOR_1 < -300)&&(SENSOR_3 > TH)&&(SENSOR_2 < TH)){
                                      sasetu;
                                               }     //図の内部の四角いエリアに入り、左が黒、右が白で左折
                       if ((SENSOR_1 < -160)&&(SENSOR_1 > -175)&&(SENSOR_3 < TH)){
                                      OnFwd(OUT_A);
                                      OnRev(OUT_C);
                                      Wait(25);
                                      go;
                                      Wait(10); 
                                               }     //近道に入る
                       if ((SENSOR_1 < -1070)&&(SENSOR_1 > -1080)&&(SENSOR_3 < TH)){
                                      OnFwd(OUT_A);
                                      OnRev(OUT_C);
                                      Wait(30);
                                      go;
                                      Wait(10);
                                               }     //近道に入る
                       if ((SENSOR_1 < -1430)&&(SENSOR_1 > -1470)){
                                      go;
                                      Wait(10);
                                               }     //下部の円のエリアに入る
                       if ((SENSOR_1 < -1900)&&(SENSOR_1 > -1940)){
                                      go;
                                      Wait(10);
                                               }     //下部の円のエリアから出る
                       if (SENSOR_1 < -1980){ 
                                      teisi;
                                               }     //スタート地点の手前で停止
         
                                     }
     }

プログラミングの工夫点

  • 当初、直角に曲がることができなかったので2種類の曲がり方をプログラミングに取り入れた。
  • タスクを1周目と2周目で分けた。理由は単純、徹夜をして思考回路が他に回らなかった。
  • ライントレースでは下部の円の部分に入れなかったので回転センサーで指定し、うまく入れるようにした。
  • タイマーに使えると思い、1秒に1回音がなるようにしてみたが、バッテリーによって時間がバラバラでタイマーが使えなかった。

正規ルートをたどるプログラム (担当:なかむ)

    #define TH 40     //光センサーの閾値 
    #define go OnFwd(OUT_A+OUT_C);     //まっすぐ進む
    #define sasetu SetPower(OUT_A,1);SetPower(OUT_C,1);OnRev(OUT_A);OnFwd(OUT_C);Wait(1);     //左折
    #define usetu SetPower(OUT_A,1);SetPower(OUT_C,1);OnFwd(OUT_A);OnRev(OUT_C);Wait(1);     //右折
    #define migi SetPower(OUT_A,1);SetPower(OUT_C,4);OnFwd(OUT_A);OnRev(OUT_C);Wait(1);     //右にカーブ
    #define hidari SetPower(OUT_A,4);SetPower(OUT_C,1);OnRev(OUT_A);OnFwd(OUT_C);Wait(1);     //左にカーブ
    #define teisi Off(OUT_A+OUT_C);     //停止
    #define taiki Wait(1)     //100分の1秒間停止
    
    task play_music ()     //1秒に1回音がなるタスク
    {
         while (true) {
         PlaySound(0);Wait(100);
    }
    }
    
    task main ()     //1周目のタスク
    {
         SetPower(OUT_A,2);     //左のトルクを2に設定
         SetPower(OUT_C,2);     //右のトルクを2に設定
         SetSensor(SENSOR_1,SENSOR_ROTATION);     //回転センサー定義
         SetSensor(SENSOR_2, SENSOR_LIGHT);     //左の光センサー定義
         SetSensor(SENSOR_3, SENSOR_LIGHT);     //右の光センサー定義
    
         ClearSensor(SENSOR_1);     //回転センサーを0に戻す
         go;     //まっすぐ進む
         start play_music;     //音を鳴らすタスクを連動させる
         
         while (true) {     go;
                   if ((SENSOR_2 < TH)&&(SENSOR_3 > TH)) {
                                      hidari;
                                               }     //左が黒、右が白で左にカーブ
                   if ((SENSOR_3 < TH)&&(SENSOR_2 > TH)) {
                                      migi;
                                               }     //左が白、右が黒で右にカーブ
                   if ((SENSOR_3 < TH)&&(SENSOR_2 < TH)) {
                                      teisi;
                                      taiki;
                                               }     //交差点を判定
                   if ((SENSOR_1 < -280)&&(SENSOR_3 < TH)&&(SENSOR_2 > TH)){ 
                                      usetu;
                                               }     //マシンが中の四角のエリアに入り、左が白、右が黒なら右折
                   if ((SENSOR_1 < -280)&&(SENSOR_3 > TH)&&(SENSOR_2 < TH)){
                                      sasetu;
                                               }     //マシンが中の四角のエリアに入り、左が黒、右が白なら左折
                   if ((SENSOR_1 < -1390)&&(SENSOR_1 > -1430)){
                                      go;
                                      Wait(10);
                                               }     //下部の円のエリアに入る
                   if ((SENSOR_1 < -1860)&&(SENSOR_1 > -1900)){
                                      go;
                                      Wait(10);
                                               }     //下部の円のエリアから出る
                   if ((SENSOR_1 < -1940)&&(SENSOR_2<TH)&&(SENSOR_3<TH)){
                                      ClearSensor (SENSOR_1);
                                      start follow_line;
                                               }     //スタート地点に戻ったら回転センサーをリセットし、2周目のタスクを起動
                                                    }
             }
    
    task follow_line ()     //2周目のタスク
    {
         SetPower(OUT_A,2);     //左のトルクを2に指定
         SetPower(OUT_C,2);     //右のトルクを2に指定
         SetSensor(SENSOR_1,SENSOR_ROTATION);     //回転センサー定義
         SetSensor(SENSOR_2, SENSOR_LIGHT);     //光センサー定義
         SetSensor(SENSOR_3, SENSOR_LIGHT);     //光センサー定義
        
         ClearSensor(SENSOR_1);     //回転センサーをリセット
         stop main;     //1周目のタスクを停止
        
         while (true) {     go;
                   if ((SENSOR_2 < TH)&&(SENSOR_3 > TH)) {
                                      hidari;
                                               }     //左が黒、右が白で左にカーブ
                   if ((SENSOR_3 < TH)&&(SENSOR_2 > TH)) {
                                      migi;
                                               }     //右が黒、左が白で右にカーブ
                   if ((SENSOR_3 < TH)&&(SENSOR_2 < TH)) {
                                      teisi;
                                      taiki;
                                               }     //交差点を判定
                   if ((SENSOR_1 < -280)&&(SENSOR_3 < TH)&&(SENSOR_2 > TH)){ 
                                      usetu;
                                               }     //図の内部の四角のエリアに入り、左が白、右が黒で右折
                   if ((SENSOR_1 < -280)&&(SENSOR_3 > TH)&&(SENSOR_2 < TH)){
                                      sasetu;
                                               }     //図の内部の四角いエリアに入り、左が黒、右が白で左折
                   if ((SENSOR_1 < -1390)&&(SENSOR_1 > -1430)){
                                      go;
                                      Wait(10);
                                               }     //下部の円のエリアに入る
                   if ((SENSOR_1 < -1860)&&(SENSOR_1 > -1900)){
                                      go;
                                      Wait(10);
                                               }     //下部の円のエリアから出る
                   if (SENSOR_1 < -1940){ 
                                      teisi;
                                               }     //スタート地点の手前で停止
                                                    }
              }

プログラミングの工夫点

  • 回転センサーの値を変えて、近道のプログラミングを入れるだけで近道のルートが完成するようにした。

感想

  • なかむの感想
    • 今回はパートナーとの連携がまるでうまくいかなかった。授業時間外にパートナーと会って作業する事も出来なかった。その結果、期日までに課題の完成に至らなかった。また、結果としてプログラミングを2つとも僕が作るハメになってしまった。これで2人分の評価だってのが正直釈だが、いたしかたない。
    • 今回、課題に取り組むにあたり1人で作業が行えず、A4右の2人や他の人にも協力していただいた。本当に感謝している。
  • わんの感想
    • とくになし

コメント

コメントをどうぞ

  • ロボットの説明は良くできています。コースの説明も加えてください -- TAKA? 2011-01-08 (土) 02:30:40
  • プログラムもロボットもがんばっていると思います。まだコースが貼ってない点とプログラムに空行がなく見にくい点を直してください。 -- FI? 2011-01-08 (土) 05:17:10
  • コースとプログラムの説明がリンクしていてわかりやすいです。プログラムの方はtask main()とtask follow_line()を設けていますが、もう少しすっきりさせられるかもしれません。 -- FI? 2011-02-08 (火) 13:30:54


添付ファイル: fileDSCN0450.JPG 137件 [詳細] fileDSCN0445.JPG 165件 [詳細] fileDSCN0446.JPG 160件 [詳細] fileDSCN0447.JPG 167件 [詳細] fileDSCN0443.JPG 108件 [詳細] fileDSCN0442.JPG 161件 [詳細] fileDSCN0441.JPG 178件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2011-02-08 (火) 13:30:54 (2867d)