2024年12月5日
010-1.ロボット競技に役立つEV3センサー入門-第4回「カラーセンサーの反射光モードを使いこなす」
この連載では「教育版レゴマインドストームEV3」を使い、各種センサーをロボット競技に役立てるためのノウハウを紹介していきます。本当に役立てるためのには実際に手足を動かすしかありませんので、これを参考に実践してみましょう。なお、使用するプログラミング環境は「教育版EV3ソフトウェア」です。(文/松原拓也)

今回使用するのはEV3用の「カラーセンサー」です。
カラーセンサーには「色」「反射光の強さ」「周辺の光の強さ」という3種類のモードがあります。全部を取り上げるとボリュームがありすぎるので、今回は「反射光」について紹介します。反射光とはLEDを赤色に発光させて、対象物に当てて反射してきた光を測定するというモードのことです。
用意するものは前回と同じモーター1個を使ったロボットです。センサー部分だけ交換します。入力ポート1にカラーセンサーを接続します。

実験用のフィールドを用意します。幅25mm(2.5cm)の黒いラインが描かれたコースです。
さらに今回は競技っぽくするために「お題」を用意します。お題は「ラインの真上にカラーセンサーがある位置でロボットを停止させる」ことです。チャレンジしてみましょう。

最初にカラーセンサーの特性を確認しましょう。
このロボットの場合、カラーセンサーの先端から地面までの距離は4+17=約21mmです。床面に直径32mmのライトの光が当たっています。
◆ カラーセンサーの特性を見える化する

この連載では常に「見える化」することで問題点を解決することをおすすめしています。まずはセンサーの特性を視覚的に確認ましょう。 教育版EV3ソフトウェアを使ってプログラムを作りました(color1.ev3)。
プログラムの処理は2つに分かれます。一つは100mm前進する処理です。
もう一つはカラーセンサーで反射光の強さを測り、液晶ディスプレイにグラフを描く処理です。

では、ここでクイズです。このプログラムを実行するとどのようなグラフが描かれるでしょう? 答えは三択です。
・A:値がハッキリと変化する。
・B:値が少しずつ変化する。
・C:AでもBでもない。
あとで正解を発表しますので、自分の答えを考えておきましょう。

では、プログラムを実行します。
ロボットが100mm(10cm)進んで止まりました。

実行後、液晶ディスプレイにグラフが表示されました。
グラフのX座標がロボットの移動距離です。縮尺は画面の幅が100mmです。Y座標方向がカラーセンサーの測定した反射光の強さです。値の1つぶんが1ピクセルに相当します。
先ほどの三択クイズの正解は「B」に似ているようですが、このグラフには丸みがあるので、ちょっと違います。正解は「C」ということになります。

では、なぜこのグラフには丸みが出ているのでしょうか?
その理由を図にしたものがこちらです。
赤い円がライトの光で、黒い四角形が床面のラインを表しています。ライトの光にラインが重なると反射しなくなり反射の量が落ちます。
円は中心から離れるほど面積が少なくなります。このため、距離に対して光量は比例しません。結果、グラフに丸みが出てしまうのです。

さらにこのグラフを見ると、ラインを通過するタイミングが分かります。
反射光の最高値と最低値の中間が「しきい値」です。 このしきい値と測定値の交差している場所がラインの「白」「黒」の境界です。 グラフに黒線を書き込んでみると、ラインの幅が25mmであることが確認できます。
赤い円はライトが照らしていると思われる範囲です。 測定値の変化が始まる地点を円の中心位置として、そこから白黒の境界までの距離を円の半径と当てはめました。その結果、円の直径は26mmくらいです。 結果として、ライトの直径とラインの幅がほとんど同じのようです。

一つだけ疑問が出てしまいます。
最初の実験ではライトの直径は目測で32mmでしたが、 この実験では26mmでした。6mmほど食い違います。
おそらくライトの光の周辺の数mmは測定されていないようです。 見える化によって、新しい事実が分かりました。
◆ ラインの上に戻る

ここからが本題です。ラインの真上にカラーセンサーがくる位置でロボットを停止させます。
プログラムを考えてみました(color2.ev3)。 本来はカラーセンサーの最大値と最小値を求めてから、中間のしきい値を求めて、線の位置と幅を求めます。ロボットは一度ラインを通過してからバックして戻る必要があります。
ただし、この方法だとプログラムがすごい量になってしまいます。そこで、ここではセンサーの最低値だけを求めます。
最低値が発生した場合、その瞬間のモーターの角度を変数に格納しておきます。これで、指定の位置に戻ることができるようになります。

プログラムを実行してみましょう。
ロボットが100mmほど前進します。途中でロボットはラインを一度通過します。それからバックで戻ってラインの真上で止まりました。成功です。センサーの最低値=黒線の中心であることが確認できました。

ちなみにライントレースロボットを作る場合には図のような位置にカラーセンサー(反射光モード)を配置して、ラインを追従するという方法があります。この場合、ライトの光が当たる白黒の比率が50対50になるように走ります。
センサー1個だけでも作れますが、大きい誤差に対応するにはセンサー2個のほうが確実です。2つセンサーを使う場合にはどちらか片方の値の符号(プラス・マイナス)を反転して使います。
◆ 配列を使ったデータロギング

先ほどのプログラムでは反射光の最低値だけを取り出して、残りの情報をすべて捨てていました。
このまま捨ててしまうのは、もったいないので配列に格納するプログラムを作ってみました(color3.ev3)。配列のデータを読み書きするには「配列操作」ブロックを使います。プログラムが巨大になってしまいましたので、マイブロックを使っています。
データの格納方法は配列のインデックスが移動距離(単位はmm。スタート時は0)です。配列の大きさは100個(インデックスは0~99)。格納には反射光の値0~100を格納します。

プログラムを実行しました。
ロボットが100mm進んで止まります。途中でラインを通過しました。

実行後の様子です。ラインを通過する様子がグラフとして描かれました。
先ほどのプログラムでは走っている最中にグラフを描いていましたが、このプログラムは走り終わったあとにグラフを描いています。センサーの情報は配列に格納されています。
配列の情報を解析すれば、センサーの最高値・最低値・しきい値も算出できます。
ロボット競技にはライントレースの要素がたくさんありますので、この技術を応用してみましょう。
[DOWNLOAD]今回作成したプログラム(教育版EV3ソフトウェア用)
当ブログの内容は、弊社製品の活用に関する参考情報として提供しております。
記載されている情報は、正確性や動作を保証するものではありません。皆さまの創意工夫やアイデアの一助となれば幸いです。