[[2013b/Member]] *ロボット本体の改造点 [#j5e47c63] #ref(トレーサ全体図.jpg) -両輪間の距離をより短くするため、モータの軸が進行方向を向くようにし、傘歯車で回転の向きを変える #(トレーサ輪列.jpg) -補助輪の代わりに重量が寄っているモータの真下に底面が半球状になっている2x2プレートを使用することで摩擦を減らしつつ省スペースで車体後部を支える #ref(トレーサ後輪.jpg) -トレース用光センサをなるべく車軸に近づける(車軸の丁度真ん中に置くと本体を回転させる意味がなくなるので車軸からは少し離す) ~など、ホイールベース部分をほぼ1から組み直した。 *コース分析 [#re7cf377] #ref(ロボテコース説明.png) 自分の担当はコースを右回りする方であった。コース内に2か所ある交差点をそれぞれ2回通過すると暫くは緩やかなライントレースを用いることができるので、2か所の交差点を通過するまでは交差点を通過するごとに変数「Ncros」を1増やし、Ncros=2となったときにトレースのモードを切り替えてNcrosをリセットし、ある時間がたつと再び細かいトレースに切り替わるようプログラムの一部を組んだ。 *プログラム [#u8665364] プログラムを丸ごと作ってから動かして不具合を見つけるという作業には時間を要するため、プログラムの一部を別のファイルで組んでおき、そのファイルを転送して調整し、本体のプログラムに移植するという方法をとった。後述の[sub put_can]などがそれである。 ~また、グローバル関数は一つだけしか定義できないようなので、メイン・サブそれぞれに最低限必要数の独立したインライン関数を定義し、仮想的に複数のグローバル関数を使う状態を作った。 **数値やマクロの定義 [#f78f4501] #define THRESHOLD 43 //閾値43 //(黒線上での測定値が36、白い部分での測定値が51なのでその中間値をとる) #define HP 5 #define MP 2 #define LP 0//以上3行でモータの出力を定義する #define turn_left2 SetPower(OUT_C,HP);OnFwd(OUT_C);//高速左折マクロ #define turn_right2 SetPower(OUT_A,HP);OnFwd(OUT_A);//高速右折マクロ #define turn_left1 SetPower(OUT_C,MP);OnFwd(OUT_C);Off(OUT_A);//中速左折マクロ #define turn_right1 SetPower(OUT_A,MP);OnFwd(OUT_A);Off(OUT_C);//中速右折マクロ #define go_forward SetPower(OUT_AC,MP);OnFwd(OUT_AC);//中速直進マクロ #define turn_left0 SetPower(OUT_C,MP);SetPower(OUT_A,LP);OnFwd(OUT_C);OnRev(OUT_A);//低速左旋回マクロ #define turn_right0 SetPower(OUT_A,MP);SetPower(OUT_C,LP);OnFwd(OUT_A);OnRev(OUT_C);//低速右旋回マクロ #define short_break Off(OUT_AC);Wait(200);//省略可 #define TURN_TIME 18 #define CROS_TIME 80//光センサが交点を横断するのに必要な時間 #define crossing SetPower(OUT_AC,HP);OnFwd(OUT_AC);Wait(CROS_TIME); #define STEP1 3//一回の判断で待つ時間(ざっくりトレース時) #define STEP2 1//一回の判断で待つ時間(細かなトレース時) #define B_CT 5//黒が続く回数(交差点判断)の基準 #define W_CT 5//白が続く回数(直角右折地点)の基準 #define TIME11 200 #define TIME12 200 **直線部や緩やかな曲線部などで利用する、非常にざっくりとしたライントレース用サブルーチン [#p09a9b26] sub normal_trace() { int Nwhc=0; while(SENSOR_1==0){ if(Nwhc>W_CT){ClearTimer(0);Nwhc=0;}//白が一定回数以上続くとTimer(0)をリセットする else if(SENSOR_2>THRESHOLD){turn_right2;Nwhc++;}//閾値以上の場合右旋回して白の回数を数え始める else if(SENSOR_2>THRESHOLD-4){turn_left2;Nwhc=0;}// else{turn_left0;Nwhc=0;} Wait(STEP1); } } **きつい曲線部で利用する、細かなライントレース用サブルーチン(コースの形状から、このルーチンにのみ交差点横断機能を付ける) [#ve3cdfe7] sub special_trace() { int TIMER0=800; int Ncros=0; int Nbkc=0; while(SENSOR_1==0){ while(Nbkc<B_CT){//黒が一定以上続くまでライントレースを行う if(SENSOR_2<THRESHOLD-8){turn_left0;Nbkc++;} else{ if(SENSOR_2<THRESHOLD-3){turn_left1;} else if(SENSOR_2<THRESHOLD+3){turn_right1;} else{turn_right0;} Nbkc=0; } Wait(STEP2); } } short_break;turn_right1;Wait(TURN_TIME); crossing;Nbkc=0;Ncros++; if(Ncros>=2){TIMER0=200;Cleartimer(0);Ncros=0;}//メインプログラムではトレースモードの切り替えを時間で管理している(タイマーをリセット後一定の時間がたつと細かなトレースに切り替わる)ため、このコマンドを入れて細かなトレース用ルーチンを終了させる if(Ncros>=2){TIMER0=200;Cleartimer(0);Ncros=0;} //メインプログラムではトレースモードの切り替えを時間で管理している //(タイマーをリセット後一定の時間がたつと細かなトレースに切り替わる)ため、 //このコマンドを入れて細かなトレース用ルーチンを終了させる } **缶を掴んで移動させるためのサブルーチン [#g287acf7] sub put_can() { SetPower(OUT_AC,1);//左右モータの出力を決定 SetPower(OUT_B,1);//缶を把握するためのモータの出力を決定 OnFwd(OUT_B);Wait(100);Off(OUT_B);//モータBを正転し缶を掴む OnFwd(OUT_AC);Wait(130);//適度に前進 OnRev(OUT_A);Wait(100);Off(OUT_AC);//180度旋回 OnRev(OUT_B);Wait(100);Off(OUT_B);//モータBを逆転し缶を放す OnRev(OUT_AC);Wait(80);//缶がアームに当たらなくなるまで後退 OnFwd(OUT_A);Wait(100);Off(OUT_AC);//180度旋回 OnRev(OUT_AC);Wait(80);Off(OUT_AC);//車体後部に缶が当たらないギリギリまで後退し、なるべく本体を缶を移動させる前の位置に近づける OnRev(OUT_AC);Wait(80);Off(OUT_AC); //車体後部に缶が当たらないギリギリまで後退し、 //なるべく本体を缶を移動させる前の位置に近づける } **メインプログラム [#e3850efa] 一応コースのどこに缶を置かれても理論上除かせるようにプログラムを組む。 task main() {//0 SetSensor(SENSOR_1,SENSOR_TOUCH); SetSensor(SENSOR_2,SENSOR_LIGHT); int CLOCK0=800; repeat(2){//1 スタートから2箇所の交差点までをカバー while(FastTimer(0)<CLOCK0){//2 タイマーが境界時間以下の時ざっくりトレース normal_trace(); put_can(); }//2 while(FastTimer(0)>=CLOCK0){//2 タイマーが境界時間以上の時細かなトレース special_trace(); put_can(); }//2 }//1 CreatTimer(1); while(FastTimer(1)<TIME11){//1 normal_trace(); put_can(); }//1 while(FastTimer(1)>=TIME11&&FastTimer(1)<TIME12){//1 special_trace(); put_can(); }//1 While(FastTimer(1)>=TIME12){//1 normal_trace(); put_can(); }//1 }//0