スクラッチくらぶ中級編ーOriginal-car

スクラッチくらぶ 1号 ロボットカーキット

オリジナルカーの名前は、スクラッチくらぶ 1号です。UCTRONICS K-0073 UC-485 を使用しないで、Raspberry Pi ロボットカーキットを動かす方法を実験・検証していきます。

※理由としては、UCTRONICS K-0073 UC-485 で提供されている実機環境は、ちょっとレベルが高すぎて、小学生高学年や中学生レベルでは動かすことは無理だと判断しました。

★★★★★ ★★★★★ ★★★★★

スクラッチくらぶ 1号は、Raspberry Pi ロボットカーキットのGPIO端子図を基に、Raspberry Pi 標準カメラをチルト(上下)する駆動機能、黒いテープライン上を走るライントラッキング機能、HC-SR04 超音波距離センサによる障害物回避機能、DCモータ4つで前進・後退する機能をPython(パイソン)でプログラミングします。

図.スクラッチくらぶ 1号(右側面) 外観図

図.スクラッチくらぶ 1号(左側面) 外観図

図.スクラッチくらぶ 1号(上側面) 外観図

★★★★★ ★★★★★ ★★★★★

図. スクラッチくらぶ 1号 GPIO端子図

★★★★★ ★★★★★ ★★★★★

■ カメラ駆動実験・検証

ブレッドボードを使って、カメラ上下駆動のコネクタの電源、GND、信号線をGPIO端子と接続します。

★★★★★ ★★★★★ ★★★★★

スクラッチくらぶ 1号 の Raspberry Pi の GPIO番号との関係(正式)
チルトするサーボモータ・・・・GPIO 25・・・・Servo Y

GPIO端子→カメラ上下駆動コネクタ 結線図

★★★★★ ★★★★★ ★★★★★

※Pythonでプログラム作成しました。

import pigpio

SERVO_PIN = 25
PULSE = 1450
Pi = pigpio.pi()
pi.set_servo_pulsewidth( SERVO_PIN,PULSE )

■ カメラ&サーボ駆動実験・検証

※Pythonでプログラム作成しました。

import time
import picamera
import pigpio

SERVO_PIN = 25
camera = picamera.PiCamera()
pi = pigpio.pi()

camera.resolution = (800,600)
camera.start_preview()

def distance():
        PULSE = 750
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 800
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 850
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 900
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )    
        time.sleep(2)

        PULSE = 950
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )   
        time.sleep(2)

        PULSE = 900
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 850
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 800
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 750
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 700
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 650
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 600
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 650
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        PULSE = 700
        pi.set_servo_pulsewidth( SERVO_PIN, PULSE )
        time.sleep(2)

        return distance

try:
    while True:
        dist = distance()

# Ctrl+Cでプログラムを中断
except KeyboardInterrupt:
    print("\r測定を停止します")

★★★★★ ★★★★★ ★★★★★

■ ライントラッキングセンサ実験・検証

ブレッドボードを使って、ライントラッキングセンサのコネクタの電源、GND、信号線をGPIO端子と接続します。

★★★★★ ★★★★★ ★★★★★

スクラッチくらぶ 1号 の Raspberry Pi の GPIO番号との関係(正式)
O1・・・・GPIO 17・・・・OUTL_protect(Left)
O2・・・・GPIO 27・・・・OUTM_protect(Middle)
O3・・・・GPIO 22・・・・OUTR_protect(Right)

GPIO端子→ライントラッキングセンサコネクタ 結線図

★★★★★ ★★★★★ ★★★★★

※Pythonでプログラム作成しました。

import pigpio
import time

PREF_PIN_1 = 17
PREF_PIN_2 = 27
PREF_PIN_3 = 22

pi = pigpio.pi()

pi.set_mode( PREF_PIN_1, pigpio.INPUT )
pi.set_pull_up_down( PREF_PIN_1, pigpio.PUD_OFF )

while True:
    if ( pi.read( PREF_PIN_1 ) == pigpio.HIGH ):
        print ("White_1")
    else:
        print ("Black_1")

time.sleep(1)

★★★★★ ★★★★★ ★★★★★

■ HC-SR04 超音波距離センサ実験・検証

ブレッドボードを使って、HC-SR04 超音波距離センサのコネクタの電源、GND、信号線をGPIO端子と接続します。

★★★★★ ★★★★★ ★★★★★

スクラッチくらぶ 1号 の Raspberry Pi の GPIO番号との関係(正式)
Trig・・・・GPIO 26
Echo・・・・GPIO 23

GPIO端子→超音波距離センサコネクタ 結線図

★★★★★ ★★★★★ ★★★★★

※Pythonでプログラム作成しました。

#!/usr/bin/env python3
# -*- coding: utf-8
 
import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
 
# HC-SR04のピン 
GPIO_TRIGGER = 37 # トリガーはGPIO 26
GPIO_ECHO = 16 # エコーはGPIO 23
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
time.sleep(1) 

# 距離を測定 
def distance():
     GPIO.output(GPIO_TRIGGER, True)
     time.sleep(0.00001)
     GPIO.output(GPIO_TRIGGER, False)

     StartTime = time.time()
     StopTime = time.time()

     while GPIO.input(GPIO_ECHO) == 0:    
     StartTime = time.time()
 
     while GPIO.input(GPIO_ECHO) == 1:
     StopTime = time.time()

     TimeElapsed = StopTime - StartTime # かかった時間
     distance = TimeElapsed * 17025 # 距離を計算

     return distance

# 距離を表示
     print("距離を測定します")
 try:
     while True:
         dist = distance()
         print ("Distance = %.1f cm" % dist)
         time.sleep(0.5)

# Ctrl+Cでプログラムを中断
except KeyboardInterrupt:
     print("\r測定を停止します")
     GPIO.cleanup() 

$ sudo python sonic_test.py [Enter]

距離を測定します。
Distance = 35.6 cm
Distance = 35.9 cm
Distance = 36.8 cm
・・・
・・・
([Ctrl]+[C]を押す)
測定を停止します

★★★★★ ★★★★★ ★★★★★

■ DCモータ駆動実験・検証

ブレッドボードを使って、DRV8835を使用したDCモータドライブキットのコネクタの電源、GND、信号線をGPIO端子と接続します。

★★★★★ ★★★★★ ★★★★★

■ DRV8835(モータドライブキット)とDCモータを使って実験・検証

DRV8835(PWMピン制御なし)結線図

Raspberry Pi 側配線
配線はこのようになります。
VCC → RaspberryPi 5V( 赤 )
GND → RaspberryPi GND( 黒 )
IN1 → RaspberryPi GPIO24( グレー )
IN2 → RaspberryPi GPIO25( 白 )

電源ターミナル側配線
VM → ACアダプタの+側へ( 赤 )
GND → ACアダプタの – 側へ( 黒 )
OUT1 → モータへ( 紫 )
OUT2 → モータへ( 緑 )


★★★★★ ★★★★★ ★★★★★

■ 「DRV8835」モータドライブキット仕様

※ DRV8835 DCモータドライブキット ※

図.DRV8835回路と端子配列図

★★★★★ ★★★★★ ★★★★★

DRV8835 DCモータドライブキット4車輪

★★★★★ ★★★★★ ★★★★★

「MODE」と「GND」を繋ぐとブレーキがかからないようになり、「MODE」と「VCC」を繋ぐとブレーキがかかるようになります。今回はブレーキをかけたくないので、「MODE」と「GND」を黒いパーツで接続しています。

MODE IN1 IN2 OUT1 OUT2 FUNCTION
0 0 0 Z Z 空転
0 0 1 L H 逆転
0 1 0 H L 正転
0 1 1 L L ブレーキ

★★★★★ ★★★★★ ★★★★★

スクラッチくらぶ 1号 の Raspberry Pi の GPIO番号との関係(正式)
左前輪モータ・・・・GPIO 5 & GPIO 6
右前輪モータ・・・・GPIO 18 & GPIO 24
左後輪モータ・・・・GPIO 20 & GPIO 21
右後輪モータ・・・・GPIO 13 & GPIO 19

GPIO端子→DRV8835モータコネクタ 結線図

★★★★★ ★★★★★ ★★★★★

(参考図)GPIO端子→TA7291Pモータコネクタ 結線図

★★★★★ ★★★★★ ★★★★★

(参考)今回はUCTRONICS K-0073 UC-485 は使用しないが、白いコネクタ部分はDRV8835モータドライブキットと接続するのに使用します。

①②・・・・左後輪
GPIO 20 & GPIO 21 →
GPIO 20(HIGH) & GPIO 21(LOW)で前進
GPIO 20(LOW) & GPIO 21(HIGH)で後退する
③④・・・・右後輪
GPIO 13 & GPIO 19 →
GPIO 13(HIGH) & GPIO 19(LOW)で前進
GPIO 13(LOW) & GPIO 19(HIGH)で後退する
⑤⑥・・・・右前輪
GPIO 18 & GPIO 24 →
GPIO 18(HIGH) & GPIO 24(LOW)で前進
GPIO 18(LOW) & GPIO 24(HIGH)で後退する
⑦⑧・・・・左前輪
GPIO 5 & GPIO 6 →
GPIO 5(HIGH) & GPIO 6(LOW)で前進
GPIO 5(LOW) & GPIO 6(HIGH)で後退する

★★★★★ ★★★★★ ★★★★★

■ DRV8835(モータドライブキット)1個とDCモータ1個を使って「Python」でプログラム作成

※Python でプログラム作成してみました

今回は正転と逆転をするようにしています。最初のループでDuty比が徐々に上がっていき、それに伴いモータの回転数も上がっていきます。Duty比が100を超えると今度は下がっていきます。0以下になったらbreakで抜けて次の処理へ移ります。


sleep(3.0)で3秒間時間を空けてから、今度は逆回転を行います。逆回転のときも処理は上記と同じようになります。逆回転の処理をBreakで抜けるとモータは止まります。

★★★★★ ★★★★★ ★★★★★

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pigpio
from time import sleep

PIN1 = 5
PIN2 = 6
FREQ = 100
RANGE = 100

pi = pigpio.pi()

pi.set_mode(PIN1, pigpio.OUTPUT)
pi.set_mode(PIN2, pigpio.OUTPUT)
pi.set_PWM_frequency(PIN1, FREQ)
pi.set_PWM_frequency(PIN2, FREQ)
pi.set_PWM_range(PIN1, RANGE)
pi.set_PWM_range(PIN2, RANGE)

try:
    d = 0
    r = 10
    while True:
        pi.set_PWM_dutycycle(PIN1, d)
        pi.set_PWM_dutycycle(PIN2, 0)
        sleep(0.2)
        d += r
        if d >= RANGE:
            r *= -1
        if d <= 0:
            break

    pi.write( PIN1, pigpio.HIGH )
    pi.write( PIN2, pigpio.HIGH )

    sleep(3.0)

    d = 0
    r = 10
    while True:
        pi.set_PWM_dutycycle(PIN1, 0)
        pi.set_PWM_dutycycle(PIN2, d)
        sleep(0.2)
        d += r
        if d >= RANGE:
            r *= -1
        if d <= 0:
            break

except Keyboardinterrupt:
pass

pi.set_mode(PIN1, pigpio.INPUT)
pi.set_mode(PIN2, pigpio.INPUT)
pi.stop()

■ DCモータ&カメラ&サーボ駆動実験・検証

※Python でプログラム作成してみました

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import picamera
import pigpio
from time import sleep

SERVO_PIN = 25
PULSE = 500

PIN1 = 5
PIN2 = 6
FREQ = 100
RANGE = 100

camera = picamera.PiCamera()
pi = pigpio.pi()

camera.resolution = (800,600)
camera.start_preview()
sleep(5)

pi.set_mode(PIN1, pigpio.OUTPUT)
pi.set_mode(PIN2, pigpio.OUTPUT)
pi.set_PWM_frequency(PIN1, FREQ)
pi.set_PWM_frequency(PIN2, FREQ)
pi.set_PWM_range(PIN1, RANGE)
pi.set_PWM_range(PIN2, RANGE)

try:
    d = 0
    r = 10
    deg = 700
    while True:
        pi.set_PWM_dutycycle(PIN1, d)
        pi.set_PWM_dutycycle(PIN2, 0)
        sleep(0.2)
        d += r

        deg = deg + 30
        pi.set_servo_pulsewidth( SERVO_PIN, deg )

        if d >= RANGE:
            r *= -1
        if d <= 0:
            break

    pi.write( PIN1, pigpio.HIGH )
    pi.write( PIN2, pigpio.HIGH )

    sleep(3.0)

    d = 0
    r = 10
    while True:
        pi.set_PWM_dutycycle(PIN1, 0)
        pi.set_PWM_dutycycle(PIN2, d)
        sleep(0.2)
        d += r

        deg = deg - 30
        pi.set_servo_pulsewidth( SERVO_PIN, deg )

        if d >= RANGE:
            r *= -1
        if d <= 0:
            break

except KeyboardInterrupt:
    print("\r測定を停止します")

pi.set_mode(PIN1, pigpio.INPUT)
pi.set_mode(PIN2, pigpio.INPUT)
pi.stop()

★★★★★ ★★★★★ ★★★★★

★★★★★ ★★★★★ ★★★★★