前回は超音波センサを使って障害物の回避プログラムを作成しました。
今回は光センサを使って黒い線を読みながら自動で走行するライントレースプログラムを行ってみます。
光センサの概要
皆さんが使っているスマートフォンは、暗い場所に行くと画面が明るくなり、逆に晴れた日の外では画面が暗くなったりします。
これはスマートフォンに内蔵されている「照度センサー」の働きによるものです。
照度センサーは、周囲の明るさを感知して自動で画面の明るさを調整する仕組みを持っています。
今回使用する照度センサーには「フォトトランジスタ」という部品が使われています。
フォトトランジスタは、光に反応する「フォトダイオード」と、微小な電流を増幅する「トランジスタ」を組み合わせたものです。
下の図にあるように、フォトトランジスタは受けた光の明るさに応じて電流を増幅する性質を持っています。
販売元リンク: 照度センサー販売ページ
フォトトランジスタのしくみ
フォトダイオードは光を受けるとわずかな電圧を発生させます。
そしてトランジスタはそのわずかな電圧をもとに、別の電源から大きな電圧を作り出す性質があります。
この2つを組み合わせることで、フォトトランジスタは受ける光の明るさに応じて大きな電圧を生じさせることができます。
これにより、周囲の明るさに応じた信号を作り出すことができます。
照度センサー(フォトトランジスター) 550nm NJL7302L-F5
LEDを使った回路の仕組み
今回の回路では、フォトトランジスタの出力に応じてLEDが発光するようになっています。
下の回路図を見てください。
この回路図では、LEDと並列に可変抵抗が接続されています。
可変抵抗の抵抗値を大きくすると、LEDに流れる電流が増えます。
また、抵抗値が大きくなるとピンにかかる電圧が減少します。
この可変抵抗を回すことで、ライントレースの動作を調整することが出来ます。
黒と白の判定
さらに、黒色は光を吸収し、白色は光を反射する性質があります。
この性質を利用して、地面の色が黒か白かを判定することができます。
これにより、照度センサーを活用したライントレースが可能になります。
照度センサーを試してみよう
下部基板には2つのライントレース用の照度センサーが搭載されています。
これを使って車体下の色を認識してみましょう。
この照度センサーはRPi PicoのADC0とADC1に接続されています。
(RPi Picoにはもう1つADCポートがありますので、他の用途でADCを追加で使いたい場合はそちらを利用できます。)
from machine import Pin, ADC
import time
led = Pin("LED", Pin.OUT) # LEDのピン設定
photoref = ADC(0) # ADC0を使用(括弧内の数字はGPIO番号ではありません)
# LEDの状態を1(オン)に初期化
led.value(1)
def read_sensor():
# センサーの値を0〜1に正規化して読み取る
photoref_out = photoref.read_u16() / 65535 # 16ビットの範囲を0〜1に変換
print(photoref_out)
while True:
read_sensor() # センサーの値を読み取る
time.sleep(0.05) # 50ミリ秒待機
16ビットの入力
照度センサーからの入力は16ビット(0〜65535)の範囲で返ってきます。
この値を0〜1の範囲に変換(正規化)して使いやすくしています。
これにより、出力値を0〜1で直感的に把握することができます。
出力の確認
プログラムを実行すると、0〜1の値が連続して表示されるはずです。
これが照度センサーが読み取った明るさの割合です。
もし値が全く変化しない場合は、どこかに不具合がある可能性があります。
値に応じた電流が前方の2つのLEDに流れており、LEDの明るさは電気的に変化しますが、この部分の変化はプログラムでは制御していません。
ライントレースの概要
次に、ライントレースについて説明します。ライントレースとは、走行するロボットが地面の黒線を認識して、その上を進む動作のことです。YouTubeなどで、黒い線に沿って走行するロボットの動画を見たことがあるかもしれませんが、それがライントレースの一例です。
ライントレースの仕組みは、使うセンサーの数によって異なりますが、今回は左右に2つの照度センサーを使用します。この2つのセンサーは、黒と白の境界を検知し、ロボットの動きを制御します。例えば、左側のセンサーが白を検知した場合、左側のタイヤを進行させます。逆に黒を検知した場合は左のタイヤを反転させます。同様に、右側のセンサーも制御することで、地面の色を認識しながらジグザグに走行することができます。
2つの照度センサーを使ってライントレースを行う
以下のコードは、左右の照度センサーから値を取得し、それに応じてモーターを制御する基本的なプログラムです。
センサーの値を取得するプログラム
左右の照度センサーから値を受け取り, タプル形式で値を返します。
from machine import Pin, ADC
import utime
led = Pin("LED", Pin.OUT)
# LED の状態を 1 (オン) に初期化します.
led.value(1)
# パーセンテージの閾値
Thr_num_left = 0.55
Thr_num_right = 0.55
# ピンの入出力設定
photoref_left = ADC(1) # ADC0を使う. ()内はGPIOの番号ではない
photoref_right = ADC(0) # ADC1を使う. ()内はGPIOの番号ではない
# モーター用のピンの入出力設定
MotorL_plus = Pin(0, Pin.OUT)
MotorL_minus = Pin(1, Pin.OUT)
MotorR_plus = Pin(2, Pin.OUT)
MotorR_minus = Pin(3, Pin.OUT)
# センサーが取得する明るさ(=明度)を読み取る
def read_sensor():
# センサー下の明度をパーセント表示する
photoref_out_left = photoref_left.read_u16() / 65535 # 0〜1の範囲に正規化
photoref_out_right = photoref_right.read_u16() / 65535 # 0〜1の範囲に正規化
# タプル形式で値をまとめて返す
return (photoref_out_left, photoref_out_right)
# 1秒停止
utime.sleep(1)
try:
while True:
utime.sleep(0.1)
# 取得したセンサーからのデータを格納する
data = read_sensor()
finally:
stop()
課題1
格納されたデータをprint(data)で確認してください。
モーターを制御するプログラム
次に、取得したセンサーの値に応じてモーターを制御します。これがライントレースの基本です。
以下のプログラムを参考に、先ほどのプログラムに追記してプログラムを完成させましょう。
from machine import Pin, ADC
import utime
~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~
# 左側のモーターを前進させる関数
def left_go():
MotorL_plus.value(1)
MotorL_minus.value(0)
# 右側のモーターを前進させる関数
def right_go():
MotorR_plus.value(1)
MotorR_minus.value(0)
# 左側のモーターを後退させる関数
def left_back():
MotorL_plus.value(0)
MotorL_minus.value(1)
# 右側のモーターを後退させる関数
def right_back():
MotorR_plus.value(0)
MotorR_minus.value(1)
# モーターを停止する関数
def stop():
MotorL_plus.value(1)
MotorL_minus.value(1)
MotorR_plus.value(1)
MotorR_minus.value(1)
# 1秒待機
utime.sleep(1)
try:
while True:
utime.sleep(0.1) # 0.1秒待機
data = read_sensor() # 照度センサーの値を取得
print(data[0], data[1]) # センサーの値を確認
# 左のセンサーが閾値より低い(黒を認識)場合
if data[0] <= Thr_num_left:
left_go() # 左のタイヤを前進
else:
left_back() # 左のタイヤを後退
# 右のセンサーが閾値より低い(黒を認識)場合
if data[1] <= Thr_num_right:
right_go() # 右のタイヤを前進
else:
right_back() # 右のタイヤを後退
# プログラムが終了する際にモーターを停止
finally:
stop()
実行上の注意点
- 閾値と可変抵抗の調整
照度センサーから読み取った明るさの値(0〜1の範囲)を基に黒と白を判別するために、閾値を適切に設定してください。
また、可変抵抗は電気的に入力される電圧を調整するものなので、最初に可変抵抗を調整して黒と白の差が明確になるように設定しましょう。
その後、閾値を調整して正しく動作するようにします。 - 動作確認
正しく認識されるようになったら、プログラムをRPi Picoに書き込み、USBケーブルを外してライントレースのフィールドに配置してください。
課題2
前の車輛との距離を保ちながらライントレースをする。
これまで学んだ内容を組み合わせて、前方の物体との距離を10cm以上に保ちながらライントレースを行ってみましょう。
やることはシンプルで、前方の物体との距離を測定し、その距離に応じてロボットが前進するか停止するかを決めるだけです。
前方の距離を測定する仕組みは、以前の障害物回避の内容を活用できます。
課題3
裏面のライントレースを行い、完走を目指してください。
時間内に出来なかった場合はどのような原因が考えられるか考察してください。