*課題2 ライントレース [#xa509c93]
#ref(./IMG_3166.JPG)

**目的 [#abbfa31a]

B地点からA地点へ行くロボットを制作する

**ロボットの特徴 [#ua0bc0d8]

-前に大きなアームを付けることで、ボールを挟んで目的地に運ぶことにした。
-左右の車輪を直径の小さいものを使用し、カーブにうまく対応できるようにした。
-後輪の部分を固定し、ゴムの部分を外すことで滑りを良くし、動作の不確定さを軽減した。

**プログラム [#y5dfc267]

 #define Black 36
 #define White 56
 #define Get_Time 1 //検知の間隔
 
 int SPD = 0;
 int SPD_Rev = 0;
 int LineTrace = 0;
 int CNT = 0;
 int Limit_R = 0;
 int Limit_L = 0;
 int Tracetime = 0;
 
 ///////////////////////////// サブルーチン //////////////////////////////////
 
 //アームを動かす
 
 sub Arm(int SWD){				//SWDの数値ででアームの上下運動を決定 する
 	RotateMotor(OUT_A,SWD,170);
 	Wait(800);
 	Off(OUT_A);
 }
 
 
 //前進する
 	
 sub Foward(int Fdist){
 	RotateMotor(OUT_BC,100,Fdist);
 }
 
 
 //超信地旋回
 
 sub Turn_Point(int Tdist){
 	RotateMotorEx(OUT_BC,-70,Tdist,100,true,true);
 }
 
 
 //超信地旋回(逆)
 
 sub Turn_Point2(int Tdist2){
 	RotateMotorEx(OUT_BC,-70,Tdist2,-100,true,true);
 }
 
 
 //ボールを放つ
 
 void Shot(){
 	Arm(-50);
 	Foward(300);
 }
 
 
 //ライントレース(時間制御)
 
 sub Line_trace_0(int Tracetime){
 
 	CNT=0;
 
 	SetSensorLight(S3);
 
 	if(LineTrace==0){SPD=80;SPD_Rev=-80;}
 	if(LineTrace==1){SPD=80;SPD_Rev=-80;}
 	if(LineTrace==2){SPD=-80;SPD_Rev=80;}
 	if(LineTrace==3){SPD=80;SPD_Rev=-80;}
 
 	while(Tracetime > CNT){
 		if( SENSOR_3 < Black ) {
 			OnFwd(OUT_B,SPD);OnFwd(OUT_C,SPD_Rev);
 		} else if( SENSOR_3 > White ) {
 			OnFwd(OUT_C,SPD);OnFwd(OUT_B,SPD_Rev);
 		} else {
 			OnFwd(OUT_BC,70);
 		}
 	Float(OUT_BC);
 	CNT++;
 	}
 	LineTrace++;
 	NumOut(80,LCD_LINE1,LineTrace);
 }
 
 
 //ライントレース(カウント制御)
 
 void Line_trace_1(){
 
 	CNT=0;
 
 	SetSensorLight(S3);
 
 	if (LineTrace==1){Limit_R = 200;Limit_L = -1000;SPD = 80;SPD_Rev = -70;}
 	if (LineTrace==3){Limit_R = 100;Limit_L = -2000;SPD = -80;SPD_Rev = 70;}
 
 	while(Limit_L < CNT && CNT < Limit_R){
 		if( SENSOR_3 < Black ) {
 			if(CNT < 0){CNT = 0;}
 			OnFwd(OUT_B,SPD);OnFwd(OUT_C,SPD_Rev);
 			CNT++;
 		} else if( SENSOR_3 > White ) {
 			OnFwd(OUT_C,SPD);OnFwd(OUT_B,SPD_Rev);
 			if(CNT > 0){CNT = 0;}
 			CNT--;
 		} else {
 			OnFwd(OUT_BC,70);
 			CNT = 0;
 		}
 	Wait(Get_Time);
 	Float(OUT_BC);
 	NumOut(80,LCD_LINE1,LineTrace);
 	}
 }
 
 ////////////////////////////////     プログラム開始       ///////////////////////////////////
 
 
 task main() {
 
 	Line_trace_0(6000);
 	Line_trace_1();
 	PlayTone(880,30);	//分岐点に到達
 	Wait(2000);
 
 	Foward(250);
 	Line_trace_0(7000);
 	PlayTone(1320,30);	//ボールを回収
 	Arm(50);
 	Turn_Point(80);
 
 	Line_trace_0(9000);
 	Line_trace_1();
 	PlayTone(880,30);	//分岐点に到達
 	Wait(2000);
 
 	Turn_Point2(100);
 	Line_trace_0(12000);
 	PlayTone(1320,40);	//ゴール前に到達
 	Shot();
 }

-ライントレースの設定を、黒白のとき曲がり、灰色のときを直進するようにした。何段階もしきい値を設定するよりも、シンプルにする方がうまくいった。
-サブルーチンに2種類のライントレースの命令を用意した。一つは、時間が経つにつれてカウントが増えていき、指定した値になるまでひたすらライントレースする。もう一つは、ある一定時間同じ色(黒or白)を検知したとき、その場所を分岐点と判断するライントレースである。こうすることで、S字カーブや分岐点判断しずらい部分をうまく突破できる。
-車輪との幅が大きすぎるので、カーブのときは左右の車輪を逆回転させることで、うまく曲がるようにした。
-ラインの右側をトレースするのか、左側をトレースするのかで大きくライントレースの難易度が変わることが分かったので、分岐点などで左右を反転しながら進むようにした。

**感想・反省 [#u64f3f72]
今回の課題は本当に難しく、プログラムの書き換えが何度も行われたり、電池の減りが早く、入れ替えによって何度も設定した値を直さないといけない事態が発生した。これでOnFwdの不正確さにあきあきし、RotateMotorの有用性を改めて実感した。カウンタ系も電池に大きく影響を受けるので注意が必要だった。ラインの右側、左側を選ぶかでライントレースが成功するか大きく分かれることを知り、ライントレースは見た目は簡単そうなのに一筋縄ではいかないことを思い知った。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS