* 課題内容 [#x7565a7e] 半径1m以内にある懐中電灯を探して,懐中電灯にピンポン玉を当てる. ロボットが懐中電灯に接触しない限りどこからピンポン玉をシュートしてもよい. [[課題3>2015a/Mission3]]参照 * 目次 [#hf0ec7bc] #contents * ロボット [#h3034268] 今回の課題3ではピンポン玉を掴む必要がないから,アームはシュートするだけの構造にしてロボットを作った. ** アーム [#w2db835b] &ref(./DSC_0264 (2).JPG,10%); &ref(./DSC_0265 (2).JPG,10%); 出来るだけピンポン玉を真っ直ぐシュートできるようなアームにした. 最初はアームを上げた状態でピンポン玉を乗せておき,シュートするときはアームを下ろすとピンポン玉が転がっていくという仕組みだ.出来るだけ真っ直ぐシュートできるようにした. また,モーターの軸にはクラッチギアを用いている.その上にギアが3つ付いているのは,摩擦を大きくしてアームを上げているときに,アームが下がってしまうのを防ぐためである. ** タイヤ [#v8e2a079] #ref(./DSC_0268 (2).JPG,10%) 左右の前輪をモーターACで動かし,後輪にはキャスターを用いている. ** 光センサー [#te7cae16] #ref(./DSC_0267 (2).JPG,10%) 図はロボットを前から見たところで,光センサーの左右をブロックで挟んでいる. そうすることで,光源を見つけるときに少しずれたところで反応してしまわないようにしている. * プログラム [#qbfe9ce3] ** 定数 [#ibe6508a] EYE・・・センサー3の値をEYEとした. TURN_TIME・・・回転する時間.確実に360°は回転するように一回転するのにかかる時間よりも少し長くなっている. #define EYE SENSOR_3 #define TURN_TIME 360 ** マクロ [#f96cc2b0] low_power・・・回転するスピードが遅い方がライトセンサーを感知しやすい.また,シュートするときもアームの動きが速すぎるとうまくシュートできない. そのため,low_powerでモーターABCのパワーを1とした. right_rotation , left_rotation・・・右回転,左回転をする. pause・・・各動作の間に0.5秒の小休止を入れた. shoot・・・アームを下げシュートする. #define low_power SetPower(OUT_ABC,1); #define right_rotation low_power;OnFwd(OUT_A);OnRev(OUT_C); #define left_rotation low_power;OnFwd(OUT_C);OnRev(OUT_A); #define shoot OnFwd(OUT_B);Wait(14);Off(OUT_B); #define pause Off(OUT_AC);Wait(50); ** グローバル変数 [#m6a2f5bf] サブルーチンでライトセンサーを探すプログラムを定義しているから,その中でも使う変数はグローバル変数としなければならなかった. light_max・・・センサーの値が最も大きくなったときのセンサーの値を代入するための変数. time_max・・・センサーの値が最も大きくなったときの時間を代入するための変数. int light_max; int time_max; ** 光源を探すプログラム [#x0379603] *** タイマー FastTimer(0) [#a52215b1] FastTimer(0)・・・回転するときに秒数を測って,光センサーの値が最も大きくなったときのFasrTimer(0)の時間をtime_maxに代入する. *** サブルーチン search [#s5aa5547] まず光源を探すため右まわりに1周回転する.このときにFastTimer(0)をセットしておく. 最初に設定したlight_maxよりも光センサーの値が大きくなったとき,その値をlight_maxに代入する.その時のFastTimer(0)の値をtime_maxに代入する. この操作をそのつど繰り返すことによって,1周のうちに最も光センサーの値が大きくなったときの値と時間がわかる. 時間がわかれば,右に回転した秒数から最も光センサーの値が大きくなった時間を差し引いた分,逆に左回転すればほぼ正確に光源のある場所を向く. sub search() { light_max = 20; ClearTimer(0); right_rotation; //光源を探すため右に回転する right_rotation; //光源を探すため右に回転する while(FastTimer(0) < turn_time) { //1回転するまで繰り返す if(EYE > light_max) { //光センサーの値がlight_maxよりも大きくなったとき while(FastTimer(0) < turn_time) { //1回転するまで繰り返す if(EYE > light_max) { //光センサーの値がlight_maxよりも大きくなったとき light_max = EYE; //その値を新たなlight_maxとする time_max = FastTimer(0); //その値になった時間をtime_maxとする } } pause; left_rotation; Wait(turn_time - time_max); //(右に回転した時間)―(光センサーの値が最も大きくなった時間)だけ左に回転する Wait(turn_time - time_max); //(右に回転した時間)―(光センサーの値が最も大きくなった時間)だけ左に回転する pause; } ** タスク main [#k3cc8cd1] *** ローカル変数 [#m6c54990] flag・・・while文の条件を(flag == 0)としていて,シュートをするとflagに+1している.シュートをすることでフラグを回収し,ループが終了する. *** main [#daa01855] 最初にサブルーチンsearchで光源を探す.このときに誤差があり光源の方向を向いていないことがあった. そこで前進し,前に進んだあとに光センサーの値がlight_maxよりも一定量増えているときは,光源の方向を向いていると判断してシュート,ループは終わる. light_maxよりも一定量増えていないときは光源からずれていると判断して,進んだ分下がってサブルーチンsearchでもう一度光源を探す.これをシュートするまで繰り返す. task main() { SetSensor(SENSOR_3,SENSOR_LIGHT); int flag = 0; search(); //光源を探す search(); //光源を探す while(flag == 0) { //シュートするまで繰り返し OnFwd(OUT_AC);Wait(100); //前進する while(flag == 0) { //シュートするまで繰り返し OnFwd(OUT_AC);Wait(100); //前進する pause; if(EYE >= light_max + 3) { pause; low_power; shoot; flag ++; } /*進んだあとにセンサーの値がlight_maxよりも3以上増えていたら 少し下がってシュートして,ループ終わり*/ /*進んだあとにセンサーの値がlight_maxよりも3以上増えていたら 少し下がってシュートして,ループ終わり*/ else { OnRev(OUT_AC);Wait(100); pause; search(); } /*進んだあと,light_maxよりも3以上増えていない場合 もう1度光源を探すところから繰り返し*/ /*進んだあと,light_maxよりも3以上増えていない場合 もう1度光源を探すところから繰り返し*/ } Off(OUT_AC); } * まとめと反省 [#h0f1ccbe] 一回判定してから,前進して光源の方向を向いているか確認することで正確性が格段に良くなった. アーム部分のギア比を調節することで,アームの速度を変えた方がよかったように思う.