- 追加された行はこの色です。
- 削除された行はこの色です。
[[2019a/Member]]
目次
#contents
*課題について [#n09c5be2]
次のようなコースを作ります。
#ref(2019a-mission3.png)
そして、4つのボールを空の弁当箱に集めます。
詳しくは[[2019a/Mission3]]を参照してください。
*基本的な作戦 [#jf8b7958]
1つのつかむ機構では、床のボールと弁当箱に入っているボールの両方を回収することはできないと考えました。
もともとは、1つのアームに2のつかむ機構を搭載し、ボールを4つ回収できるようなロボットを作成しました。
もともとは、1つのアームに2つのつかむ機構を搭載し、ボールを4つ回収できるようなロボットを作成しました。
しかし、アームが重すぎて上がらなくなってしまったことで、アームを作り直す必要が出てきてしまい、プログラムにかけられる時間が少なくなってきてしまったことから、床に置いてあるボールを諦め、点数の高い弁当箱に入っている2つのボールを確実に回収できるようなロボットを目指しました。
*ロボットの本体の説明 [#y99352ff]
#ref(IMG_4909.jpg)
ロボットの全体図
弁当箱の形に合わせて作られたアームで、しっかりとつかむことができます。
NXTのコアを2つ用いて、Bluetoothで接続しています。
マスター側には、ラインセンサー1つとモーター2つが接続しており、ライントレースを行います。
スレーブ側には、モーターが3つ接続しており、アームの動作を担っています。
移動を担っているNXTとアームの動作を担っているNXTが独立しているので、移動しながらアームの上げ下げも行うことができます。
このことによって、アームの動作が終わっていないのに、ロボットが移動するプログラムが始まってしまったとしても問題ないことになります。
#ref(IMG_5014.jpg)
二輪駆動で移動します。
タイヤの少し前にラインセンサが付いており、モーターが回り、ロボットが移動したときに、適度にラインセンサが動き、地面の状況を調べることができます。
#ref(IMG_4997.jpg)
弁当箱を持ち上げ、中に入っているボールをレールを伝わせて、ボール収納スペースに入れます。
#ref(IMG_5015.jpg)
ボール収納スペースに入っているところ。
#ref(./IMG_5016.jpg)
ストッパーでボールが出てくるのを止めています。
#ref(IMG_4927.jpg)
坂になっているので、ストッパーをあげると、自動的にボールが出てきます。
#ref(IMG_5017.jpg)
モーターに高いギヤ比をかけることで、大きなパワーを出すことができ、重いアームを持ち上げることができるようになりました。
#ref(IMG_4952.jpg)
アームを開閉させるためのモーターをギヤによってアームの先まで力を伝導させています。
#ref(IMG_4948.jpg)
ボールをつかむためのアーム
フェースギアを用い、モーターの回転軸を90度回転させることで、ボールをつかむためのアームを製作しました。
フェースギアを用い、モーターの回転軸を90度回転させることで、弁当箱をつかむためのアームを製作しました。
*プログラムの説明 [#l0b5f21e]
#ref(1.png)
図のように進んで行きます。
ボールが入っている弁当箱の目の前までは、ライントレースで行きます。
ボールを回収した後は、そのまま空の弁当箱の前まで行き、ボールを入れます。
#ref(2.png)
ラインセンサの値は、黒のときが30くらいで、白のときが60くらいです。
そのため、白と黒の境の値をを40として、図のように、白のときは左に進み、黒のときは右に進みます。
交差点では、いつもより黒の上を進む時間が長い(右に進む時間が長い)ので、それを変数Aを用いて判断しました。
右に進んでいるときは、Aの値が増え続け、右に進むとAは0になります。
右に進んでいるときは、Aの値が増え続け、左に進むとAは0になります。
Aの値が一定の値(400)以上になったときに、交差点にいると判断して、1秒間停止します。
void re_stop_corner(){
SetSensorLight(S1);
while(A<400){
if(SENSOR_1>40){
hidari;
A=0;
B=B+1;
}else{
migi;
A=A+1;
B=B+1;
}
}
}
tomaru;
Wait(1000);
B=0;
}//交差点で止まるライントレース(ラインの右側を進む)
交差点を直進するプログラムと交差点で止まるプログラムがセットで組み合わせます。
ライントレースをしている時間を計測するために変数Bを用います。
ライントレースをしている間はBの値が増え続けます。
一定の値になり、一定の時間が経過したことがわかると、交差点を直進するプログラムから交差点で停止するプログラムに変わります。
while(B<8000){
re_cross_line();//交差点を直進するライントレース(ラインの右側を進む)
}
while(B>=8000){
re_stop_corner();
}//交差点で止まるライントレース(ラインの右側を進む)
#ref(3.png)
弁当箱の前に移動するときに、アームが弁当箱にあたり、弁当箱がどこかに行ってしまうことがあったので、上の図のように移動して解決しました。
また、スタートのときにはアームを上に上げておき、途中で下げるようにもしました。
マスター側
#define CONN 1
#define on1 1
#define on2 2
#define on3 3
#define zenshin OnFwd(OUT_BC,60); //前進
#define koushin OnFwd(OUT_BC,-60); //後進
#define migikaiten OnFwd(OUT_B,-70);OnFwd(OUT_C,40); //右回転
#define hidarikaiten OnFwd(OUT_B,40);OnFwd(OUT_C,-70); //左回転
#define migi OnFwd(OUT_C,40);Off(OUT_B);//右に進む
#define hidari OnFwd(OUT_B,40);Off(OUT_C); //左に進む
#define tomaru Off(OUT_BC); //ストップ
long A=0;//ライン上を連続して進んでいる時間を計測する変数
long B=0;//ライントレースしている時間を計測する変数
void re_stop_corner(){
SetSensorLight(S1);
while(A<400){
if(SENSOR_1>40){
hidari;
A=0;
B=B+1;
}else{
migi;
A=A+1;
B=B+1;
}
}
tomaru;
Wait(1000);
B=0;
}//交差点で止まるライントレース(ラインの右側を進む)
void re_cross_line(){
SetSensorLight(S1);
if(SENSOR_1>40){
hidari;
B=B+1;
}else{
migi;
B=B+1;
}
}//交差点を直進するライントレース(ラインの右側を進む)
task main()
{
SetSensorLight(S1);
while(B<8000){
re_cross_line();//交差点を直進するライントレース(ラインの右側を進む)
}
while(B>=8000){
re_stop_corner();
}//交差点で止まるライントレース(ラインの右側を進む)
tomaru;
Wait(500);
koushin;
Wait(1600);
migi;
Wait(300);
zenshin;
Wait(1300);
migikaiten;
Wait(1300);
tomaru;
Wait(100);
koushin;
Wait(300);
tomaru;
Wait(100);
zenshin;
Wait(300);
tomaru;
Wait(100);//弁当箱をつかむために、向きを変えるための動作
SendRemoteNumber(CONN,MAILBOX1,on2);
Wait(18000);//アームを下げる動作
zenshin;
Wait(300);
tomaru;
Wait(100);//前進して、弁当箱の目の前に移動する動作
Wait(100);//前進して、弁当箱の目の前に移動する動作ーこの動作により、しっかりと弁当箱をつかむことができる
SendRemoteNumber(CONN,MAILBOX1,on1);
Wait(30000);//弁当箱をつかみ、アームを上げ、下げて、放す動作
OnFwd(OUT_B,50);OnFwd(OUT_C,-80); //少し強く左回転
Wait(400);
tomaru;
Wait(100);
koushin;
Wait(1500);
tomaru;
Wait(100);//空の弁当箱の前に移動する動作
SendRemoteNumber(CONN,MAILBOX1,on3);
Wait(1000);//ストッパーを上げて、回収したボールを空の弁当箱の中に入れる動作
tomaru;
Wait(100);
}
スレーブ側
#define on1 1
#define on2 2
#define on3 3
#define tomaru Off(OUT_AB);Wait(100);//ストップ
task main()
{
int msg1;
int msg2;
while(1){
ReceiveRemoteNumber(MAILBOX1,true,msg1);
if(msg1==on1){
OnFwd(OUT_B,50);
Wait(1500);//弁当箱をつかむ動作
tomaru;
OnFwd(OUT_A,-100);
Wait(20000); //アームを上げる動作
OnFwd(OUT_A,100);
Wait(20000);//アームを下げる動作
tomaru;
OnFwd(OUT_B,-50);
Wait(1500);//弁当箱を放す動作
tomaru;//弁当箱をつかみ、アームを上げ、下げて、放す動作
msg1=100;//msg1に1,2,3以外の関係ない数を代入し、if文の外に出る
}
}
if(msg1==on2){
OnFwd(OUT_A,100);
Wait(20000);//アームを下げる動作
msg1=100;//msg1に1,2,3以外の関係ない数を代入し、if文の外に出る
}
if(msg1==on3){
OnFwd(OUT_C,-30);
Wait(200);//ストッパーをあげる動作
msg1=100;//msg1に1,2,3以外の関係ない数を代入し、if文の外に出る
}
}
}
*難しかったところ [#q17bbad3]
#ref(IMG_4955.jpg)
機体が重いので、キャスター1つでは、バランスを崩す可能性がありました。
そのため、小さな車輪をつけたのですが、そうすると回転移動のときに引っかかってしまい、きちんと回転移動ができずに、毎回移動距離が変わってしまいました。
そのため、プログラムが大変になってしまいました。