目次
今回制作したロボットは、ロボット全体をできるだけコンパクトにして、小回りが利くようにした。下図が外観図である。
工夫した点は、センサーとタイヤの距離をできるだけ狭くしたことである。センサーをタイヤに近づけることでセンサー値の変化に対するタイヤの応答速度が速まり、ヘアピンカーブや直角コーナーをきれいに曲がることができます。
ライントレースは精度の違う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; } } }
今回はライントレースロボットを制作した。コースも最初はシンプルにしたつもりだったが、直角コーナーから交差点までの距離が短すぎて、切り替えに苦労した。また、コースの線が太くなりすぎてしまったため、交差点を横切るときにスピードを上げるだけでは上手く行かなかった。そのためトレースを無視するプログラムを入れなければ上手く走らなかった。トレースの方法を工夫して、スピードを上げることができたのはよかったと思う。次回からはロボコンの準備なので今回の経験を活かして、頑張りたいと思います。