*はじめに [#bdf4ce2a]
*課題 [#ba46394b]
**ルール [#vd6a8cfb]
ルールはC地点、D地点にある紙コップを交互に積み上げ、その積み上げた個数を競うものである。コースは課題2のコースを使う。
ロボットはA地点B地点からスタートし、一体型の場合はどちらかからスタートする。
2機が通信して協力し合い、課題をいかに早くクリアするかを競うものである。

*目次 [#v7885e67]
#contens 
**方針 [#xe848675]
今回の課題はルール上、NXT一機につきモーターが3つという制限ではクリアはきつかった。よって一体型を作ることにした。
一体を移動とセンサ系、もう一体をカップの積み上げという作業の分担を行わせる。また、片方に主眼を置いてプログラムうを組むことで、通信を行わせるという課題をクリアするとともに全体の流れを把握しやすくなることを狙った。

*あ [#rf62f317]
流れとしてはスタート地点から近い方のカップに向かう。その後、C地点とD地点の間を往復しカップを積み上げる。その間、積み上げたカップは機体で保持するようにする。
最後にゴールにカップを置いて終了とする。
ざっくりとだが以上である。

*ハードウェアについて [#j89df8c3]
ハードは上記の方針より、以下の4つの能力が必要となる。
・カップを掴む
・カップを積み上げる
・積み上げられたカップを保持すること
・積み上げられたカップを崩すことなく下すこと
これらを満たすハードウェアとして複数の関節を持ったアームのような機構とカップを保持するためだけの機構を作った。

それぞれの機構については以下の様になった。
**アーム部分 [#p341d057]
アーム部分はカップを持ち上げる動作、積み上げる動作を担う部分である。よってクレーンを参考として腕のような機構を作った。(下画像)
#ref(s_DSC_1508.JPG)

下はカップを掴んでいる写真

順に説明する。
***手に当たる先端部分について。 [#o80c7315]
これは下の画像のように隣接する歯車は逆に回転していることを利用した。
#ref(s_DSC_1516.JPG)

プログラムは下記の通りである。モーターの回転角度が小さくてすむため回転角度を指定する命令を利用した。使用回数が多いため、ほとんどは定義部分にのみ入れている。

 RotateMotor(OUT_B,50,-88);   //手閉じる

 RotateMotor(OUT_B,50,88);    //手開く

また、先端にてモーターが腕の部分と垂直になっているのはバランスを保つためである。今回は紙コップを掴む競技であったためゴムによる滑り止めと紙コップの淵による引っかかりでより安定する持ち方となっている。しかし、モーターの形や掴む対象の形しだいでは、手の取り付けをもう一工夫する必要がある。

***肘に当たる中間部分について [#v3d9a2eb]
肘の部分は普通に考えればモーターの回転する部分に長い棒を固定して回せば良い。
しかしこの機器の場合、手の重さとモーターの力不足によりそれではアームが壊れる可能性が強くなってしまう。
よってこの機体では下の画像のようにギア比の差を利用した出力不足の改善を行った。大きい歯車が2つ付いているのは腕の補強のために力のかかる場所を分散させるためである。
#ref(s_DSC_1514.JPG)

下はプログラムの一例である。
出力はギア比の工夫により下げることが出来た。よって動きが速すぎてカップを落とすことのないよう、心持ち低めにしてある。
角度はプラスで腕を上げマイナスで下がり、記載角度のおよそ1/5の角度分腕が上下する。

 RotateMotor(OUT_C,50,500);

***肩に当たる根元部分について [#ubdfd921]
肩の部分は下画像の様になっている。
#ref(s_DSC_1515.JPG)
ここでもギア比による出力不足の解消を使った。
また、アームの大型化による重量の増加でバランスが保てなかったため、本体(制御部分)を重石として使った。モーターが本体同士の間にあるのはそのためである。
#ref(s_DSC_1500.JPG)
本体と肩の画像。更なる安定化を図り、本体の高さも出来る限り低めにしてある。
プログラムは以下の通り。回転角度を調節する機会が多かったため定義と剰余計算を使っている。

 #define kata_hanten 860
 RotateMotor(OUT_A,75,kata_hanten/2);    //肩90度回転(正で正面右)

**カップの保持について [#r904cc1d]
上記のアームは手の形から「積み上げられた」カップを持ち上げるのは不可能に近いと考えた。よって下画像のような保持腕を作った。
#ref(s_DSC_1498.JPG)
本体よりやや離れた位置に取り付けられているのはアームが機体前方より反転し、腕を下した位置に保持腕が来るようにするためである。
#ref(s_DSC_1499.JPG)
画像は丁度カップを積み上げるところのもの。

またこの保持腕の存在により、C地点とD地点の往復回数を減らすと共にゴール地点にて保持腕を開くだけで積み上げられたカップを静かに置ける、ということも可能である。

**センサー系について [#z3c69419]
センサーは超音波センサと光センサを使う。ただし今回は時間の都合上光センサの調整は間に合わず、使うことは出来なかった。

***超音波センサ [#f97d26f1]
超音波センサはカップとの距離を測るために使用した。
#ref(s_DSC_1506.JPG)
画像の様にY字のパーツと併用してアームが確実にカップを取れる場所に機体とカップを誘導した。

***光センサ [#naae3c4c]
光センサは予定では車体下部に2個取り付け、ライントレースの交差点の判断を容易なものとした。

**走行について [#j3859f4f]
車輪とモーたーは機体の重心の都合により本体の下には設置出来なかった。よって下画像のように若干横にせり出した形になった。また、モーターの取り付けの関係上モーターの正転で後進、モーターの後転で前進となっている。
#ref(s_DSC_1500.JPG)
プログラムは以下のような回転角度指定の命令を主に使用した。

 RotateMotorEx(OUT_AC,75,-600,0,true,true);    //左右同期させて-600度ぶん「前進」


*ソフトウェアについて [#t4529da6]
方針より、マスターをメインとした流れとなるように組んだ。

**マスター側 [#ub7621fe]
基本的な流れは方針の通りである。
スタート(A)地点→D地点
カップを2個持ちC地点へ
カップを積み上げ残りの1個を持ちD地点へ
カップを積み上げゴール地点で保持腕を開く。

しかし今回は時間の都合上、C地点で積み上げた後ゴール地点へとなっている。
ただし機体が大型化しているためC地点の手前で旋回するだけでゴール内へ保持腕が入るようになってしまっている。
 #define CONN 1   // スレーブの接続番号
 #define tyouonpa 7.75
 
 task main()
 {
    SetSensorLowspeed(S1);
    RotateMotorEx(OUT_AC,75,-600,0,true,true);  //AからDへと向かう
    Wait(2000);
    until (BluetoothStatus(CONN) == NO_ERR); //接続できるまで待つ
    OnRevSync(OUT_AC,50,0);
    until (SensorUS(S1) <= tyouonpa);  //8cmまで近づく
    Off(OUT_AC);
    RemoteStartProgram(CONN,"cup_hold_first.rxe");  //コップをつかんで下ろすプログラムを起動
    Wait(10000);
    RotateMotor(OUT_B,30,-20);
    Wait(15000);
    RotateMotor(OUT_B,50,-28);
    OnRevSync(OUT_AC,50,0);
    until (SensorUS(S1) <= tyouonpa);  //8cmまで近づく
    Off(OUT_AC);
    RemoteStartProgram(CONN,"cup_hold.rxe");  //コップをつかんだままのプログラムを起動
    Wait(10000);
    RotateMotorEx(OUT_AC,75,500,100,true,false);  //方向転換
    RotateMotorEx(OUT_AC,75,-1500,0,false,false);  //Cに向かう
    OnRevSync(OUT_AC,75,0);
    until (SensorUS(S1) <= tyouonpa);  //7cmまで近づく
    Off(OUT_AC);
    RemoteStartProgram(CONN,"cup_yoko_oki.rxe");
    Wait(15000);
    RemoteStartProgram(CONN,"cup_hold_next.rxe");  //コップをつかんで下ろすプログラムを起動
    Wait(20000);
    RemoteStartProgram(CONN,"cup_yoko_toru.rxe");
    Wait(20000);
    OnRevSync(OUT_AC,75,0);
    until (SensorUS(S1) <= tyouonpa);  //7cmまで近づく
    Off(OUT_AC);
    RemoteStartProgram(CONN,"cup_hold_next.rxe");  //コップをつかんで下ろすプログラムを起動
    Wait(20000);
    RotateMotor(OUT_A,75,180);  //方向転換
    RotateMotor(OUT_B,30,50);  //アームを開く
 }

**スレーブ側 [#raaffcdd]
【】はファイル名となっている。

【cup_hold】
 #define hold_up RotateMotor(OUT_C,50,500); Wait(1000); RotateMotor(OUT_B,50,-88); RotateMotor(OUT_C,80,-500);
 #define hold_down RotateMotor(OUT_C,50,500); Wait(1000); RotateMotor(OUT_B,50,88); RotateMotor(OUT_C,80,-500);

 task main()
 {
    ResetTachoCount(OUT_ABC);
    hold_up;                      //手(先端)がモータB 肘(中間)がモータC 肩(根本)がモータA
    Off(OUT_B);
 }

前方のカップを持ち上げるプログラム。

【cup_hold_first】
 #define hold_up RotateMotor(OUT_C,50,500); Wait(1000); RotateMotor(OUT_B,50,-88); RotateMotor(OUT_C,80,-500);
 #define hold_down RotateMotor(OUT_C,50,500); Wait(1000); RotateMotor(OUT_B,50,88); RotateMotor(OUT_C,80,-500);
 #define kata_hanten 860

 task main()
 {
    ResetTachoCount(OUT_ABC);        //手(先端)がモータB 肘(中間)がモータC 肩(根本)がモータA
    hold_up;
    RotateMotor(OUT_C,90,-100);
    Off(OUT_B);
    Wait(2000);
    RotateMotor(OUT_A,75,kata_hanten);    //肩180度回転(正で正面右)
    Wait(1500);
    RotateMotor(OUT_C,75,100);
    hold_down;
    RotateMotor(OUT_A,75,-kata_hanten); //マイナスで手を閉じる
    ResetTachoCount(OUT_ABC);
 }

一番最初のカップを持ち上げ、保持腕に卸すプログラム。保持腕にカップがあるときと無いときで腕の下す角度を変えないといけないため作成した。

【cup_hold_next】
 #define hold_up RotateMotor(OUT_C,50,540); Wait(1500); RotateMotor(OUT_B,50,-88); RotateMotor(OUT_C,80,-540);
 #define hold_down RotateMotor(OUT_C,50,450); Wait(1500); RotateMotor(OUT_B,50,88); RotateMotor(OUT_C,80,-450);
 #define kata_hanten 860

 task main()
 {
    ResetTachoCount(OUT_ABC);  //手(先端)がモータB 肘(中間)がモータC 肩(根本)がモータA
    hold_up;            
    RotateMotor(OUT_C,90,-100);  
    RotateMotor(OUT_B,80,-3);
    Off(OUT_B);
    Wait(2000);
    RotateMotor(OUT_A,75,kata_hanten);    //肩180度回転(正で正面右)
    RotateMotor(OUT_C,50,50);
    Wait(2000);
    hold_down;
    RotateMotor(OUT_C,50,50);
    RotateMotor(OUT_B,80,3);
    RotateMotor(OUT_A,75,-kata_hanten); //マイナスで手を閉じる
    ResetTachoCount(OUT_ABC);
 }

保持腕にカップがあるときに前方のカップを持ち上げ、保持腕に卸すプログラム。保持腕にカップが無いときにこのプログラムを使うと保持腕がカップを掴めず、カップが倒れてしまう。

【cup_yoko_oki】

 #define hold_up RotateMotor(OUT_C,50,540); Wait(1000); RotateMotor(OUT_B,50,-88); RotateMotor(OUT_C,80,-540);
 #define hold_down RotateMotor(OUT_C,50,500); Wait(1000); RotateMotor(OUT_B,50,88); RotateMotor(OUT_C,80,-500);
 #define kata_hanten 860

 task main()
 {
    ResetTachoCount(OUT_ABC);    //手(先端)がモータB 肘(中間)がモータC 肩(根本)がモータA
    RotateMotor(OUT_A,75,kata_hanten/2);    //肩90度回転(正で正面右)
    Wait(1500);
    hold_down;
    RotateMotor(OUT_A,75,-kata_hanten/2); //マイナスで手を閉じる
    ResetTachoCount(OUT_ABC);
}

C地点とD地点の往復を減らすため、最初の移動でアームにカップを掴ませて移動し、そのカップを機体横に下すプログラム。横に置いている時は移動を行わないことでカップを見失うのを防いでいる。

【cup_yoko_toru】
 #define hold_up RotateMotor(OUT_C,50,540); Wait(1000); RotateMotor(OUT_B,50,-88); RotateMotor(OUT_C,80,-540);
 #define hold_down RotateMotor(OUT_C,50,500); Wait(1000); RotateMotor(OUT_B,50,88); RotateMotor(OUT_C,80,-500);
 #define kata_hanten 860

 task main()
 {
    ResetTachoCount(OUT_ABC);    //手(先端)がモータB 肘(中間)がモータC 肩(根本)がモータA
    RotateMotor(OUT_A,75,kata_hanten/2);    //肩90度回転(正で正面右)
    Wait(1000);
    hold_up;
    RotateMotor(OUT_C,90,-100);  
    RotateMotor(OUT_B,80,-5);
    Off(OUT_B);
    Wait(2000);
    RotateMotor(OUT_A,75,kata_hanten/2); //マイナスで手を閉じる
    RotateMotor(OUT_C,50,50);
    Wait(1000);
    hold_down;
    RotateMotor(OUT_C,50,50);
    RotateMotor(OUT_A,75,-kata_hanten);
    ResetTachoCount(OUT_ABC);
 }
上記のプログラムで横に置かれたカップを掴み、保持腕に積み上げるプログラム。


*結果考察と感想 [#m7f01fc5]
結果は残念ながらカップを1個保持腕にもっていくことしか出来なかった。主にセンサーに関する認識が不足していたことによるプログラミングの遅れが原因である。
また、コードも含めた機体全体に負荷をかけ過ぎる設計になっていたのも要因の一つだ。
時間を取れなかったのは自分たちの責任にしても、もう少し余裕とパーツの安定性が欲しかった。
ただ、プログラミングの雰囲気や機械製品の不安定さを知ることが出来たのは大きな収穫であった。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS