今回の課題は紙に引いた黒い線をトレースさせてロボットを進ませるというものである。
B地点をスタートしてA地点へゴールさせるプログラムを組むのだが、
B地点 → P右折 → Q右折 → P左折 → Q左折 → Q直進 → P直進 → A地点
とそれぞれの交差点で指示された方向へ進行させるプログラムを立てることとなった。
ロボットは上の写真の用に組み立てた。運動をさせる前輪はモーターのすぐ近くにつけてある。
センサーは、前輪からあまり距離が発生しないように組んだ。
こうすることにより微調整するときにあまり大きくセンサーが動かないようになった。
#define SPEED 30 //速さ #define go_forward OnFwd(OUT_BC,SPEED); //前進 #define turn_left OnFwd(OUT_B,SPEED);Off(OUT_C); //左折 #define turn_right OnFwd(OUT_C,SPEED);Off(OUT_B); //右折 #define turn_here_L OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED); //左旋回 #define turn_here_R OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED); //右旋回
進む上では前進、左折、右折の3つで事足りるのだが、
より綺麗にトレースさせるために微調整するために左旋回、右旋回を加えた。
#define STEP 50 #define TMAX 150
STEPはライントレースをさせる回数、TMAXは左旋回をする最大の時間。
元々TMAXはもう少し長かったのだが、交差点を間違えて左折することがしばしばあったためこの時間となった。
#define THRESHOLD 40
線の中央、線の境目、白い部分を測定したところ、それぞれ28前後、38前後、55前後であった。
そのため、確実に線の境目と認識できる40を基準にして、閾値をその都度調整することにした。
sub turnL() { turn_here_L; until(SENSOR_3>THRESHOLD+8); turn_left; Wait(500); }
途中直角に曲がる箇所と急カーブがあるのだが、そこを交差点と誤認してしまう。
誤認する箇所はいずれも左折であり、交差点でも左折する箇所があったため予めサブルーチン化させた。
以下のプログラムはtask mainの中にすべて入っているのだが、分けて説明する関係上途中で区切ることにする。
task main() { SetSensorLight(S3); //センサーをつけた位置 long t_left = CurrentTick(); //左旋回にかかる時間を計測するための変数の定義 int n=0; //交差点を通過する回数(但し誤認も含む。)
while(true){ while(CurrentTick()-t_left<TMAX){ if(SENSOR_3<THRESHOLD-10){ turn_here_L; }else if(SENSOR_3<THRESHOLD-5){ turn_left; t_left = CurrentTick(); }else if(SENSOR_3<THRESHOLD){ go_forward; t_left = CurrentTick(); }else if(SENSOR_3<THRESHOLD+8){ turn_right; t_left = CurrentTick(); }else{ turn_here_R; t_left = CurrentTick(); } }
測定した時間がTMAX(=150)を超えない時のプログラム。
閾値の項目で線の中央が28前後、白い部分が55前後という値になったと言った。
線の中央と確実に認識させるために線の中央を30として、線の中央と線の境目との間をそれぞれの値の平均である35、線の境目と白い部分の間をそれぞれの平均である48として、
先ほど定義した閾値をこの値になるように調整した。
左旋回以外は測定時間がリセットされるようにプログラムを立ててある。
if(n<2){ Off(OUT_BC); Wait(1000); turn_right; //交差点を右折 until(SENSOR_3>THRESHOLD+10); n++; t_left = CurrentTick(); }else if(n<5){ turnL(); //直角及び急カーブを左折 n++; t_left = CurrentTick(); }else if(n<7){ Off(OUT_BC); Wait(1000); turnL(); //交差点を左折 n++; t_left = CurrentTick(); }else{ Off(OUT_BC); Wait(1000); turn_right; //交差点を直進 Wait(580); t_left = CurrentTick(); } }
交差点に到達した時のプログラム。
交差点を右折する長さを閾値で指定してあるが、間違って白い部分と認識しないように先程より少し高めに設定。
直角や急カーブの内側をトレースされる関係上どうしてもこれらを交差点と誤認してしまうため、
交差点と誤認する3,4,5回目は、交差点を左折するプログラムと別のプログラムを立てた。
Wait(STEP); }
今回の課題は、色の濃さの測定だけでなくタイマーやカウンターと言った様々な関数を使用したため、途中でわからなくなることがあった。
また、条件文を多用したため中括弧を入力し損ねてプログラムを実行できないといったこともあった。
しかし、そこをクリアできると思いの外実行させたい動きをしてくれたので、プログラムの改良はやりやすかった。