【Raspberry Pi Pico】ライントレースロボットを作ろう ②センサー3つ

【Raspberry Pi Pico】ライントレースロボットを作ろう ②センサー3つ

こんにちは! けい(Twitter)です。

前回ラズパイPicoで作ったライントレースロボットの進化verを作ったので、ご紹介していきたいと思います。

前回と今回の比較

前回のロボットの構成

前回は、以下の構成でライントレースロボットを作りました。

  • マイコン:ラズパイPico
  • モータードライバ:DRV8833
  • モーター:タミヤのダブルギヤボックス
  • ライントレースセンサ:1つ
  • 回転:旋回のみ

詳しくは前回の記事を読んでみて下さい。

今回の改良点

今回は、以下の構成でライントレースロボットを作りました。

  • マイコン:ラズパイPico
  • モータードライバ:DRV8833
  • モーター:タミヤのダブルギヤボックス
  • ライントレースセンサ:3つ
  • 回転:超信地旋回を追加
  • pwmによるモータ速度調整機能を追加

ハード面ではセンサーの追加ソフト面では超信地旋回と速度調整機能を追加しました。

ロボットのハードウェア

ライントレースセンサーの追加

前回同様のライントレースセンサーを増やして、スペーサーで固定しました。

また、センサーが外向きになる方がかっこいいので、向きを変えてみました。

回路図

図では単三電池が2本ですが、実際には3本の4.5Vで全ての電力を供給しています。

プログラム

ソースコード

電源が入ると自動でプログラムが実行されるように、「main.py」というファイル名でRaspberry Pi Picoにファイルを保存します。

from machine import PWM, Pin
import utime

class Robot:
    def __init__(self):
        self.IN1 = PWM(Pin(1))
        self.IN2 = PWM(Pin(2))
        self.IN3 = PWM(Pin(3))
        self.IN4 = PWM(Pin(4))
        self.IN1.freq(1000)
        self.IN2.freq(1000)
        self.IN3.freq(1000)
        self.IN4.freq(1000)
    def forward(self,v):
        self.IN1.duty_u16(duty(v))
        self.IN2.duty_u16(0)
        self.IN3.duty_u16(duty(v))
        self.IN4.duty_u16(0)
    def right(self,v):
        self.IN1.duty_u16(duty(v))
        self.IN2.duty_u16(duty(v))
        self.IN3.duty_u16(duty(v))
        self.IN4.duty_u16(0)
    def left(self,v):
        self.IN1.duty_u16(duty(v))
        self.IN2.duty_u16(0)
        self.IN3.duty_u16(duty(v))
        self.IN4.duty_u16(duty(v))
    def right_spin(self,v):
        self.IN1.duty_u16(0)
        self.IN2.duty_u16(duty(v))
        self.IN3.duty_u16(duty(v))
        self.IN4.duty_u16(0)
    def left_spin(self,v):
        self.IN1.duty_u16(duty(v))
        self.IN2.duty_u16(0)
        self.IN3.duty_u16(0)
        self.IN4.duty_u16(duty(v))
    def back(self,v):
        self.IN1.duty_u16(0)
        self.IN2.duty_u16(duty(v))
        self.IN3.duty_u16(0)
        self.IN4.duty_u16(duty(v))
    def stop(self):
        self.IN1.duty_u16(duty(100))
        self.IN2.duty_u16(duty(100))
        self.IN3.duty_u16(duty(100))
        self.IN4.duty_u16(duty(100))
    def release(self):
        self.IN1.duty_u16(0)
        self.IN2.duty_u16(0)
        self.IN3.duty_u16(0)
        self.IN4.duty_u16(0)
        
class Photo_sensor:
    def __init__(self):
        self.sensor_1 = Pin(6, Pin.IN)
        self.sensor_2 = Pin(7, Pin.IN)
        self.sensor_3 = Pin(8, Pin.IN)
        self.value = [0]*3
    
    def read_sensor(self):
        self.value[0] = self.sensor_1.value()
        self.value[1] = self.sensor_2.value()
        self.value[2] = self.sensor_3.value()
        return self.value

def duty(percent):
    return int(65025*percent*0.01)

robot = Robot()
sensor = Photo_sensor()
value_old = [0, 0, 0]
utime.sleep(1)

while True:
    value = sensor.read_sensor()
    # 真ん中が黒
    if value[1]==1:
        if value[0]==value[2]:
            robot.forward(80)
        elif value[0]==1:
            robot.left_spin(80)
        elif value[2]==1:
            robot.right_spin(80)
            
    # 真ん中が白
    else:
        if value[0]==1:
            robot.left_spin(80)
        elif value[2]==1:
            robot.right_spin(80)
        else:
            if value_old[0]==1:
                robot.left_spin(100)
                utime.sleep(0.2)
            elif value_old[2]==1:
                robot.right_spin(100)
                utime.sleep(0.2)
            else:
                robot.forward(80)
    value_old = value

コード解説

4~53行目が、ロボットの駆動系のクラスです。
ここの部分に、今回新たに超信地旋回用の関数、「left_spin」「right_spin」を追加しました。
また、pwm信号でモーターにかかる電圧を調整できるようにしました。

55~66行目が、ライントレースセンサーのクラスです。
この部分で、センサー3つそれぞれの白と黒を読み取る関数を作成しています。

76行~が、メインループです。
主に、真ん中が黒か白かでプログラムを二分化しています。
ここの部分はまだまだ改良の余地があるので、皆さんでもぜひ挑戦してみて下さい。

実際にロボットを動かしてみた

動かした様子をyoutubeにアップしました。

なんとか試行錯誤の結果、コースを走破することができました。

始めてライントレースロボットを作ってみて、やはり一筋縄ではいかなかったなというのが所感です。