センサーを使ったロボットの自律制御
光センサーを使ってみる
光センサーを使う前に、光センサーがどのような値を返してくるのかを知る必要があります。この光センサーは、発光ダイオードが照射した光の反射光を受けて、0から1023までの値を返します。光の反射光が多ければ値は小さく、光の反射光が少なければ値は大きくなります。
光センサーの値を調べるためにはプログラムを作成する必要があります。簡単なプログラム「光センサー値表示」を作成してみました。
※ソースファイルについては、1ページ目でダウンロードしたzipファイルの中の「view」を参照してください。
●view.cから抜粋
============
void tsk0(VP_INT exinf){
while(TRUE){
//モニターを表示する
ecrobot_debug1(ecrobot_get_light_sensor(NXT_PORT_S3),0, 0);
systick_wait_ms(500);
}
ext_tsk();
}
============
このプログラムは、ecrobot_get_light_sensor(NXT_PORT_S3)という関数により、光センサーがつながっている入力ポート3の値を取得して、ecrobot_debug1(引数1,引数2,引数3)という関数で液晶ディスプレイに表示した後、systick_wait_ms(500)という関数により、500ミリ秒待ちます。これらを何度も繰り返すことにより、液晶ディスプレイに500ミリ秒間隔で光センサーの値を表示します。
実際の黒い線と白い場所の値を測ると、黒い線が640前後、白い場所が500前後の値を検出しました。
さて、光センサーがどのような値を返してくるのかがわかったところで、ロボット自身が黒い線を認識しながら走るという「ライントレース」を考えます。前回作成したロボットには、光センサーが1つ付いていました。この光センサーは床の面に向くように取り付けてあり、床面の明るさを知ることができます。
光センサーを使って床面の黒線に沿って走るロボットを作りましょう。今回は単純に光センサーの値が明るかったら右に曲がり、暗かったら左に曲がるというプログラムです。10ミリ秒間隔で、明るさを読み取りながら、黒い線に沿って走ります。なかなかうまく動きました。
※ソースファイルについては、1ページ目でダウンロードしたzipファイルの中の「linetrace」を参照してください。
●linetrace.cから抜粋
============
void tsk0(VP_INT exinf){
while(TRUE){
if(ecrobot_get_light_sensor(NXT_PORT_S3)
//明るいとき
ecrobot_set_motor_speed(NXT_PORT_B, 50);
ecrobot_set_motor_speed(NXT_PORT_C, 0);
}else{
//暗いとき
ecrobot_set_motor_speed(NXT_PORT_B, 0);
ecrobot_set_motor_speed(NXT_PORT_C, 50);
}
systick_wait_ms(10);
}
ext_tsk();
}
============
光センサーの値を表示しながらライントレースをするには?
では、「光センサー値表示」をしながら「ライントレース」をするにはどうしたらいいでしょうか。
同じタスクに「光センサー値表示」の処理と「ライントレース」の処理を入れると、表示をするためのsystick_wait_ms(500)があるた め、大きくラインからはずれてしまいます。逆にsystick_wait_ms(500)をなくすと、画面がチカチカして見にくくなります。
この2つの処理は、やりたいことが異なりますし、その重要性も違います。ライントレースは重要度が高く、この処理がうまく動かないと脱線してしまいま す。逆に光センサーの値を表示することはそれほど重要ではなく、タイミングが少々遅れても問題なさそうです。これらを考慮して、2つのタスクに優先度を付 けて動かしてみましょう。
nxtJSP(μITRON)では、タスクの優先度は、16段階(1~16)あり、値が小さいほど優先して処理されます。
しかし、よく考えてみると、「ライントレース」処理の優先度を高くした場合「ライントレース」より優先度の低い「光センサー値表示」処理は動くことがで きません。逆に「光センサー値表示」処理の優先度を高くすると「ライントレース」処理は動くことができません。
結局のところ、タスク内で閉じたループを作っていると、そのタスクを実行しながら別のタスクを実行するということができないのです。