目次
2箇所以上交差点のある周回コース(黒い線)をA0版の画用紙上描き、その自作のコースを3周するロボットを作成せよ。ただし、
今回の課題では,接触時の動作は3秒間停止と360度旋回を選びました.
初めロボットの車体は本に載っていたドライブベースのままだったが,4輪だとカーブが曲がりにくく,スムーズに動いてくれなかった.そこで,後輪2輪を無くし,代わりに車体後部に自由に動く車輪を付けることで3輪の車体を作った.また,この車輪を付けるにあたってドライブベースの骨組み部分の黒い長いパーツの長さを短くし,その上にもう1つ同じパーツをずらして取り付け1段上がった部分に後輪を付けた.この後輪も本の通りではなく小さいタイヤを使用して高さを合わせ,さらに取り付け方もシンプルかつ確実な方法に変えた.
また,初めはダブルバンパーの取り付け部分を避けその両側にセンサーを取り付けていたが,センサーの間隔が広く車体の左右の振れ幅が大きかった.そのため,初めはダブルバンパーの取り付け部分の位置を変え,ダブルバンパーを高くしその下にセンサーを付けることでセンサーの幅を縮めようとしたが欲しい材料が足りず断念.結局,ダブルバンパーの下部のパーツを1つ外しそこに光センサーを付けるというシンプルな方法に落ち着いた.
また,バンパーにダブルバンパーを用いたのは,横からの接触に対応するためである.2つのタッチセンサーからのコードを重ねて取り付けることでどちらのタッチセンサーが反応しても出力が得られると聞き,その方法をとった.
しかし,タイヤが小さいため速度が遅いがその割にコースアウトが多く,センサーの取り付け位置が広いといって1マス分取り付け位置をずらすと逆に狭すぎてコースアウトしやすくなってしまった.また,左右のタイヤとタイヤの間隔が広いため旋回半径が大きくなり,急なカーブを曲がれないのも影響していると思われる.この点はプログラムを変えてもなかなか直すことができなかった.ギヤを変えたりタイヤを変えたりしてスピードアップを図り,旋回速度を縮めようとしたが,逆にコースアウトしやすくなってしまった.
1代目の課題点を踏まえ,車体から新しく作り替えた.まず,それまで開いていた左右のモーターとモーターの間のスペースを無くし,モーター同士がぴったりとくっつくような形の車体に変更した.こうすることで左右のモーターの間隔をかなり縮めることができた.基本はドライブベースの設計を参考にしているが,モーターをくっつける形にしたため車体の前から後ろまであったベースのブロックを入れることができず,他のパーツを組み合わせて耐久力を上げた.また,駆動輪とキャスターはどちらも大きいものを使用し,スピードアップとスムーズな旋回を目指した. しかし実際に走らせてみると左右のモーターの速度差が大きく,直進と一時停止後の動作に影響があった.モーターを入れ替え原因がモーターかRCXかを確かめたところ,今度は逆の方向に曲がったためモーターが原因とわかった.この問題は遅い方のモーターを余っていたもう1つのモーターに変えることで解決した.さらに,センサーの幅の問題を解決するため,スライド式の機構を追加した.
#define WHOLE_NOTE 100 #define HALF_NOTE ( WHOLE_NOTE / 2 ) #define QUARTER_NOTE ( WHOLE_NOTE / 4 ) #define EIGHTH_NOTE ( WHOLE_NOTE / 8 ) #define SIXTEENTH_NOTE ( WHOLE_NOTE / 16 ) task play_music() { while(true) { PlayTone( 293, HALF_NOTE ); //メヌエット Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 261, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 329, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 261, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 329, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 369, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 391, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 261, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 261, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 261, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 184, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, WHOLE_NOTE ); Wait( WHOLE_NOTE ); PlayTone( 293, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 261, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 329, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 261, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 329, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 369, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 391, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 261, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 261, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 261, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 184, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, WHOLE_NOTE ); Wait( WHOLE_NOTE ); PlayTone( 493, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 391, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 440, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 493, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 391, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 440, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 329, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 369, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 391, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 329, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 369, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 391, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 277, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 277, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 277, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 329, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 369, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 391, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 369, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 329, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 369, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 220, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 277, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 293, WHOLE_NOTE ); Wait( WHOLE_NOTE ); PlayTone( 293, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 184, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 329, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 184, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 261, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 246, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 184, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 146, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 164, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 184, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 220, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 261, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 246, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 220, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 246, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 293, QUARTER_NOTE ); Wait( QUARTER_NOTE ); PlayTone( 195, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 184, HALF_NOTE ); Wait( HALF_NOTE ); PlayTone( 195, WHOLE_NOTE ); Wait( WHOLE_NOTE ); } }
ピアノパネルを使ったため早く完成させることができたが,プログラミングが長くなってしまった.
#define THRESHOLD 40 //光センサーの感度設定 #define RUN_TIME 800 //走行時間 sub linetrace() { SetSensor(SENSOR_1,SENSOR_LIGHT); //センサ1とセンサ3は光センサ SetSensor(SENSOR_3,SENSOR_LIGHT); if ((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD)) //センサ1とセンサ3が白紙上 { OnFwd(OUT_A+OUT_C); //直進 } if ((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)) //センサ1とセンサ3が黒線上 { Off(OUT_A+OUT_C); //一時停止 Wait(50); OnFwd(OUT_A+OUT_C); Wait(50); } if ((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)) //センサ1が黒線上,センサ3が白紙上 { Off(OUT_A); //左旋回 OnFwd(OUT_C); } if ((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD)) //センサー1が白紙上,センサー3が黒線上 { OnFwd(OUT_A); //右旋回 Off(OUT_C); } } task main () { SetSensor(SENSOR_2,SENSOR_TOUCH); //センサ2はタッチセンサ ClearTimer(0); //走行時間タイマリセット start play_music; //音楽を流す while(Timer(0) <= RUN_TIME) //タイマが走行時間内のとき { if (SENSOR_2 == 0) //タッチセンサが反応しないとき { linetrace(); //ライントレース } else { //タッチセンサが反応したとき OnRev(OUT_A+OUT_C); //後ろに下がる Wait(30); Off(OUT_A+OUT_C); //一時停止 Wait(300); //3秒間 linetrace(); //ライントレース再開 } } stop play_music; //音楽を止める Float(OUT_A+OUT_C); }
task main { SetSensor(SENSOR_2,SENSOR_TOUCH); //センサ2はタッチセンサ ClearTimer(0); //走行時間タイマリセット start play_music; //音楽を流す while(Timer(0)<= RUN_TIME) { if (sensor_2==0) { linetrace(); }else { OnRev(OUT_A+OUT_C); wait(20); OnRev(OUT_A) OnFwd(OUT_C) wait(60); linetrace(); } stop play_music; //音楽を止める Float(OUT_A+OUT_C); }
2つの光センサで黒線を挟み込むようにしてトレースするロボットにしたため,センサ1とセンサ3が両方白紙上にあるときは直進し,センサ1が白紙上でセンサ3が黒線上のとき右旋回し,その逆のときは左旋回し,両方のセンサが黒線上のとき交差点と見なして一時停止するようにした.また,タイマーを用いてコースを大体3周回ったところで止まるようにした.モーターの回転数が左右で異なっていたことと,コースの事情からいつも決まった場所でコースアウトしてしまったため,SetPowerを用いてモーター出力の微妙な差を調整しようとしたがほとんど効果がなかった.そのため,これは車体を改良することで解決し,プログラムは基本に忠実なシンプルなものに仕上げた.
#define THRESHOLD 40 //光センサーの感度設定 int i; int i_min=0,i_max=9; sub linetrace() { SetSensor(SENSOR_1,SENSOR_LIGHT); //センサ1とセンサ3は光センサ SetSensor(SENSOR_3,SENSOR_LIGHT); if ((SENSOR_1>THRESHOLD)&&(SENSOR_3>THRESHOLD)) //センサ1とセンサ3が白紙上 { OnFwd(OUT_A+OUT_C); //直進 } if ((SENSOR_1<THRESHOLD)&&(SENSOR_3<THRESHOLD)) //センサ1とセンサ3が黒線上 { i=i+1; Off(OUT_A+OUT_C); Wait(50); OnFwd(OUT_A+OUT_C); Wait(50); } if ((SENSOR_1<THRESHOLD)&&(SENSOR_3>THRESHOLD)) //センサ1が黒線上,センサ3が白紙上 { Off(OUT_A); //左旋回 OnFwd(OUT_C); } if ((SENSOR_1>THRESHOLD)&&(SENSOR_3<THRESHOLD)) //センサー1が白紙上,センサー3が黒線上 { OnFwd(OUT_A); //右旋回 Off(OUT_C); } } task main () { SetSensor(SENSOR_2,SENSOR_TOUCH); //センサ2はタッチセンサ start play_music; //音楽を流す for(i=i_min; i<=i_max;.) { if (SENSOR_2 == 0) //タッチセンサが反応しないとき { linetrace(); //ライントレース } else { //タッチセンサが反応したとき OnRev(OUT_A+OUT_C); //後ろに下がる Wait(30); Off(OUT_A+OUT_C); //一時停止 Wait(300); OnFwd(OUT_A+OUT_C); Wait(30); linetrace(); //ライントレース再開 } } stop play_music; //音楽を止める Float(OUT_A+OUT_C); }
上記の接触後3秒間停止のライントレースプログラムを,より正確にコース3周で停止するようにしたプログラム.コースには交差点が3カ所あるため,交差点で一時停止を行うたびに変数iの値を1づつ増加させていき,値が9になったとき,つまり交差点を9回通過したときに停止するようにした.こうすることで,途中で他のロボットと衝突するなどのタイムロスがあっても確実にコースを3周するようになった.
*個人制作ページです
ライントレースはよくロボット作りの一番の入門に使われ,仕組みも簡単ですが,コースを実際に造り走らせてみると思わぬトラブルがたくさん発生し,解決していくのが大変でした.簡単な仕組みだからこそ,動作がロボットの作り方やプログラムの組み方に影響されやすく,各チームのオリジナリティが出るのだと思います.最終的になんとかコースを3周できるようになりましたが,思っていた以上に大変でした.
左右で性能の異なるモーターを使用しなければならず苦労しました。コースを三周できた時は本当にうれしかった。ヒコ
コメントをどうぞ