[[ロボティクス入門ゼミ]]  
#contents
*課題 ライントレースロボット [#oa7cbaec]
黒い線をなぞって周回するロボットを製作する。
&br; ・交差点が2箇所以上。
&br; ・急なヘアピンカーブが1箇所以上。
&br; ・直角に曲がるコーナー(クランク)が1箇所以上。
&br; ・黒い線の幅は15〜20mm程度。
#ref(2012a/A5/ITY/M2/photo/無題.png,wrap)
上記の写真は私たちA5のコース。下半分はなだらかなコースでだが、上半分がヘアピンや、半径が小さいカーブが多いために少し難しいコースになってしまった。
*製作過程 [#r3faba28]
h24/6/1〜6/29 [[2012a/A5/ITY/M2/photo]]
#ref(2012a/A5/ITY/M2/photo/CIMG1577.JPG,wrap)
・アナログセンサ1個、タッチセンサ2個使用。
**・ライントレースの仕組み [#cfa4084d]
#ref(2012a/A5/ITY/M2/photo/無題5.png,wrap)
・黒と感知すると旋回、白と感知すると旋回して蛇行しながら進む。
#ref(2012a/A5/ITY/M2/photo/無題2.png,wrap)
・カーブも蛇行しながらトレースすることができる。
**車体部分 [#y9face06]
#ref(2012a/A5/ITY/M2/photo/CIMG1578.JPG,wrap)
・前回は重心が高くて走行に支障が出たので今回は低重心、コンパクトを目指した。
#ref(2012a/A5/ITY/M2/photo/CIMG1582.JPG,wrap)
・センサの位置をできるだけ車体に近づけた。
***工夫したところ [#r33af6c3]
・低重心、コンパクト化
**結果 [#qb252fa7]
**プログラム [#mf2ad5b3]
***フローチャート [#u15fb6d6]
#ref(2012a/A5/ITY/M2/photo/無題7.png,wrap)
・白黒のしきい置調整用の関数と侵入時に90度回転する関数を使用し、メインルーチンでモータ制御した。
***プログラム [#sdcc1eb3]
 /*		2012/6/22  ITY					*/
 /*		2012a_robo		tore-su6		*/
 
 /*-------------------------------------------------------------------
 				別名定義
 -------------------------------------------------------------------*/
 #define PWM 		80							// PWM(力の大きさ)
 #define PWM_D 		15							// PWM(力の大きさ)
 #define DIF 		6							// 差
 #define ON 		1							// オン
 #define OFF		0							// オフ
 #define TRUN_AC	320								// 90度の回転角度
 #define DEFF_RC	180								// 超信地旋回までの時間
 #define DEFF_LC	100								// 超信地旋回までの時間
 
 /*-------------------------------------------------------------------
 				関数宣言
 -------------------------------------------------------------------*/
 void TURN_R();									// 90度ターン
 void TURN_L();									// 90度ターン
 void MODULATE();								// しきい値調整用の関数
 
 /*-------------------------------------------------------------------
 				グローバル変数
 -------------------------------------------------------------------*/
 int s1_touch,s2_touch,br_light,wh_light;					// タッチセンサ、しきい値の変数宣言
 
 /*-------------------------------------------------------------------
 				メインルーチン
 -------------------------------------------------------------------*/
 task main()
 {
     SetSensorLight(IN_4);							// アナログセンサの宣言
     SetSensorTouch(IN_2);							// タッチセンサの宣言
     SetSensorTouch(IN_1);							// タッチセンサの宣言
     int s_light,diff,abs_diff,aspect,s_avg,r_count,l_count,num_c;		// 変数宣言
     num_c=0,s_light=0,r_count=0,l_count=0;					// 変数の初期化
 
 	MODULATE();								// しきい値調整用の関数
 	s_avg = (br_light+wh_light)/2;						// 白と黒の平均値を取る
 	OnFwd(OUT_AC,80);							// コースに入るために前進
 	Wait(400);								// 0.4秒間前進
 	TURN_R();								// 右に90度旋回
 	while(true){								// ライントレース開始
 	num_c++;								// クランク用のカウンタを回す
 		s_light = Sensor(IN_4);						// アナログセンサの値を取得
 		if((s_light < (s_avg + DIF)) && (s_light > (s_avg - DIF))){	// センサの値が平均値の差(DIF)に入っているとき
 			OnFwd(OUT_AC,PWM);					// 両方のモータを正転させる
 		}
 		else{								// センサの値が平均値の差(DIF)に入っていないとき
 			abs_diff = abs(s_light - s_avg);			// 今のセンサの値と平均値を比較する
 			diff = PWM_D + (50 - abs_diff) + (abs(l_count-r_count)*0.1);// PWM=(初期速度)+(上で比較した値)+(センサが復帰するまでの時間*0.1) 
 			if(diff > 100)diff = 100;				// PWMが100を超えないようにする
 			if(s_light < s_avg){					// センサの値が平均値より小さい時(黒)
 				OnFwd(OUT_C,diff);				// Cのモータを正転
 				if(l_count > DEFF_RC) OnRev(OUT_A,diff/2);	// 復帰モードに入った時、Aのモータを後転(超信地旋回)
 				else Off(OUT_A);				// 復帰モードに入るまで、Aのモータを停止
 				l_count++;					// lのカウンタ開始
 				r_count=0;					// rのカウンタのクリア
 			}
 			else if(s_light > s_avg){				// センサの値が平均値より小さい時(白)
 				OnFwd(OUT_A,diff);				// Aのモータを正転
 				if(r_count > DEFF_RC) OnRev(OUT_C,diff/2);	// 復帰モードに入った時、Cのモータを後転(超信地旋回)
 				else Off(OUT_C);				// 復帰モードに入るまで、Cのモータを停止
 				r_count++;					// rのカウンタ開始
 				l_count=0;					// lのカウンタのクリア
 			}
 		}
 		Wait(1);							// 1ms周期でメインルーチンを回す
 		if(num_c > 20000){						// クランク前にトレースする向きの変更
 			Off(OUT_AC);						// ACのモータの停止
 			OnFwd(OUT_A,diff);					// ACのモータの正転
 			Wait(400);						// 0.4秒待つ
 		}
 		while(num_c > 20000){						// 向きの変更後トレース開始
 			s_light = Sensor(IN_4);					// 以下は上のプログラムの左右を変更したもの
 			if((s_light < (s_avg + DIF)) && (s_light > (s_avg - DIF))){
 				OnFwd(OUT_AC,PWM);
 			}
 			else{
 				abs_diff = abs(s_light - s_avg);
 				diff = PWM_D + (50 - abs_diff) + (abs(l_count-r_count)*0.2);
 				if(diff > 100)diff = 100;
 
 				if(s_light < s_avg){
 					OnFwd(OUT_A,diff);
 					if(l_count > DEFF_LC) OnRev(OUT_C,diff/2);
 					else Off(OUT_C);
 					l_count++;
 					r_count=0;
 				}	
 				else if(s_light > s_avg){
 					OnFwd(OUT_C,diff);
 					if(r_count > DEFF_LC) OnRev(OUT_A,diff/2);
 					else Off(OUT_A);
  					r_count++;
 					l_count=0;
 				}
 			}
 		}
 	}
 }
 
 /*-------------------------------------------------------------------
 				サブルーチン
 -------------------------------------------------------------------*/
 void TURN_R()									// 90度ターン
 {
 	int tako_a=0,tako_c=0;							// 変数宣言
 	ResetScreen();								// LCDの初期化
 	OnFwdSyncEx(OUT_AC,40,-100,RESET_NONE);					// 左右ACのモータを回す
 	while((tako_a < TRUN_AC) && (tako_c < TRUN_AC)){			// 90度回転していないとき
 		tako_a = abs(MotorTachoCount(OUT_A));				// タコメータからモータAの値を取得
 		tako_c = abs(MotorTachoCount(OUT_C));				// タコメータからモータBの値を取得
 		NumOut(10,48,tako_a,0);						// LCDにタコメータ(A)の値を表示
 		NumOut(10,40,tako_c,0);						// LCDにタコメータ(A)の値を表示
 	}
 	Off(OUT_AC);								// モータの停止
 }
 
 void MODULATE()									// しきい値の調整用
 {
     int t_count;								// 変数宣言
     s1_touch=0,s2_touch=0,t_count=0,						// 変数の初期化
      br_light=10,wh_light=60;
 
 	while(s2_touch == OFF){
 		s1_touch = Sensor(IN_2);					// タッチセンサの値を取得
 		s2_touch = Sensor(IN_1);					// タッチセンサの値を取得
 		NumOut(10,60,s1_touch,0);					// LCDにタッチセンサの値を表示
 		NumOut(10,40,s2_touch,0);					// LCDにタッチセンサの値を表示
 		NumOut(30,60,br_light,0);					// LCDに黒のしきい値を表示
 		NumOut(30,40,wh_light,0);					// LCDに白のしきい値を表示
 		if(s1_touch == OFF){						// スイッチ1が押されていないとき
 			t_count = 0;						// カウンタの初期化
 			Off(OUT_AC);						// モータの停止
 		}
 		else if(s1_touch == ON){					// スイッチ1が押されているとき
 			if(t_count < 1000){					// 1秒間押されているか判定
 				t_count++;					// カウンタをまわす
 				br_light = Sensor(IN_4);			// 黒いラインの明るさを取得
 			}
 			else {							// 1以上押されているとき
 				wh_light = Sensor(IN_4);			// 白い部分の明るさを取得
 			}
 		}
 	}
 }

***工夫したところ [#f9d5e0c8]
#ref(2012a/A5/ITY/M2/photo/無題6.png,wrap)
・クランクや、コースを出るところは、あらかじめ時間がたつと左右のトレースを反転するようにしておく。
#ref(2012a/A5/ITY/M2/photo/無題3.png,wrap)
・左右トレースを反転した後、クランクやコースを出るときに、曲がりやすいように超信地旋回に移る時間を変更した。
*反省・感想 [#caeac12f]
#ref(2012a/A5/ITY/M2/photo/無題4.png,wrap)
・写真の赤丸のところで良く脱線していた。クロスラインとRがきつい曲線は成功率が低かったので、ライン検出がうまくできていないと考えられる。また、コースに斑がありそれも影響していると考えられる。
・写真の赤丸のところで良く脱線していた。クロスラインとRがきつい曲線は成功率が低かったので、ライン検出がうまくできていないと考えられる。また、コースの黒色に斑があり、それも影響していると考えられる。
#ref(2012a/A5/ITY/M2/photo/無題1.png,wrap)
&br; ・折りたたんだためコースに穴があいてしまい、誤検出が目立った。
&br; ・精度も悪く走行もぎこちなかったため、センサ1つで走行する難しさを知ったが、発想次第で、簡単にトレースする方法があったりと非常に驚いた。また、電地に影響されないようにするためには、回転数もしっかり計算してプログラムする必要があると感じた。

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