[[2018a/Member]]
#contents
*最終課題概要 [#fcf3161c]
**フィールドの説明 [#k2f1a3c4]
#ref(2018a-mission3.jpg)~
---フィールドは課題2で使用した紙を使用する。~
---2種類の空き缶(Aタイプ,Bタイプ)をそれぞれ3個づつ用意し、円XにABA、円YにBABとなるように3段づつ積み上げる。~
---空き缶には色をつけたり文字や記号を書いてもよい。あるいは周囲に紙を張ってもよい。~
**基本ルール [#v2a0c558]
-競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。~
-図のA地点またはA'地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする。上空部分は領域からはみ出していてもよい。~
-タイプの空き缶を円Y内に、Bタイプの空き缶を円X内に運ぶ。~
-開始の合図から5秒以内にスタートボタンを押す作業を完了すること。~
-競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。~
-途中でうまく動かなくなった場合、1回限り再スタートすることができる。~
-得点は基本得点(運んだ缶の数や位置)と技術得点(採点者による評価)で決定される。~
*ロボットの概要 [#q8fb5a6c]
今回の課題に対しては二台のロボットを使用し、それぞれに特定の役割を与えることにした。また二台のロボットはBluetooth通信を用いて連携させた。
**Master側のロボット [#q686ed47]
Master側のロボットは三段に積まれた缶の二段目を挟み、固定する役割を担った。~
機体は三輪式を採用している。また、缶を掴むところの機構はギアを三枚使用し、掴む部分は役割的に固定した状態で少し強めの力に対応できるようアームを二重にした。~
フィールド上の動きは光センサーや超音波センサーなどを使わず缶からの距離、移動の距離を実測し、動きをプログラミングした。
#ref(Image_9407a88.jpg)~
**Slave側のロボット [#zae350a9]
Slave側のロボットは一段目、三段目の缶を挟み運ぶ役割をした。~
機体を製作する上でMaster側と同じような三輪式を作ってみると、取り付けたアームが一缶目を掴むことができなかった。また、パーツを駆使して低い位置にアームを取り付けると機体が不安定になってしまった。さらには三段目を掴むために一段目と連動して動く縦に長いアームを取り付ける必要があったため、三段目の缶用のアームに強い力を与えなくてはいけなく、アームを開閉する機構の基礎をきっちり固定させるには本体に直接アームを付ける必要があった。~
#ref(一段目が掴めない図)、#ref(アームが不安定な図)~
そのため下図のようになるべく本体をボタンの付いている方を下向きにし、その側面にタイヤを付ける形で地面すれすれにした。これによって思い通りの位置にアームを付けることができた。しかし、これでは自分でプログラムを起動させるのに一度持ち上げなければいけなくとても不便になってしまった。よって、こちらの機体はMaster側からの信号受信によって動き出すようにプログラムを組むことになった。~
#ref(Image_c53db42.jpg)
*プログラム概要 [#md0db707]
**二つの機体をつなげるプログラム [#w8261459]
二つの機体にはそれぞれの役割があると先でも説明した。そのため機体同士が自分勝手に動いてしまっては缶を思い通りには掴めない。~
なので、Master側が缶を掴んだ後Slave側を移動させ缶を掴ませるという様にお互いがメッセージを送り合い連携した。
***MasterからのメッセージでSlaveが動くプログラム [#qded6849]
-Master側~
task main()
{
SendRemoteNumber(1,MAILBOX1,11); //Slave側のMAILBOX1に11という文字を送る
}
-Slave側~
task main()
{
int msg,frg1=1;
while(frg1){
ReceiveRemoteNumber(MAILBOX1,true,msg); // MAILBOX1の値を受け取りmsgに格納
if(msg==11){ //もしmsgにある数字が11ならば下の命令を行う
(命令);
frg1=0;
}
}
}
***SlaveからのメッセージでMasterが動くプログラム [#lb95b03a]
-Slave側~
task main()
{
SendResponseNumber(MAILBOX1,12); //Master側のMAILBOX1に12という文字を送る
}
-Master側~
task main()
{
int msg,frg1=1;
while(frg1){
ReceiveRemoteNumber(MAILBOX1,true,msg); // MAILBOX1の値を受け取りmsgに格納
if(msg==12){ //もしmsgにある数字が12ならば下の命令を行う
(動かしたい命令);
frg1=0;
}
}
}
**プログラムの定義 [#iaddc74e]
Master側、Slave側それぞれで以下のようにプログラムを定義した。~
-Master側~
#define kail OnFwd(OUT_B,50);OnRev(OUT_C,50);Wait(500);Off(OUT_BC); //左旋回を0.5秒間行う
#define kair OnFwd(OUT_C,50);OnRev(OUT_B,50);Wait(500);Off(OUT_BC); //右旋回を0.5秒間行う
-Slave側~
#define SPEED_H 30
#define SPEED_L 35
#define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);
#define go_forward OnRL(SPEED_H, SPEED_H); // 前進
#define Back(X) OnRev(OUT_BC,30);Wait(X);Off(OUT_BC);//後退
#define turn_rt(X) OnRL(SPEED_L, -SPEED_L);Wait(X);Off(OUT_BC); // 右旋回
#define turn_right(X) OnRL(SPEED_L, 0);Wait(X);Off(OUT_BC); // 右折
#define turn_left(X) OnRL(0, SPEED_L);Wait(X);Off(OUT_BC); // 左折
#define turn_lt(X) OnRL(-SPEED_L, SPEED_L);Wait(X);Off(OUT_BC); // 左旋回
**サブルーチンを用いてのプログラム [#gf850175]
前進、後退など一部動作はMaster側のみサブルーチンを使い組んだ。
-前進するプログラム~
sub zen(int i)
{
int t;
t=i*50;
OnFwd(OUT_B,50); OnFwd(OUT_C,49);
Wait(t);
Off(OUT_BC);
}
~
sub zeny(int i)
{
int t;
t=i*100;
OnFwd(OUT_B,25); OnFwd(OUT_C,25);
Wait(t);
Off(OUT_BC);
}
-後退するプログラム~
sub kou(int i)
{
int t;
t=i*50;
OnRev(OUT_B,50);OnRev(OUT_C,49);
Wait(t);
Off(OUT_BC);
}
-缶を掴むプログラム~
sub armc()
{
OnFwd(OUT_A,30);
}
-缶を離すプログラム~
sub armo()
{
OnRev(OUT_A,30);
}
**プログラムの完成 [#p0681c32]
完成したプログラムは以下のようになった。連携は一方が動いている最中、もう一方は停止しているため実際にはそれぞれ一つになっているが停止し動く方が変わるところでMaster側とSlave側で交互に表示する。
-Masterが�,侶佻�を移動
task main()
{
int msg,frg1=1,frg2=1; //関数frg1,frg2を定義
zen(51); //2.55秒、50%の速さで前進
kair; //0.5秒右旋回
zen(75); //3.75秒、50%の速さで前進
kair; //0.5秒右旋回
zeny(20); //2秒、25%の速さで前進
armc(); //二段目の缶を掴む Xに移動完了
SendRemoteNumber(1,MAILBOX1,11);//送信 //Slave側に11の数字を送信(一旦停止)
-Slaveが�△侶佻�を移動
task main()
{
int msg,frg1=1,frg2=1;
while(frg1){
ReceiveRemoteNumber(MAILBOX1,true,msg); //MAILBOX1の値を受け取りmsgに格納
if(msg==11){
SetSensorLowspeed(S1); //缶の方向を探した後、近づいて10cm手前で停止
int d = searchDirection(120);
if (d > 10) {
fwdDist(d-10.0);
}
str(500); //0.5秒前進
Off(OUT_A); //モーターAの電源を切る
str(400); //0.4秒前進
OnRev(OUT_A,30); //一段目と三段目の缶を掴む Xに移動完了
Wait(1000); //1秒待つ
Back(1000); //1秒後退
SendResponseNumber(MAILBOX1,12); //Master側に12の数字を送信(一旦停止)
frg1=0; //関数frg1に0を代入
}
}
-Masterが��の経路を移動
ReceiveRemoteNumber(MAILBOX1,true,msg);//受信
if(msg==12){
armo(); //缶を離す
kou(20); //1秒後退
kair; //0.5秒右旋回
zen(44); //2.2秒、50%の速さで前進
kail; //0.5秒左旋回
zeny(20); //0.5秒、25%の速さで前進
armc(); //二段目の缶を掴む Yに移動完了
frg1=0; //関数frg1に0を代入
SendRemoteNumber(1,MAILBOX1,13); //Slave側に13の数字を送信(一旦停止)
}
}
-Slaveが�い侶佻�を移動
while(frg2){
ReceiveRemoteNumber(MAILBOX1,true,msg); //MAILBOX1の値を受け取りmsgに格納
if(msg==13){
turn_lt(600); //0.6秒左旋回
str(4000); //4秒前進
turn_rt(1000); //1秒右旋回
str(1000); //1秒前進
OnFwd(OUT_A,30); //缶を離す Yに移動完了
Wait(500); //0.5秒待つ
Off(OUT_A); //モーターAの電源を切る
Back(1000); //1秒後退
turn_rt(800); //0.8秒右旋回
str(500); //0.5秒前進
turn_lt(1000); //1秒左旋回
str(2000); //2秒前進
turn_left(1000); //1秒左折
OnRev(OUT_A,30); //一段目と三段目の缶を掴む
Wait(1000); //1秒待つ
Back(1000); //1秒後退
turn_rt(2000); //2秒右旋回
str(4000); //4秒前進
OnFwd(OUT_A,30); //缶を離す
Wait(1000); //1秒待つ
Off(OUT_A); //モーターAの電源を切る
SendResponseNumber(MAILBOX1,14); //Master側に14の数字を送る
frg2=0; //関数frg2に0を代入(完全停止)
}
}
}
-Masterがその場で缶を離す
while(frg2){
ReceiveRemoteNumber(MAILBOX1,true,msg); //43 受信
if(msg==14){
armo(); //缶を離す
frg2=0; //関数frg2に0を代入(完全停止)
}
}
}
#ref(Inked2018a-mission3_LI.jpg)
*まとめ [#d7c33bed]
**結果 [#o76ad397]
結果は一回目は0点、二回目は2点となった。また技術点は平均12.2点で合計が14.2点であった。
**反省 [#teb81a3c]
最終課題では授業初期に教わったdefineによるプログラムの定義、サブルーチンの使用、超音波センサー、Bluetoothによる通信といった様々なプログラミングを使うことができた。しかし上のような点数になってしまったのは微調整不足、電池残量によるモーターの変化、力の伝わり方の知識不足である。また缶を運んでいる最中に滑り落とさないようアームへの工夫、移動の動きを滑らかにすることで移動の振動を減らし、缶を落とさないようにする、といった方法も考えられる。~
しかし、プログラミング構成面での反省点がそんなに挙げられないのは構成技術が進歩したということであろう。完璧にはほど遠いためこれからも改善の余地は多くあるが、プログラミングの知識を学ぶという目標は達成することができた。