2019a/Member

目次

課題3

ピンポン玉または青と赤のボールを運搬して、所定の容器の中に入れる。

画像1

フィールドの説明

基本ルール

詳細はこちら

方針

とにかく安定性を重視した。移動はほぼすべてライントレースで行うため、貼り合わせたフィールドの境界線に線を引いた。ボールを持つ機構はアーム式とし、そのためにはモーターが最低4つ必要であったため、NXTを2台組み合わせた一体型とした。移動関連はマスターが、アーム関連はスレーブが担う。

ロボット

画像1

↑側面。NXTが対称に配置されており、見えているNXTがスレーブ、反対側がマスターである。マスターにはタイヤのモーターと光センサー、スレーブにはアーム関連のモーターがつながっている。

画像1

↑斜め上。NXT本体やモーターのような大きなパーツをなるべく少ないパーツで組み合わせることで、頑丈になる。

画像1

↑背面。こちら側はキャスターが支えている。配線をしまう空間をあけて、見た目にも配慮した。(この画像のみアームの構造が旧型である。)

画像1

↑アームを取り払った前面。デフォルトのようにタイヤを回すモーターを寝かせると、重心の関係でアームの配置が難しくなった。そこで課題1のようにモーターを立てることで、重いNXT本体をアームの反対側に低く配置することができ、重心の問題を解決した。

画像1

↑底面。毎度のごとくタイヤにギアを組み込んでいる。今回は光センサーを2つ使用しており、センサー間は線の幅より少しだけ大きい。タイヤの軸とセンサーの距離は課題2と同様。

画像1

↑真ん中に挟まれたモーターはアームの上げ下げを担う。ここもギアを使用。

画像1

↑このようにアームが上下する。アームはそれなりの重量があり自然に落ちてきてしまうため、プログラムでカバーすることにした(後述)。アームの一部になっているモーターは、玉をつかむ部分の開閉を担う。

画像1

↑玉を2つ同時につかめる大きさとすることで、容器内の玉を効率よく運べる。画像の下の部分は、玉を持ち上げたときに落とさないようにするストッパーである。ギアで回転方向を変えるのが難しかった。

マスターのプログラム

定数、マクロ

#define KOSATEN 37     //37以下は黒
#define completed 15
#define turn_left   OnRev(OUT_A,70);OnFwd(OUT_B,70);   //左に回転する
#define go_left     OnRev(OUT_A,85);Off(OUT_B);        //左に進む
#define go_straight OnRev(OUT_AB,70);                  //まっすぐ進む
#define go_right    OnRev(OUT_B,85);Off(OUT_A);        //右に進む
#define turn_right  OnRev(OUT_B,100);OnFwd(OUT_A,100); //右に回転する
#define short_break Off(OUT_AB);Wait(1000);
#define brake       Off(OUT_AB)

completed は通信に使う(後述)。 brake は「ブレーキ」を意味するが、break として捉えてほしい。

サブルーチン

ライントレース

光センサーを2つ取り付けており、課題2のプログラムを流用できないため、新たに作り直した。左右の値の差を求め、差が大きければ曲がり、0に近ければ直進する仕組みとなっている。以下の画像では、赤い丸が光センサー、数字が光センサーの値、青い四角がタイヤを示している。

画像1

↑このとき、左右の値の差は0のため直進する。

画像1

↑軌道からずれてこのようになると、差が大きくなり軌道を修正する。

画像1

↑このように両側で黒と認識すると交差点と判断する。

画像1

↑このとき、まず右側が黒と認識するため、右に進む。

画像1

↑やがて左側も黒と認識するため、交差点と判断する。

交差点や玉扱い後の動作

ライントレースの性質上、T字路の行き止まりでない方向から進入すると分岐している方向に向いてしまうため、直進のプログラムは2通り作った。

sub chokusinL()                    //交差点を直進(右を向いているとき)
{
 go_left;Wait(500);
}
sub chokusinR()                    //交差点を直進(左を向いているとき)
{
 go_right;Wait(500);
}
sub sasetsu()                      //交差点を左折
{
 turn_left;Wait(500);
 go_left;Wait(500);
}
sub usetsu(int migi)               //交差点を右折
{
 turn_right;Wait(500);
 go_right;Wait(migi);
}
sub turn_behind()                  //振り向く
{
 turn_left;Wait(1000);
 while(SENSOR_1>KOSATEN){
 turn_left;
 }                          //(線を認識するまで回転)
 Off(OUT_BC);
}
sub backleft()                     //後退し右を向く
{
 OnFwd(OUT_A,100);Off(OUT_B);Wait(1500);
 turn_right;Wait(600);
 Off(OUT_AB);
}
sub backright()                    //後退し左を向く
{
 OnFwd(OUT_B,100);Off(OUT_A);Wait(1400);
 turn_left;Wait(500);
 Off(OUT_AB);
}

アーム関連(通信)

アーム関連はスレーブで制御するため、メッセージで指示を出し、completed と完了の合図が来るまで待つような仕組みとなっている。

sub ball_catch()                   //玉をつかむ
{
 int msg;
 SendRemoteNumber(1,MAILBOX1,12);
 while(msg==completed){
  ReceiveRemoteNumber(MAILBOX1,true,msg);
 }
}
sub ball_release()                 //玉を放す
{
 int msg;
 SendRemoteNumber(1,MAILBOX1,11);
 while(msg==completed){
  ReceiveRemoteNumber(MAILBOX1,true,msg);
 }
}
sub arm_up()                      //アームを上げる
{
 int msg;
 SendRemoteNumber(1,MAILBOX1,13);
 while(msg==completed){
  ReceiveRemoteNumber(MAILBOX1,true,msg);
 }
}
sub arm_down()                    //アームを下げる
{
 int msg;
 SendRemoteNumber(1,MAILBOX1,14);
 while(msg==completed){
  ReceiveRemoteNumber(MAILBOX1,true,msg);
 }
}
sub up_catch()                    //アームを上げながら閉じる
{
 int msg;
 SendRemoteNumber(1,MAILBOX1,16);
 while(msg==completed){
  ReceiveRemoteNumber(MAILBOX1,true,msg);
 }
}
sub down_release()                //アームを下げながら開く
{
 int msg;
 SendRemoteNumber(1,MAILBOX1,17);
 while(msg==completed){
  ReceiveRemoteNumber(MAILBOX1,true,msg);
 }
}

task main

移動の流れを下の画像に示す。この順番にしたがってサブルーチン等を組み合わせる。

画像1
task main()
{
 SetSensorLight(S1);                                        //右光センサー
 SetSensorLight(S2);                                        //左光センサー
 arm_up(); short_break; ball_release();
 go_straight; Wait(2000);                                   //A→M
 follow_line();                                             //M→K
 chokusinR(); follow_line2(1500); short_break;              //K→L
 arm_down(); short_break; ball_catch(); short_break;
 arm_up(); short_break;                                     //玉をつかむ
 turn_behind(); follow_line();                              //L→K
 chokusinL();   follow_line();                              //K→M
 usetsu(500);   follow_line();
 sasetsu();     follow_line();                              //M→B
 chokusinL();   follow_line();                              //B→X
 usetsu(500);   follow_line();                              //X→X'
 sasetsu();     follow_line();                              //X'→B'
 chokusinR();   follow_line();                              //B'→M'
 sasetsu();     follow_line();                              //M'→K'
 sasetsu(); follow_line2(1000); short_break;                //K'→J'
 ball_release(); short_break;                               //玉を放す
 backleft();   //J'→K'
 follow_line2(3700); short_break;                           //K'→L'
 arm_down(); short_break; ball_catch(); short_break;
 arm_up(); short_break;                                     //玉をつかむ
 turn_behind(); OnFwd(OUT_AB,30); Wait(100); follow_line(); //L'→K'
 usetsu(500); follow_line2(500); short_break;               //K'→J'
 ball_release(); short_break;                               //玉を放す
 backright(); follow_line();                                //J'→K'
 chokusinL(); follow_line();                                //K'→M'
 usetsu(500); follow_line();                                //M'→B'
 chokusinL(); follow_line();                                //B'→X'
 usetsu(500); follow_line();                                //X'→X
 sasetsu();   follow_line();                                //X→B
 sasetsu();   follow_line();                                //B→C
 usetsu(400); follow_line2(1650); short_break;              //C→I
 arm_down(); short_break; ball_catch(); short_break;
 up_catch(); short_break;                                   //玉をつかむ
 backleft();                                                //I→C
 follow_line();                                             //C→B
 usetsu(500); follow_line();                                //B→X
 usetsu(500); follow_line();                                //X→X'
 sasetsu();   follow_line();                                //X'→B'
 sasetsu();   follow_line();                                //B'→C'
 usetsu(700); follow_line2(900); short_break;               //C'→I'
 down_release(); short_break;                               //玉を放す
 arm_up(); short_break;
 backright();                                               //I'→C'
}

スレーブのプログラム

通信してアームを動かすだけなので、シンプルである。

定数

すべてマスターと対応している。

#define ball_release 11
#define ball_catch   12
#define arm_up       13
#define arm_down     14
#define completed    15
#define up_catch     16
#define down_release 17

task main

マスターの指示に従って動作し、完了したら completed とメッセージを送る。

task main()
{
 int msg;
 while(true){
  ReceiveRemoteNumber(MAILBOX1,true,msg);
  if(msg==ball_release){
   OnFwd(OUT_A,50);Wait(500);Off(OUT_A);Wait(500);
   SendResponseNumber(MAILBOX1,completed);
  }                                                 //玉をつかむ
  if(msg==ball_catch){
   OnRev(OUT_A,50);Wait(600);Off(OUT_A);Wait(500);
   SendResponseNumber(MAILBOX1,completed);
  }                                                 //玉を放す
  if(msg==arm_up){
   OnFwd(OUT_B,50);Wait(600); OnFwd(OUT_B,5);Wait(500);
   SendResponseNumber(MAILBOX1,completed);
  }                                                 //アームを上げる
  if(msg==arm_down){
   OnRev(OUT_B,30);Wait(600); OnFwd(OUT_B,5);Wait(500);
   SendResponseNumber(MAILBOX1,completed);
  }                                                 //アームを下げる
  if(msg==up_catch){
   OnFwd(OUT_B,40);OnRev(OUT_A,15);Wait(300);
   SendResponseNumber(MAILBOX1,completed);
  }                                                 //アームを上げながら閉じる
  if(msg==down_release){
   OnRev(OUT_B,10);OnFwd(OUT_A,20);Wait(150);
   SendResponseNumber(MAILBOX1,completed);
  }                                                 //アームを下げながら開く
  Wait(100);
  msg=0;
 }
}

アームが重力で落ちてくるのを防ぐため、アームの上げ下げのプログラムは Off(OUT_B)から OnFwd(OUT_B,5) に置き換えている。すると、常にアームに上向きの力が働き、重力とつり合う。

まとめ

アーム式というありきたりな仕組みではあるが、安定性を突き詰めたおかげで容器外の玉2つを確実に運ぶことができた。容器内の玉もあと少し調整を加えれば運べただろう。3人チームでもそれぞれ役割分担をして完成に近づけたことに大変達成感を感じている。


添付ファイル: filefield'.jpg 165件 [詳細] filelt5.JPG 175件 [詳細] filelt4.JPG 124件 [詳細] filelt3.JPG 116件 [詳細] filelt2.JPG 202件 [詳細] filelt1.JPG 130件 [詳細] filerobot8.jpg 193件 [詳細] filerobot7.jpg 194件 [詳細] filerobot6.jpg 161件 [詳細] filerobot5.jpg 174件 [詳細] filerobot4.jpg 169件 [詳細] filerobot3.JPG 140件 [詳細] filerobot2.jpg 180件 [詳細] filerobot1.jpg 176件 [詳細] filefield.jpg 161件 [詳細]

トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-08-14 (水) 21:32:28