2012a/MemberOnly/進行状況A

2012a/Member

2012a/A4

2012a/A4/Tnakano

目次

課題2 ライントレースロボット

  • 白の画用紙に書かれた黒い線のコースをトレースするロボットを作成する。

ルール

  • コースは交差点2ヶ所以上、ヘアピンカーブ、直角コーナーそれぞれ1ヶ所以上。
  • 線の幅15〜20mm。
  • ひとりにつき一つ以上のプログラムを作成すること。(コースの逆まわり)

ハードウェア

今回制作したロボットは、ロボット全体をできるだけコンパクトにして、小回りが利くようにした。下図が外観図である。

外観図

工夫した点

工夫した点は、センサーとタイヤの距離をできるだけ狭くしたことである。センサーをタイヤに近づけることでセンサー値の変化に対するタイヤの応答速度が速まり、ヘアピンカーブや直角コーナーをきれいに曲がることができます。

センサーとタイヤの距離について

プログラム

ライントレースについて

ライントレースは精度の違う2種類を使い分けている。 1つ目は、緩やかなカーブや直線を速く走るためのトレースである。センサーを黒から白に動かしたとき、値が約23から63まで変化したことを利用して、その時のセンサー値−23を行うことで0から40まで変化することになる。この値を変数に代入し右(または左)の出力に2倍して代入するとモータへの出力を0〜80%まで、センサー値に応じて連続的に変化させることができる。左(または右)には80−(センサー値−23)を出力することで右の時とは逆の出力を行うことができる。(下図参照)ただしセンサー値−23を行うとき、0より小さくなってしまう時と63より大きくなってしまう時は、正しい計算を行うことができないので、if文を用いて、上限(63)下限(0)を定めている。 もう1つはヘアピンカーブ、直角コーナー、入り口、出口等を曲がるためのトレースである。1つ目のトレースと同様にセンサー値の変化23から63を0から40に変換する。そして、配列を用いて0から40のセンサー値に応じて、モーターの出力を-20から60%まで変化させようとした。そうするとカーブは曲がるが直線がパワー不足で進まなくなってしまった。センサー値が中心の20になったときモータへの出力は、両方20パーセントだが、電池が少なくなったり、2周目になったりすると動かなかった。この失敗から配列を組み替え出力を−20、25、40%の3種類にして走行した。そうすると、動きはぎこちなくなってしまったが、各種カーブも直線も走るようになった。

モータ出力図

プログラムの流れ

基本的に、switch case文をwhile文の永久ループで囲んでプログラムを進めている。交差点や直角コーナー、ヘアピンカーブ等の検出は、nxtのタコメータを使用し、スタートからの距離を測定しながら大まかな検討をつけ、トレースの精度を変えながら走行した。プログラムの重複を避けるため、何度も使うcaseでフラグ変数にカウントしながら、caseの切り替えを行った。

コースについて

コース

上図の順に走行した。ヘアピンも直角もアウトコースから通ったほうが安全だったため、直前の交差点で、アウトコースへトレースを切り替えた。交差点でラインを無視して直進するところやコースのインコースからアウトコースに交代するところ、スピードupするところ、直角コーナー、ヘアピンカーブ等、各ポイントでcaseを変更し走行した。

プログラムリスト

/*****************************************************************/
/*		nxtプログラム kadai2				*/
/*****************************************************************/

//定義文
#define	thr1_dis	400            //交差点1距離
#define	thr3_dis	4900            //交差点3距離
#define	cr1_dis 	5600            //直角コーナー距離
#define	thr4_dis	7200            //交差点4距離
#define	thr5_dis	7700            //交差点5距離
#define	thr6_dis	9000            //交差点6距離

//メイン関数
task main(void){
	unsigned int mode,thr_f=0,cr_f=0,distance_r;
	int power_b[]={
		/*-20,-18,-16,-14,-12,-10,-8,-6,-4,-2,0,2,4,6,8,10,12,14,16,18,20,
		22,24,26,28,30,32,34,36,38,4,42,44,46,48,50,52,54,56,58,60*/
                -20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,25,25,25,25,25,
		25,25,25,25,25,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40
		};
	int power_c[]={
		/*60,58,56,54,52,50,48,46,44,42,40,38,36,34,32,30,28,26,24,22,20,
		18,16,14,12,10,8,6,4,2,0,-2,-4,-6,-8,-10,-12,-14,-16,-18,-20*/
		40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,25,25,25,25,25,
                25,25,25,25,25,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,-20,
		};
	int power;
	unsigned int power_bs,power_cs;
	
	SetSensorLight(IN_3);          //センサーセット

	ResetTachoCount(OUT_B);         //タコメータリセット

	mode=1;                 //初期モードセット

	while(1){
							
		distance_r=MotorTachoCount(OUT_B);

		TextOut(0,LCD_LINE1,"LightSensor =");
		NumOut(85,LCD_LINE1,Sensor(IN_3));            //センサー値表示

		TextOut(0,LCD_LINE2,"TachoCout_R");
		NumOut(0,LCD_LINE3,distance_r);               //距離表示
				
		NumOut(0,LCD_LINE4,mode);                     //case表示

		switch(mode){

			case 1:
				power=Sensor(IN_3)-23;
				if(power<=0){
					power=0;
				}else if(power>=40){
					power=40;
				}
			
				CoastEx(OUT_BC,0);			//モータBCフリー
				OnFwdEx(OUT_C,power_c[power],0);
				OnFwdEx(OUT_B,power_b[power],0);
				Wait(1);
				
				if(distance_r>thr1_dis && thr_f==0){
					mode=2;
				}

				if(distance_r>thr4_dis && thr_f==2){
					mode=2;
				} 
				
				if(distance_r>thr5_dis && thr_f==3){
					mode=6;
				} 

				break;
				
			case 2:
			
				PlayTone(TONE_G4,100);
				RotateMotor(OUT_BC,40,130);		
				
				
				if(thr_f==0){
					mode=3;
					thr_f++;
				}
				
				if(distance_r>thr3_dis && thr_f==1){
					mode=4;
					thr_f++;
				}

				if(distance_r>thr4_dis && thr_f==2){
					mode=1;
					thr_f++;
				}
				
				if(distance_r>thr6_dis && thr_f==3){
					mode=4;
					thr_f++;
				}

				break;
				
			case 3:
				
				power=Sensor(IN_3)-23;
				if(power<=0){
					power=0;
				}else if(power>=40){
					power=40;
				}
				
				power_bs=power*2;
				power_cs=80-power*2;
			
				CoastEx(OUT_BC,0);			//モータBCフリー
				OnFwdEx(OUT_C,power_cs,0);
				OnFwdEx(OUT_B,power_bs,0);
				Wait(1);
				
				if(distance_r>thr3_dis && thr_f==1){
					mode=2;
				} 

				break;
				
			case 4:
				power=Sensor(IN_3)-23;
				if(power<=0){
					power=0;
				}else if(power>=40){
					power=40;
				}
			
				CoastEx(OUT_BC,0);			//モータBCフリー
				OnFwdEx(OUT_C,power_b[power],0);
				OnFwdEx(OUT_B,power_c[power],0);
				Wait(1);
				
				if(distance_r>/*cr1_dis*/5600 && cr_f==0){
					cr_f++;
					mode=5;
				}
				
				break;
			
			case 5:
			
				PlayTone(TONE_G4,100);
				CoastEx(OUT_BC,0);
				RotateMotor(OUT_C,40,150);
				RotateMotor(OUT_BC,40,130);		
				mode=1;
				break;
				
			case 6:
			
				PlayTone(TONE_G4,100);
				CoastEx(OUT_BC,0);
				RotateMotor(OUT_B,40,250);
				RotateMotor(OUT_BC,40,130);		
				mode=7;
				break;
				
			case 7:
				power=Sensor(IN_3)-23;
				if(power<=0){
					power=0;
				}else if(power>=40){
					power=40;
				}
				
				power_bs=power*2;
				power_cs=80-power*2;
			
				CoastEx(OUT_BC,0);			//モータBCフリー
				OnFwdEx(OUT_C,power_bs,0);
				OnFwdEx(OUT_B,power_cs,0);
				Wait(1);
				
				if(distance_r>thr6_dis){
					mode=2;
				} 

				break;
		}
	}
}

反省・感想

今回はライントレースロボットを制作した。コースも最初はシンプルにしたつもりだったが、直角コーナーから交差点までの距離が短すぎて、切り替えに苦労した。また、コースの線が太くなりすぎてしまったため、交差点を横切るときにスピードを上げるだけでは上手く行かなかった。そのためトレースを無視するプログラムを入れなければ上手く走らなかった。トレースの方法を工夫して、スピードを上げることができたのはよかったと思う。次回からはロボコンの準備なので今回の経験を活かして、頑張りたいと思います。


添付ファイル: fileモータ出力図.png 207件 [詳細] fileIMG_0320_a.jpg 202件 [詳細] fileIMG_0321.JPG 218件 [詳細] fileIMG_0318_b.jpg 196件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-08-05 (日) 16:15:00 (2576d)