TakasakiPhysicsClub-RoboCup-Documentation

著者:根岸孝次

ロボカップでアウトオブバウンズを防ぐために必須なラインセンサの原理、作り方をまとめました。

物体の色が見える仕組み

私たちの目に映る物体の色は、光の反射によって生まれます。この原理を理解することは、ラインセンサの仕組みを理解する基礎となります。

光の反射と色の関係

白色光(太陽光や蛍光灯など)には、赤(R)、緑(G)、青(B)の3原色が含まれています。物体に白色光が当たると、物体の性質によって特定の色の光だけが反射され、その他の色は吸収されます。 以下のような反射の特徴があります。

出典:https://d2u1z1lopyfwlx.cloudfront.net/thumbnails/ab28ae92-0b58-5152-9852-df79e765d10e/4c6a6ffa-d96c-59d8-8f04-b51ed2860a62.jpg

センサへの応用

この色の原理は、カラーセンサの設計に直接応用されています。カラーセンサは人間の目と同じように、物体から反射された光のRGB成分を検出します。 具体的には、

  1. センサが白色光を物体に照射します
  2. 物体から反射された光をRGB各色に分けて検出します
  3. 各色の反射量の比率から物体の色を判定します3

このような原理を応用することで、ラインセンサは移動する物体の色情報を正確に読み取ることができます。 img|445

出典:https://www.rohm.co.jp/documents/11401/7457285/img_01.jpg/b89a1cdf-9013-331c-aa29-bd8f21574fd1?t=1576203765973

ロボカップで使うLEDの色

ロボカップサッカーではコートの緑色と白線が区別できれば十分です。上述のような様々な色を見分けられる必要は無く、このセンサを実装するのは過剰です。(サッカーコートのゴールの色は距離が遠すぎるのでこの方式のカラーセンサでは認識できません。カメラを利用してください。)

我々が作るラインセンサは緑色と白色が区別できれば十分だとわかりました。では、そのためにもっとも効果的な方法を考えましょう。例えば、緑色が0(LOW)で、白色が1(HIGH)になったら嬉しいのではないでしょうか?以下ではそうなるようにセンサを考えてみます。

白色はすべての色を反射します。基本的にどんな色を照射しても強く反射されるのでセンサは1(HIGH)を得ます。一方、緑色は緑色を一番強く反射し、赤色と青色を吸収してしまいます。色相環を見れば緑色の捕食が赤色になっていることがわかります。つまり、例えば赤色を照射してあげれば0(LOW)となると考えられます。 img|293

出典:https://zokeifile.musabi.ac.jp/%E8%89%B2%E7%9B%B8%E7%92%B0/

※「○」は反射する。「✕」は吸収する。

実際にロボカップのラインセンサでは赤色光をコートに照射しその反射光の強さを測定することでコート上にいるのかライン上にいるのか判別します。青色も良さそうに思えますがおすすめできません。ロボカップサッカーでは一方のコートの色として青色が採用されており、ロボットに青色の部分があることが許されていないためです。 また、コートに照射して反射された光が減衰したり、ロボットの外に漏れてしまわないようにLEDとセンサは地面すれすれにつけます。(あまりに地面すれすれにするのは良くないのは言うまでもありません。)

フォトトランジスタについて

先ほどから光の強度を測定するとずっと言っていますが、センサについて何も解説していなかったのでここで解説します。ラインセンサにはフォトトランジスタを利用します。 img|179

出典:https://akizukidenshi.com/img/goods/L/127315.jpg

基本構造と動作原理

フォトトランジスタは、光を電気信号に変換する半導体素子で、フォトダイオードとトランジスタを組み合わせた構造を持っています。

光電流の発生と増幅

特性と性能

回路での使用方法

一般的な使用例として

ラインセンサの概観

回路

この資料で扱う部品構成は以下のとおりです。真似する場合には参考にしてください。

※補足 上位に食い込みたいなら大事かも 原理の説明の際に、白色でHIGH、緑色でLOWと説明したのでデジタル入力を使用すれば判別できるはずである。しかし、LEDやフォトトランジスタ、環境の影響で緑色でもHIGHになったり、逆に白色でもLOWとなってしまうことが多々ある。この場合、デジタル入力では判別でいないのでアナログ入力を使うことになる。そこで問題になってくるのがアナログ入力数である。強いチームではフォトトランジスタを1台あたり30個とか使う。(私達のチームでは32個使っていました。かなり多い方。)一方、マイコンのアナログ入力できるピン数は多くても10とかである。そこで、アナログマルチプレクサというものが必要になる。

アナログマルチプレクサとは、複数のアナログ信号を1つのアナログ入力で読むためのICである。(本来の用途がこれなのかは知らないがロボカップではこのように使う。アナログ出力でも利用できそうだが使ったことは無い。)アナログマルチプレクサには、主に以下のピンが生えている。

実際に私達が使用したアナログマルチプレクサはCD74HC4067です。Amazonでモジュールで販売されていたやつをハンダごてで熱して外して自分たちの基板に取り付けていました。digikeyなどで部品単体として販売されているのでそれを買ってもいいのですが、Amazonのやつは異様に安かったのでこっちを使いました。偽物説もかなり濃厚ですが動いているのでこれを使っていました。

補足終わり

LED部分

Neopixel

img Neopixelには4つの端子があります。上の画像は回路CADでのシンボルです。

フォトトランジスタ

img フォトトランジスタの画像をよく見ると、長い足と短い足がある。見た目がLEDと非常にそっくり。長い足を Corrector 、短い足を Emitter と呼ぶ。まあ、LEDと同じで順に +, - だと思ってもらって問題ない。 img 回路CADでつないだ様子。電源として 3.3V を使用しているが、これはマイコンの電源電圧がが3.3V であるためであり、5Vのマイコンを使用している場合には5Vでも構わない。回路をよく見ると、Emitterと抵抗の間の配線名がL4となっていると思う。反射光の強度がここの電圧に反映されるので、ここをアナログ入力(デジタル入力でも良い)で監視する。(名前がL4であることに深い意味は無い。)以下のように複数作って、別々に監視してやるのが良い。 img

(補足)アナログマルチプレクサ

勢い余ってアナログマルチプレクサを紹介してしまったので解説します。 img 上の画像はCD74HC4067のデータシートに掲載されているピンマップです。

プログラム

アナログマルチプレクサを使用しない場合

以下のようなコードを書いてあげれば良いと思います。Neopixelの光らせかたは自分で調べてください。難しくないので。わからなかったら聞いて。

#include <Arduino.h>

const int LINESENSOR_NUM = 5; //フォトトランジスタの個数、こういうの大事
const int LINESENSOR_PIN[LINESENSOR_NUM] = {A0, A1, A2, A3, A4}; //各センサのピン

void setup() {
	Serial.begin(115200) //シリアル通信を開始、デバッグ用
}

void loop() {
	int sensorValues[LINESENSOR_NUM]; //結果を格納する配列
	for (int i = 0; i < LINESENSOR_NUM; i++) {
		sensorValues[i] = analogRead(LINESENSOR_PIN[i]); //アナログ入力で読む
	}

	for (int i = 0; i < LINESENSOR_NUM; i++) {
		Serial.print(sensorValues[i]); //結果を出力、改行しない
		Serial.print("\t"); //値と値の間にtabを入れるとスペースと異なりきれいに出力できる
	}
	Serial.print("\n") //改行も忘れずに

	delay(1000);
}

各フォトトランジスタにスマホのLEDととかをかざしてみると値が変化すると思います。変化しなかったらなにか問題があると思います。コート上で白線上を行ったり来たりさせて値の変化を観察しましょう。ライン上にいるかどうかのしきい値はなんとなくで大丈夫だと思います。

(補足)アナログマルチプレクサを使用する場合

#include <Arduino.h>

const int LINESENSOR_NUM = 16; //フォトトランジスタの個数、こういうの大事
const int COM_PIN = A0; //COMピン
const int SELECT_PIN[4] = {D5, D6, D7, D8} //選択ピン、番号は適当

void setup() {
	Serial.begin(115200) //シリアル通信を開始、デバッグ用

	for (int i = 0; i < 4; i++) {
		pinMode(SELECT_PIN[i], OUTPUT);
	}
}

void loop() {
	int sensorValues[LINESENSOR_NUM]; //結果を格納する配列
	for (int i = 0; i < LINESENSOR_NUM; i++) {
		for (int j = 0; j < 4; j++) {
			digitalWrite(SELECT_PIN[j], (i >> j) & 1);
		}
		sensorValues[i] = analogRead(COM_PIN);
	}

	for (int i = 0; i < LINESENSOR_NUM; i++) {
		Serial.print(sensorValues[i]); //結果を出力、改行しない
		Serial.print("\t"); //値と値の間にtabを入れるとスペースと異なりきれいに出力できる
	}
	Serial.print("\n") //改行も忘れずに

	delay(1000);
}

ビット演算をうまく活用すると選択ピンの出力を簡単に変更できるのでおすすめです。アナログマルチプレクサを使うならある程度自分で何でもできないといけないと思うので特に解説しません。

補足事項

色々補足があってごめんなさい。最後にエンジェルリングといういものを軽く紹介します。 img|354 エンジェルリングとはラインセンサを円形に配置したものをさします。円形にラインセンサを配置することで、機体が踏んでいる白線の位置や角度を計算することができます。使い方によっては自己位置推定にも少しつながります。ただ、大量のラインセンサが必要となるのでアナログマルチプレクサは必須になると思いいます。加えて、コートの隅の角やゴールエリアの白線の角などでは処理がかなり難しくなります。この欠点を補うために機体の前後左右の端に独立したラインセンサを4つ付けて、それらとエンジェルリングを組み合わせてより高度なライン処理を行っているチームもあります。余裕があれば調べてみたりすると良いと思います。円形ボールセンサの計算方法も参考にできると思います。

おすすめサイト