先ず地面が白い場合と黒い場合で赤外線反射センサの値がどのように変化するかを確認します。
GCC Developer Liteを起動し、以下を入力します。
#include <fd.h> #define KEY_QUIT { if(fd_rx_buff()) fd_SoftReset();} void main (void) { uint8_t ReadData; fd_Init (0, BT_CONSOLE, FD_BEEP_MMI | FD_BEEP_PACKETERR | FD_BEEP_LOWVOLTAGE | FD_BEEP_BOOTUP, 7.4); fd_DXSetEndlessTurn (1, 1); fd_DXSetEndlessTurn (2, 1); while (1) { fd_DXReadByteData (100, 28, &ReadData); fd_printf ("%3d\r", RightData); KEY_QUIT; } }
fd_DXSetEndlessTurnでエンドレスターンの設定、fd_DXReadByteDataで赤外線反射センサの値を取得、fd_printfで表示します。
ここまでは前章と同じです。プログラムを書き込んで実行してみましょう。
如何でしょうか?
おそらく赤外線反射センサを白い地面の上に置いても、黒い地面の上に置いても値は255と表示されるでしょう。
地面との距離が近過ぎて、地面が白くても黒くても最大値の255になってしまいます。
それではセンサを地面から15cmくらい離してみてください。
白い地面の上にいる時と黒い地面の上にいる時で値が変わるのが分かるでしょうか?
ならばセンサを地上から15cm離した位置に固定すれば良いということになりますが、キリンのように首が長いロボットを作るのは大変ですし、バランスも悪いです。
先ず赤外線反射センサの原理を説明します。
AX-S1を見ると3方向にそれぞれ2つの丸い物が並んで付いています。その2つの丸いものを良く見ると片方は黒く、片方は透明です。
黒い方から赤外線が照射されます。照射された赤外線は直進し、その先に物体があると反射します。
反射して戻ってきた赤外線の量を透明の方が測定します。
これによって、対象との距離や色を判別します。
この測定された赤外線の量を0~255の値に変換した値を、今私たちは見ています。
跳ね返ってくる赤外線の量が多すぎて飽和してしまっているのであれば、照射する赤外線の量を減らせば良いのです。 物理的に赤外線照射部を隠すのが一番簡単でしょう。
黒いビニールテープで少しだけ隙間残して赤外線照射部を隠しました。
どれくらい隠すかは、赤外線反射センサの値を見ながら調節してください。
上図の場合、白い地面では約120、黒い地面では約20という値になりました。
これで白い地面の上にいるか、黒い地面の上にいるかを判断することができるようになりました。
ライントレースは黒いラインに沿って進みます。
それを実現するために、最初は赤外線反射センサが黒いラインの上にあり、もし白い地面の上に来たら黒いラインへ戻るようにタイヤを動かせば良い、という発想がおそらく最初に浮かぶでしょう。
図のように黒いラインから右に外れたら左へ、左に外れたら右へ進めば良いのですが、右に外れたか左に外れたかをどうやって判断すれば良いでしょうか?
赤外線反射センサ1つでは不可能でしょう。 勿論2つあれば可能ですが、今回はどうにか1つでライントレースをしたいです。
赤外線反射センサ1つでライントレースをする方法としては、「黒いラインをトレース」するのではなく、「黒と白の境界線をトレース」すれば良いのです。 例えば左側の白い地面は忘れ、黒いラインの右側の境界線をトレースするとします。
図のように地面が白い時は左に、黒い時は右に進むことで黒と白の境界線をトレースすることができます。
Chapter1から進んできた方ならプログラムの作成はもう簡単でしょう。
そうでない方はChapter8を先に読まれることをお勧めします。
if (ReadData < 70) { fd_DXWriteWordData (1, 32, 0); fd_DXWriteWordData (2, 32, 400); } else { fd_DXWriteWordData (1, 32, (1 << 10) + 400); fd_DXWriteWordData (2, 32, 0); }
while文の中に上記を入力します。
もしセンサの値が50未満(地面が黒)なら左のタイヤだけを回転させ右へ、それ以外(地面が白)なら右のタイヤだけを回転させ左へ進みます。
以上でプログラムは完成です。
#include <fd.h> #define KEY_QUIT { if(fd_rx_buff()) fd_SoftReset();} void main (void) { uint8_t ReadData; fd_Init (0, BT_CONSOLE, FD_BEEP_MMI | FD_BEEP_PACKETERR | FD_BEEP_LOWVOLTAGE | FD_BEEP_BOOTUP, 7.4); fd_DXSetEndlessTurn (1, 1); fd_DXSetEndlessTurn (2, 1); while (1) { fd_DXReadByteData (100, 28, &ReadData); fd_printf ("%3d\r", ReadData); if (ReadData < 70) { fd_DXWriteWordData (1, 32, 0); fd_DXWriteWordData (2, 32, 400); } else { fd_DXWriteWordData (1, 32, (1 << 10) + 400); fd_DXWriteWordData (2, 32, 0); } KEY_QUIT; } }
ムービーではスピードを速く設定しています。