課題2

指定の道をあらかじめ模造紙に描き、第1コース・第2コースそれぞれの道順に沿って製作したロボットを動かす。また、その途中に、350mlの空き缶を指定の位置から、指定の位置に運ぶ。

コース

第2コース

2018a-mission2.png
1Aをスタート
2Bを右折
3Jで一時停止の後、Yの空き缶をキャッチしてJに戻る
4JからKに向かい、Kを直進
5Lを直進
6Iを左折
7Hで一時停止の後、左折
8Gで一時停止の後、右折
9Fで一時停止の後、右折
10Eを直進
11Dで一時停止の後、空き缶をXに置いてDに戻り、Cに向かう
12Cで一時停止の後、直進
13Bを直進
14Aで停止
(一時停止の指定がある場所は、1秒間停止すること)

ロボットの説明

車輪部分

課題1と同様、シンプルな3輪構造で、前輪が2輪、後輪が1輪となっている。前輪の2輪が駆動し、後輪の2輪が自由に回転する。

センサーライト部分

2つの車輪ほぼ真ん中前方に、確実に明るさを読み取れるような高さに設置した。

IMG_1298.JPG

アーム

IMG_1301.JPG
アーム.png

モータBに歯車を直接取り付け、 アームの動作は缶をつかむ動作、缶の方向を変える動作、缶を離す動作の3段階に分かれている。

缶をつかむ動作

モータBを稼働させるだけでは先にアームの方向が変わってしまうので、図のようにある程度固定し、缶をつかむ動作のみが稼働するようにした。

IMG_1300neo.png

缶の方向を変える動作

缶をつかむ動作を終えると缶をつかむ動きが固定され、缶の方向をかえる力が大きくなる。すると、上の図の部品が外れ、缶の方向が左に変わる。

缶を離す動作

缶の方向が変わると赤で囲まれた部分が回転し、それとともに黄で囲まれた部分が上昇し、回転部分にひっかかる。すると、缶の方向を変える部分が固定され、モータBを回すと、缶を離す。

IMG_1299ex.png

交差点の感知

今回、私は関数DAI(DAIに深い意味はない)を使って交差点を感知する方法として採用した。関数DAIは4つの範囲で図に示した数値を足されることになっている。

白黒数値2.png
#define LEFT_LINE if(DEEPWHITE){RIGHT DAI -= 3;} else if(WHITE){BIT_RIGHT DAI -= 1;} else if(DEEPBLACK){LEFT DAI += 3;} else if(BLACK){BIT_LEFT DAI += 1;} else {STRAGHT DAI *= 0;}    
#define RIGHT_LINE if(DEEPWHITE){LEFT DAI -= 3;} else if(WHITE){BIT_LEFT DAI -= 1;} else if(DEEPBACK){RIGHT DAI += 3;} else if(BLACK){BIT_RIGHT DAI += 1;} else {STRAGHT DAI *= 0;}

プログラムのようにその時位置している範囲に従ってそれ相応の数値を足され、指定の方向へ移動する。どの範囲にも属さない時(丁度白と黒の境界にある時)は直進する。

右[#gabb9e62]
#define RIGHT OnFwd(OUT_A,30);OnRev(OUT_C,30);Wait(1);Off(OUT_AC);
少し右[#f2a3eb93]
#define BIT_RIGHT OnFwd(OUT_A,30);OnRev(OUT_C,10);Wait(1);Off(OUT_AC);
左[#yf200910]
#define LEFT OnFwd(OUT_C,30);OnRev(OUT_A,30);Wait(1);Off(OUT_AC);
少し左[#m9a0ad8a]
#define BIT_LEFT OnFwd(OUT_C,30);OnRev(OUT_A,10);Wait(1);Off(OUT_AC);
直線方向[#d825c59f]
#define STRAGHT OnFwd(OUT_AC,30);Wait(1);Off(OUT_AC);

各方向に1000分の1秒進み、その時間毎に今存在している範囲を感知することで正確にライントレースできるようにした。

#define KANSU DAI < 150

ライントレース中は4つの範囲を行き来するのでほぼ±0に保たれ、交差点にさしかかるとDEEPBLACKの範囲上に比較的長時間存在するので関数DAIが増加し、関数DAIが150を超えると次の動作へうつる。 また、関数DAIを正確に測るためにライントレース前には"DAI *= 0"(関数DAIに0をかけて0にする)をする。

交差点からの右折等

(例)右折

右折1.png
右折2.png
右折3.png

交差点を感知し、停止する。(図A) 85°くらい回転する。(図B)

while(BLACK){OnFwd(OUT_AC,20);}

地面がBLACKになるまで直進する。(図C) ライントレースする。

プログラミングにあたっての準備

色分けし、それに伴う方向に動くプログラム

白
#define DEEPWHITE SENSOR_1 > 48
少し白 [#g54731d9]
#define WHITE SENSOR_1 > 44
少し黒ece9d1]
#define BLACK SENSOR_1 < 40
黒 [#hdece4ff]
#define DEEPBLACK SENSOR_1 < 36
右[#gabb9e62]
#define RIGHT OnFwd(OUT_A,30);OnRev(OUT_C,30);Wait(1);Off(OUT_AC);
少し右[#f2a3eb93]
#define BIT_RIGHT OnFwd(OUT_A,30);OnRev(OUT_C,10);Wait(1);Off(OUT_AC);
左[#yf200910]
#define LEFT OnFwd(OUT_C,30);OnRev(OUT_A,30);Wait(1);Off(OUT_AC);
少し左[#m9a0ad8a]
#define BIT_LEFT OnFwd(OUT_C,30);OnRev(OUT_A,10);Wait(1);Off(OUT_AC);
直線方向[#d825c59f]
#define STRAGHT OnFwd(OUT_AC,30);Wait(1);Off(OUT_AC);
白黒判別.png

※上のプログラムを組み合わせて図のように動作するようにした。

#define LEFT_LINE if(DEEPWHITE){RIGHT DAI -= 3;} else if(WHITE){BIT_RIGHT DAI -= 1;} else if(DEEPBLACK){LEFT DAI += 3;} else if(BLACK){BIT_LEFT DAI += 1;} else {STRAGHT DAI *= 0;}    
#define RIGHT_LINE if(DEEPWHITE){LEFT DAI -= 3;} else if(WHITE){BIT_LEFT DAI -= 1;} else if(DEEPBACK){RIGHT DAI += 3;} else if(BLACK){BIT_RIGHT DAI += 1;} else {STRAGHT DAI *= 0;}
#define KANSU DAI < 150

それぞれ左・右のライントレース時に使うプログラム

 
#define OFF Off(OUT_AC);
 
#define WAIT Wait(1000);

車輪を止めるプログラムと停止するプログラム

 
#define CATCH OnFwd(OUT_AC,20);Wait(300);OFF OnFwd(OUT_B,30);Wait(300);Off(OUT_B);OnRev(OUT_AC,20);Wait(300);OFF
 
#define RELEASE OnFwd(OUT_B,30);Wait(1000);Off(OUT_B);Wait(500);OnRev(OUT_B,30);Wait(500);Off(OUT_B);

それぞれアームを閉開するプログラム

 
#define SIMPLE_RIGHT OnFwd(OUT_A,40);OnRev(OUT_C,40);
 
#define SIMPLE_LEFT OnFwd(OUT_C,40);OnRev(OUT_A,40);

それぞれ右・左にその場で旋回するプログラム

 
#define GO_STRAIGHT OnFwd(OUT_A,40);OnFwd(OUT_C,40);Wait(190);OFF
#define MOVE_RIGHT SIMPLE_RIGHT Wait(750); OFF
 
#define GO_STRAIGHT OnFwd(OUT_A,40);OnFwd(OUT_C,40);Wait(190);OFF
#define MOVE_LEFT SIMPLE_LEFT Wait(750); OFF

それぞれ交差点で右・左に曲がるプログラム

プログラム本編

task main()

{
   SetSensorLight(S1);

   int DAI=0;

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF
   DAI *= 0;           //右ライントレース
   PlaySound(SOUND_DOWN);         //音を鳴らす

   GO_STRAIGHT                    //少し直進
   MOVE_RIGHT                     //右に85°曲がる

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF
   DAI *= 0;                      //右ライントレース
   PlaySound(SOUND_UP);           //音を鳴らす
   WAIT                           //停止
   CATCH                          //掴む

   OnFwd(OUT_B,10);               //掴み続ける

   GO_STRAIGHT                    //少し直進
   MOVE_LEFT                      //左に85°曲がる

   while(BLACK){
                   OnFwd(OUT_AC,20);
                 }
   OFF                            //黒になるまで直進

   repeat(2){
                while(KANSU){
                                LEFT_LINE
                                }
                OFF
                DAI *= 0;                      //左ライントレース

                SIMPLE_RIGHT
                Wait(50);
                OFF                            //微調整

                while(BLACK){
                                OnFwd(OUT_AC,30);
                                }
                OFF                            //黒になるまで直進
              }

   while(KANSU){
                   LEFT_LINE
                 }
   OFF                            //左ライントレース
   PlaySound(SOUND_UP);           //音を鳴らす
   WAIT              //停止
   DAI *= 0;

   OnFwd(OUT_AC,30);
   Wait(50);
   OFF

   SIMPLE_LEFT
   Wait(450);
   OFF                            //微調整

   while(KANSU){
                   LEFT_LINE
                 }
   OFF
   DAI *= 0;                      //左ライントレース

   while(BLACK){
                   OnFwd(OUT_A,30);OnFwd(OUT_C,30);
                 }
   OFF                            //黒になるまで直進

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF
   DAI *= 0;                      //右ライントレース

   while(BLACK){
                   OnFwd(OUT_A,30);OnFwd(OUT_C,30);
                 }
   OFF                            //黒になるまで直進

   while(KANSU){
                   LEFT_LINE
                 }
   OFF
   DAI *= 0;                      //左ライントレース

   GO_STRAIGHT                    //少し直進
   MOVE_LEFT                      //左に85°曲がる

   while(KANSU){
                   LEFT_LINE
                 }
   OFF
   DAI *= 0;                      //左ライントレース
   WAIT                           //停止

   GO_STRAIGHT                    //少し直進
   MOVE_RIGHT                     //右に85°曲がる

   while(BLACK){
                   OnFwd(OUT_A,30);OnFwd(OUT_C,30);
                 }
   OFF                            //黒になるまで直進

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF
   DAI *= 0;                      //右ライントレース
   WAIT                           //停止
   PlaySound(SOUND_UP);           //音を鳴らす

   GO_STRAIGHT                    //少し直進
   MOVE_RIGHT                     //右に85°曲がる

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF                            //右ライントレース

   SIMPLE_RIGHT
   Wait(50);
   OFF              //微調整

   while(BLACK){
                   OnFwd(OUT_AC,30);
                  }
   OFF                            //黒になるまで直進

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF                            //右ライントレース

   Off(OUT_B);                    //掴み続けることをやめる
   WAIT                           //停止
   RELEASE                        //離す

   OnFwd(OUT_AC,30);
   Wait(80);
   OFF

   SIMPLE_RIGHT
   Wait(500);
   OFF              //微調整

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF
   DAI *= 0;                      //右ライントレース

   GO_STRAIGHT                    //少し直進
   MOVE_RIGHT                     //右に85°曲がる

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF
   DAI *= 0;                      //右ライントレース
   WAIT                           //停止
   PlaySound(SOUND_UP);           //音を鳴らす

   while(BLACK){
                   OnFwd(OUT_A,30);OnFwd(OUT_C,29);
                 }
   OFF                            //黒になるまで直進

   while(KANSU){
                   RIGHT_LINE
                 }
   OFF
   DAI *= 0;                      //右ライントレース
   PlaySound(SOUND_FAST_UP);      //音を鳴らす
}

課題2を終えて

苦労した点

作成の過程では、センサーライトやアームを所定の位置に設置しつつ、全体のバランスを保つことが難しかった。また、アーム部分を1つのモータで2段階動かすことにこだわり過ぎて、時間と労力を使い過ぎた。プログラミングの過程では、交差点などを正常に通過させる確率を上げることが大変だった。

工夫した点

上では苦労したと書いたが、やはり、あらゆる工夫を取り込んで、1つのモータで2段階動かすことができたことがよかった。また、ライントレースに関数を使用することで安定して交差点を認識できるようにした。


添付ファイル: file右折3.png 147件 [詳細] file右折2.png 135件 [詳細] file右折1.png 132件 [詳細] file白黒数値2.png 125件 [詳細] fileアーム.png 180件 [詳細] file白黒判別.png 147件 [詳細] file白黒数値.png 62件 [詳細] fileIMG_1299ex.png 125件 [詳細] fileIMG_1300neo.png 164件 [詳細] fileIMG_1299neo.png 86件 [詳細] file2018a-mission2.png 144件 [詳細] filesirokuro.png 68件 [詳細] fileIMG_1301.JPG 125件 [詳細] fileIMG_1299.JPG 74件 [詳細] fileIMG_1298.JPG 124件 [詳細] fileIMG_1300.JPG 41件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-08-18 (土) 00:26:22