#contents *課題内容 [#g6c199ec] 今回の課題は自立型ロボットを用いて二か所の紙コップの中にある二つのボールの位置を入れ替えるというものである。この際、二つある空の紙コップを用いることができる。 *ロボット本体 [#b5cdd40c] **コンセプト [#m059c531] ボールの移動するときに、空の紙コップを使わないで済むように、ロボット本体に4つボールを格納できるようにし、順次二つずつ降ろすことで入れ替えられるようにする。 **完成品 [#rbb6f1d7] コンセプト通りの機構を作ることができた。この機構のおかげで、位置さえ合えばボールを二つ確実に入れられるようになった。 &ref(./1423658987925.jpg,100%);&ref(./1423658989038.jpg,100%);&ref(./1423658977120.jpg,100%); &ref(./1423658982987.jpg,100%);&ref(./1423658981273.jpg,100%); アーム部は掴む部分を長くすることで、アームをそのまま持ち上げることで高い位置に格納できるようになった。 #ref(./1423658995152.jpg,100%) *プログラム [#j4a127c7] **コンセプト [#ze362640] 機構の特性上、移動する回数は少ないので、ある程度の距離まで直進信号で近づき、超音波センサで位置を確定し、近づき、取る・降ろす動作をするようなプログラムにする。 **完成品 [#s31247f3] 製作途中までは良かったのだが、ロボットが完成したあと、超音波センサの値が安定しなくなってしまった。そのためコンセプトのようなプログラムを使用することができず、人の手の微調整が必要なポログラムになってしまった 製作途中までは良かったのだが、ロボットが完成したあと、超音波センサの値が安定しなくなってしまった。そのためコンセプトのようなプログラムを使用することができず、人の手の微調整が必要なプログラムになってしまった。 **プログラム内容(マスター側) [#s7550c86] -関数やサブルーチンを用いて、距離・角度を引数とするプログラムにして、分かりやすくなるようにした。 -サーボモーターの機能を使うことで、電池残量の影響を受けないようにした。 本体側のNXTではタイヤとボールを降ろす機構のモータを制御する。 #define CONN 1 #define SIGNALON 1 #define OPEN_SPEED 15 #define OPEN OnFwd(OUT_A,OPEN_SPEED);Wait(800);Off(OUT_A); #define CLOSE OnRev(OUT_A,OPEN_SPEED);Wait(1300);Off(OUT_A); #define SPEED_H 70 #define SPEED_L 50 const float diameter = 5.6; //タイヤの直径(�僉� const float track = 10.5; //タイヤのトレッド幅(�僉� const float pi = 3.1415; //円周率 float GetAngle_turn(float a) //求める本体の回転角からタイヤの回転角を求める関数 { float ang = (a*track)/diameter; return ang; } float GetAngle_go(float a) //求める移動距離からタイヤの回転角を求める関数 { float ang = a/(diameter*pi)*360.0; return ang; } sub angle_turn_L(float t) //左にt度回転 { int angle_turn_L = GetAngle_turn(t); RotateMotorEx(OUT_BC,SPEED_H,angle_turn_L,-100,true,true);//P37 Off(OUT_BC); } sub angle_turn_R(float t) //右にt度回転 { int angle_turn_R = GetAngle_turn(t); RotateMotorEx(OUT_BC,SPEED_H,angle_turn_R,100,true,true);//P37 Off(OUT_BC); } sub dist_go_F(float t) //前にtセンチ進む { int angle_go_F = GetAngle_go(t); RotateMotorEx(OUT_BC,SPEED_H,angle_go_F,0,true,true); Off(OUT_BC); } sub dist_go_R(float t) //後ろにtセンチ進む { int angle_go_R = GetAngle_go(t); RotateMotorEx(OUT_BC,-SPEED_H,angle_go_R,0,true,true); Off(OUT_BC); } task main() { dist_go_F(57.0); //コップを取るボール搭載の信号を送る SendRemoteNumber(CONN, MAILBOX1, SIGNALON); Wait(9000); angle_turn_R(150.0); dist_go_F(40.0); //コップを取るボール搭載の信号を送る SendRemoteNumber(CONN, MAILBOX1, SIGNALON); Wait(9000); //反転して dist_go_R(5.0); angle_turn_R(190.0); dist_go_R(20.0); //ボールを置く OPEN; Wait(1000); CLOSE; dist_go_F(50.0); //反転して dist_go_R(20.0); angle_turn_R(220.0); //コップまで近づく dist_go_R(33.0); //ボールを置く信号を送る OPEN; Wait(1000); CLOSE; //離れる dist_go_F(20.0); } **プログラム内容(スレーブ側) [#y89872fa] スレーブ側のNXTではアームの開閉や昇降を制御する #define SIGNALON 1 #define ARM_TIME1 1000 //アームの開閉時間1 #define ARM_TIME2 2000 //アームの開閉時間2 #define ARM_SPEED1 10 //アームの開閉スピード1 #define ARM_SPEED2 50 //アームの開閉スピード2 #define UP_TIME 2000 //アームを上げる時間 #define UP_SPEED 50 //アームを上げるスピード #define DOWN_TIME 1800 //アームを下げる時間 #define DOWN_SPEED 20 //アームを下げるスピード task main() { int msg; //受け取った値を格納する変数 while(true){ ReceiveRemoteNumber(MAILBOX1, true, msg); //MAILBOX1の値を受け取りmsgに格納 if(msg==SIGNALON){ OnFwd(OUT_C,DOWN_SPEED);Wait(DOWN_TIME);Off(OUT_C); //アームを下げる OnRev(OUT_B,ARM_SPEED2);Wait(ARM_TIME2);Off(OUT_B); //アームを閉じる OnRev(OUT_C,UP_SPEED);OnRev(OUT_B,ARM_SPEED2);Wait(UP_TIME);Off(OUT_C);Off(OUT_B); //アームを上げる OnFwd(OUT_C,DOWN_SPEED);Wait(DOWN_TIME);Off(OUT_C); //アームを下げる OnFwd(OUT_B,ARM_SPEED1);Wait(ARM_TIME1);Off(OUT_B); //アームを開く ARM_UP2 OnRev(OUT_C,UP_SPEED);Wait(450);Off(OUT_C); //アームを定位置に戻す }else{ Off(OUT_BC); } } } *反省・考察 [#k4163363] #ref(./1423658973030.jpg,100%) 良い機構を作ることができた。しかし、組上りは少し無理がかさんでいるように思えた。 超音波センサの数値が安定しない理由を解明し、改善するまでに至る事ができなかった。 センサの取り付け位置や、センサの前まで飛び出た機構が、安定した数値を取れなかった原因ではないかと考えられる センサの取り付け位置や、センサの前まで飛び出た機構が、安定した数値を取れなかった原因ではないかと考えられる。 超音波センサを用いた場合、以下のようなプログラムを組み込んでいたが、外さざるを得なくなった 超音波センサを用いた場合、以下のようなプログラムを組み込んでいたが、外さざるを得なくなった。 const float arm = 21.0; //アーム距離 int catch_searchDirection(long ang) //現在の方向を中心にang度の範囲で探し障害物までの距離を返す { long angle, tacho_min=0, tacho_corr; int d_min; d_min = 300; //仮の最小値 angle = (track/diameter)*ang; //旋回角度からタイヤの回転を計算 angle_turn_R(ang/2); //指定された角度の半分を旋回 ResetTachoCount(OUT_BC); //角度計測をリセット OnFwdSync(OUT_BC, SPEED_L, -100); //半時計回りに旋回 while(MotorTachoCount(OUT_B) <= angle){ if(SensorUS(S4) < d_min){ d_min = SensorUS(S4); //仮の最小値を更新 tacho_min = MotorTachoCount(OUT_B); } } OnFwdSyncEx(OUT_BC, SPEED_L, 100, RESET_NONE); until(MotorTachoCount(OUT_B)<=tacho_min||SensorUS(S4)<=d_min); Off(OUT_BC); Wait(500); return d_min; } task main() { SetSensorLowspeed(S2); SetSensorLowspeed(S4); int d; //センサとの距離変数 //方向を探したあと、腕の長さ前で停止 d = catch_searchDirection(120.0); dist_go_R(arm-d); }