#contents *Mission2 [#w8255cd2] **課題について [#v855df8d] 今回の課題はライントレースロボットの作成である。光センサーによる閾値の識別を利用して次のコースをトレースしながら進むようにする。&br;&ref(2017a/Member/kyo/Mission2/2017a-mission2.png,60%);&br;経路や道中のアクションなど様々なルールがあるため詳しくは[[2017a/Mission2]]を参照していただきたい。&br;今回はA→F→Q→R→S→G→H→T→R→S→P→E→Aの順で通過していく。 **目標 [#a96430c4] 課題に臨むにあたって今回はプログラムをより簡単にするということを目標にした。前回の課題1ではサブルーチンや引数をあまり使うことができなかったので今回はそれらを使っていければと思い臨んだ。 *ロボット [#z8d5ac24] 今回は機体の大きさに制限があり、より小さくより機敏に動けることが望まれた。結果として次のようなロボットとなった。&br;&ref(2017a/Member/kyo/Mission2/IMG_0687_640.JPG,55%);&ref(2017a/Member/kyo/Mission2/IMG_0688_640.JPG,60%);&br;タイヤをセンサーに近づけることにより車体の動きがコンパクトになるようにした。&br;&ref(2017a/Member/kyo/Mission2/IMG_0689_640.JPG,55%); &br;タイヤは二輪だけにして、後輪のかわりに円盤状の部品を用いることで滑りながら移動できるようになり機動性を損なわずサイズを縮小することができた。三点で支えることにより安定した動作が可能となり旋回や左折など滑らかに動かすことができ満足のいくものとなった。また、写真では分かりづらいと思うが光センサーをなるべく低くして紙面に近づけた結果、作業場所による感度の違いが少なくなったように感じた。 *プログラム [#r931b424] 今回のプログラムはライントレースとカウントを利用した。&br; これらについて説明していきたいと思う。 **グローバル変数 [#c94c8e38] int n=0;//カウント &br;サブルーチン、メインプログラム、マクロの全てにカウントを用いるため、nをカウント数としてグローバル変数に定義した。&br;このカウントは次のような役割がある。 &br; �.薀ぅ鵐肇譟璽� &br; ↓ &br; ��曲がり角だと判別(左旋回を一定時間(今回は25秒)以上おこなったので);ライントレースを停止 &br; ��曲がり角だと判別(左旋回を一定時間(今回は0.25秒)以上おこなったので);ライントレースを停止 &br; ↓ &br; ��カウントを+1(F地点の場合n=0→n=1、Q地点ならばn=1→n=2) &br; ↓ &br; ��n=1,2....になったときのアクション(対応のアクションはサブルーチンの項目を参照) &br;以上のようにカウントを用いることで今回のような何番目の角ではどのような動作を行うか、ということが設定されたコースならうまく動作してくれる。 **定数 [#ee93861d] #define tmax 24//曲がり角を判別するための一般的な定数 #define tmid 26//曲がり角の判別を厳しくする定数 #define senter 42 //白と黒の境界の数値 #define right_turn OnFwd(OUT_A);OnRev(OUT_C);//右旋回 #define right OnFwd(OUT_A);Off(OUT_C);//右回転 #define left OnFwd(OUT_C);Off(OUT_A);//左回転 #define left_turn OnFwd(OUT_C);OnRev(OUT_A);//左旋回 #define teishi(t) Off(OUT_AC);Wait(t);//t秒間停止 #define sound_up PlaySound(SOUND_UP);//サウンドアップ #define sound_down PlaySound(SOUND_DOWN);//サウンドダウン &br;ライントレースについては後で説明するが、それに必要な定数をここで定義している。 &br;加えて音関係の動作やロボットの動作についてのプログラムも多様するため定義することにした。 **マクロ [#e6e7a248] #define line_trase while(FastTimer(0)<tmax){if(SENSOR_2 >senter +13){right_turn;ClearTimer(0);}else if(SENSOR_2 >senter +7){right;ClearTimer(0);}\ else if(SENSOR_2 >senter +0){OnFwd(OUT_AC);ClearTimer(0);}else if(SENSOR_2 >senter -2){left; ClearTimer(0);}\ else{SetPower(OUT_C,0);left_turn;}if(FastTimer(0)>tmax){ClearTimer(0);}}n++;SetPower(OUT_C,7);//黒線の右側をトレースするプログラム #define line_trase_curve while(FastTimer(0)<tmid){if(SENSOR_2 >senter +13){right_turn;ClearTimer(0);}else if(SENSOR_2 >senter +7){right;ClearTimer(0);}\ else if(SENSOR_2 >senter +0){OnFwd(OUT_AC);ClearTimer(0);}else if(SENSOR_2 >senter -1){left; ClearTimer(0);}\ else{left_turn;}if(FastTimer(0)>tmid){ClearTimer(0);}}n++;//曲線でカウントが進まないように直角判断を厳しくしたもの &br;今回はライントレースを多用するためマクロ化した。ライントレースの原理は次のようになる。 &br;�.薀ぅ鵑虜乎次頁鬚塙�の境界)の閾値を測定(定数tmax) &br; ↓ &br;�△發係�センサーが境界の閾値よりも大きな値を計測したら境界より左にあると判断し境界に向かうように右折。反対に境界の閾値よりも小さな値を計測すると境界より右にあると判断し左折。&br; ↓ &br;���△魴�り返すことで黒線の左端の境界に沿って進む。 &br;また、左旋回を一定時間以上行うとロボットが曲がり角に差し掛かったと判断しカウントnが+1される。 &br;また、左旋回を一定時間(今回は0.25秒)以上行うとロボットが曲がり角に差し掛かったと判断しカウントnが+1される。 &br;ちなみにマクロをこれほど大きくしてしまうのはあまり良いことではないらしい。なので今後はサブルーチンを上手く用いて見やすいプログラムにしていくように心がけたい。 **各ラインにおけるサブルーチン [#f53c10c8] サブルーチンはすべて次のような構成となっている。 sub line_○○○() { ClearTimer(0);//タイマーをリセット line_trase(_curve);//ライントレース if(n==カウント数){ //カウントに対応したアクション } Off(OUT_AC);//一連の動作を終了 } 以上のように ライントレース→曲がり角でのカウント増加→カウントに対応したアクション→停止 という構成になっており、それらを連続で行うことで ライントレース→アクション→ライントレース→..... とスムーズに動くことが可能となった。 sub line_one()//A〜F,R〜S、S〜G、S〜Pの経路 { ClearTimer(0); line_trase; if((n==1)||(n==4)||(n==5)||(n==11)){//カウントが1または4または5または11になったときサウンドアップ sound_up; } Off(OUT_AC); } sub line_two()//F〜Q、T〜R、S〜Pの経路 { ClearTimer(0); line_trase_curve; if((n==2)||(n==9)||(n==12)){//カウントが2か9か12となったときサウンドダウン→1秒間停止 sound_down teishi(100); } Off(OUT_AC); } sub line_three()//Q〜R、R〜Sの経路 { ClearTimer(0); line_trase; if((n==3)||(n==10));{//カウントが3または10になったとき サウンドアップ→交差点で横道を無視して直進 sound_up; right;Wait(45); OnFwd(OUT_AC);Wait(20); } Off(OUT_AC); } sub line_four()//H〜T、T〜Tの経路 { ClearTimer(0); line_trase; if((n==7)||(n==8)){//カウントが7または8になったとき サウンドダウン→1秒間停止→交差点で横道を無視して直進 sound_down; teishi(100); right;Wait(45); OnFwd(OUT_AC);Wait(20); } Off(OUT_AC); } sub line_five()//G〜Hの経路 { ClearTimer(0); line_trase_curve; if(n==6){//カウントが6になったとき サウンドアップ sound_up; } Off(OUT_AC); } 基本的な動きはline_oneと同じだが道中で急な曲線があるためカウントの判定を厳しくして道中でカウントが起こらないようにした。 sub line_six()//E〜A { ClearTimer(0); line_trase; if(n==13){//カウントが13になったとき サウンドダウン sound_down; } Off(OUT_AC); } **メインプログラム [#hb91490c] task main() { SetSensor(SENSOR_2, SENSOR_LIGHT); SetPower(OUT_AC,0); line_one();//A〜F line_two();//F〜Q line_three();//Q〜R repeat(2){//R〜G line_one(); } line_five();//G〜H repeat(2){//H〜T〜T line_four(); } line_two();//T〜R line_three();//R〜S line_one();//S〜P line_two();//P〜E line_six();//E〜A } *感想 [#g28ea617] **今回の課題を振り返って [#b040aa4f] 今回の課題では主にプログラムが大きな壁となったと思う。ロボットが反応してくれるような条件を設定するということは思った以上に難しく、他のルーチンなどとおかしな反応をしてしまうことがあったので何度も試行錯誤をすることとなった。最低限の動きはしてくれるようになったが定数を少しいじると動きがおかしくなり、毎回同じ動きをするということが難しかった。改善すべき箇所はやはり曲がり角と交差点の判断をする箇所だと思う。今回の作品は判断とは言いづらいものなので非常に残念である。 しかし目標としたサブルーチンや引数を使用するということは前回よりもできるようになったのではないだろうか。プログラムに纏まりがあり、量も少なく済んだと満足している。 **次回の課題に向けて [#ic4b7335] 次回の課題はいよいよロボコンである。前期で学んだことのすべてを組み合わせなければいけないため非常に大変な課題となるだろう。もっとスムーズに動けばいいと思ったので、今回の課題についてライントレースや条件に注視して今一度プログラミングを見直して改善点を探っていきたいと思う。