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

UCTRONICS-K0073 ロボットカーキット

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

プログラミング言語の、Scratch(スクラッチ)やPython(パイソン)と、 Raspberry Pi(ラズベリーパイ)の教育用マイコンボードを組み合わせることで、ロボットやIoT機器を制御することが出来ます。

Raspberry Pi(ラズベリーパイ)は、イギリスのラズベリーパイ財団で開発された教育用のマイコンボードです。

※ Raspberry Pi は ラズベリーパイ財団 の登録商標です。

21世紀型の新しい教育STEM教育(ステムきょういく)」が世界各国で導入され始めています。「Scratch(スクラッチ)」はSTEM教育に適したビジュアルプログラミング言語です。

【 STEM教育とは 】
STEMとは、Science(科学)、Technology(技術)、Engineering(工学)、Mathematics(数学)の頭文字を取ったもので、これら4つの学問の教育に力を注いで、IT社会とグローバル社会に適合した国際競争力を持った人材を多く育てていこうという考えをベースにした、21世紀型の教育システムです。

日本で2020年度から始まる「小学校でのプログラミング教育の必修化」もその一環といえるでしょう。

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

■ RASPi3-RGL Raspberry Pi 3B+ の準備

共立プロダクツ RASPi3-RGL[Raspberry Pi 3B+ スタータセット/レギュラー] を組み立てた後は、PCでOS「Raspbian full」を 「FAT32」形式のMicroSDカード(16GB)にインストールします。

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

■ Raspberry Pi Touch Display の準備

アイ・オー・データ機器 I-O DATA UD-RPDISPLAY [Raspberry Pi Touch Display] は、Raspberry Pi 公式の7インチタッチディスプレイです。Raspberry Pi をタブレット、インフォテインメントシステムなどとして利用することができます。

Raspberry Pi 用OS「Raspbian」を使用する場合は仮想オンスクリーンキーボードとして利用できます。 Raspberry Pi 3B+ からのデータは、FFCフレキシブルフラットケーブルを通して Raspberry Pi Touch Display に送信されます。

DC電源(+5V)とGNDは Raspberry Pi 3B+ のGPIO端子の DC電源(+5V)とGND から取ります。

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

■ Raspberry Pi 用 公式カメラモジュールの準備

Raspberry Pi 用 公式カメラモジュールの FFCフレキシブルフラットケーブは、必ずカメラモジュールに付属のケーブルを使って下さい。

カメラ用コネクタの位置は下図の通りです。コネクタのロックを外して黒いプラスチックを浮かせて下さい。

FFCフレキシブルフラットケーブは、金属の接点のある側がHDMIコネクタ側を向く様に差し込んで下さい。

ケーブルが突き当たるまでコネクタに差し込んで下さい。差し込みが浅いとカメラが機能しません。

差し込んだら、黒いプラスチックを押し込んでロックして下さい。

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

■ UCTRONICS-K0073 Raspberry Pi ロボットカーキットの組み立て

UCTRONICS-K0073 Raspberry Pi ロボットカーキット制御ボードと Raspberry Pi 3B+ マイコンボードと Raspberry Pi Touch Display を接続します。

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

■ UCTRONICS-K0073 Raspberry Pi ロボットカーキット用 ソフトウェアマニュアル

UCTRONICS-K0073 Raspberry Pi(ラズベリーパイ)ロボットカーキットを購入したときに添付されているDVDファイル内容は、

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

■ 3.Software(Raspberry Pi configuration and programming) フォルダ

Software(Raspberry Pi configuration and programming) フォルダ → UCBlockをクリック → UCBlockアプリケーションをクリックします。

★ Scratch 2 画面が表示されて、プログラミングとシミュレーションが実行出来ます。

ステージの画面の大きさは、横座標は(-250~0~+250ピクセル)、縦座標は(-180~0~+180ピクセル)です。

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

■ 公式カメラモジュールで静止画や動画を撮る

Raspberry Pi 3B+ の公式カメラモジュールで写真や動画が撮影できることを確認します。Raspbian の「ラズパイのアイコン」→「設定」→「Raspberry Pi 設定」の「インターフェイス」の「カメラ」を「有効」にします。

Raspberry Pi 3B+ のRaspbian のコマンド入力 LXTerminal で 、

写真の撮影には、

$ raspistill -o sample.jpg [Enter]
$ gpicview sample.jpg [Enter]

すると、下図のような静止画像が撮影できました。

sample.jpg

また、撮影開始してから3秒後に実際の撮影が行われるようにするには、

$ raspistill -t 3000 -o sample.jpg [Enter]
$ gpicview sample.jpg [Enter]

となります。

また、動画撮影には、

$ raspivid -o sample.h264 -t 10000 [Enter]
$ omxplayer sample.h264 [Enter]
$ sudo apt -y install gpac [Enter]
$ MP4Box -fps 25 -add sample.h264 sample.mp4 [Enter]
$ omxplayer sample.mp4 [Enter]

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

■「Python」で公式カメラモジュールで静止画を撮るプログラム

カメラモジュールはpicameraというライブラリで動かせます。

$ pip install picamera [Enter]

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

import time
import picamera

camera = picamera.PiCamera()

def takepic(picname):
    camera.resolution = (800,600)
    camera.rotation = 180
    camera.start_preview()

    # Camera warm-up time                                                                                                               
    time.sleep(200)
    camera.capture(picname)

def main():
    takepic("test.png")

if __name__ == '__main__':
    main()

200秒後に「test.png」という画像ファイルが取得出来ました。

※この様な簡単なプログラムも書けます。

import time
import picamera

with picamera.PiCamera() as camera:
    camera.resolution = (800,600)
    camera.start_preview()
    time.sleep(20)
    camera.capture("test.jpg")

    camera.stop_preview()

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

■「Python」で公式カメラモジュールで動画を撮るプログラム

※この様な簡単なプログラムも書けます。

import time
import picamera

with picamera.PiCamera() as camera:
    camera.resolution = (800, 600)
    camera.start_preview()
    time.sleep(2)
    camera.start_recording('test.h264')
    camera.wait_recording(10)

    camera.stop_recording()

「test.h264」 という約10秒間の動画ファイルが取得出来ました。

※※※ H.264をMP4に変換する方法 ※※※

「gpac」パッケージをインストールします 。

sudo apt install -y gpac [Enter]

「MP4Box」というコマンドで、h.264からmp4に変換が可能です。

MP4Box -add test.h264 test.mp4 [Enter]

これで、「test.h264」ファイル形式を「test.mp4」に変換できました。

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

■ 「Mu Python」や「Python 3」や「Thonny Python IDE」を使う

Raspberry Pi で電子パーツを制御するには、「pigpio」というライブラリを利用します。「pigpio」を使うには、あらかじめ常駐プログラムの「pigpio」を動作させておく必要があります。

LXTerminal を立ち上げます。

$ sudo systemctl enable pigpiod [Enter]

$ sudo systemctl start pigpiod [Enter]

※プログラムがうまく動作しなかった場合は、「pigpio」に問題が生じている恐れがあります。この場合は次のように実行して「pigpio」を再起動します。

$ sudo systemctl restart pigpiod [Enter]

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

※工作用のPythonライブラリ比較

ライブラリ名 RPi.GPIO pigpio
標準搭載
常駐アプリ 不要 必要
デジタル入出力
ソフトウェアPWM
ハードウェアPWM ×
I2C ×
SPI ×
UART ×
リモートGPIO ×

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

■ UCTRONICS K-0073 UC-485 回路図を見る

ブラウザで、「UCTRONICS UC-485 K0073」で検索します。

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

タイトル:「-PDF Free Download」から、「回路図」が取得できます。

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

UCTRONICS-K0073用 GPIO端子図

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

■ UCTRONICS K-0073 UC-485 動作内容

■ パーン(左右動作)するサーボモータと、チルト(上下動作)するサーボモータ

サーボモータは特定の角度まで腕状のロッドを動かし、その角度で維持し続けられるモータです。ロボットのアームや、模型の車のステアリングなどに利用されます。サーボロッドを目的の角度まで動かすには、PWMを利用します。Highの時間によって目的の角度を指定できます。今回利用するサーボモータのSG-90ではHighの時間を1450μ秒にすると中央まで移動します。500μ秒にすると右方向90度まで回転し、2400μ秒にすると左90度まで回転します。

PWMのパルス幅(μ秒)
パーンするサーボモータ・・・・500(右に90度)~ 1450(0度)~ 2400(左に90度)
チルトするサーボモータ・・・・500(上に90度)~ 1450(0度)~ 2400(下に90度)

※角度からパルス幅を求める計算式
パルス幅 = ( 950÷90 ) X 角度 + 1450

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

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

UCTRONICS-K0073 Raspberry Pi の GPIO番号との関係(正式)
パーンするサーボモータ・・・・GPIO 4・・・・Servo X
チルトするサーボモータ・・・・GPIO 25・・・・Servo Y

import pigpio

SERVO_X_PIN = 4
SERVO_Y_PIN = 25
PULSE_X = 800
PULSE_Y = 1450

Pi = pigpio.pi()
pi.set_servo_pulsewidth( SERVO_X_PIN,PULSE_X )
pi.set_servo_pulsewidth( SERVO_Y_PIN,PULSE_Y )

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

#!/usr/bin/env python

import math
import time

import pantilthat

while True:
    # Get the time in seconds
    t = time.time()

    # G enerate an angle using a sine wave (-1 to 1) multiplied
        by 90(-90 to 90)
    a = math.sin(t * 2) * 90

    # Cast a to int for v0.0.2
    a = int(a)

    pantilthat.pan(a)
    pantilthat.pantilthat.pantilthat.tilt(a)

    # Two decimal places is quite enough!
    print(round(a,2))

    # Sleep for a bit so we're not hammering the HAT with updates
    time.sleep(0.005)

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

■ Line Tracking Sensor module ライントラッキングと黒ラインとの関係

フォトリフレクタは、床に描いた黒線などを検知できるセンサです。黒線まで達したら動作を停止する運搬車や、黒線に沿って進むライントレーサなどに利用されています。フォトリフレクタは赤外線LEDと光センサが直接光が届かないように配置されています。照射した赤外線は床などで反射すると光センサに届きます。床が黒色だとほとんど反射しないため、黒線と認識されます。

O1=1 の場合が白線検知(U3点灯)、 O1=0 の場合が黒線検知(U3消灯)
O2=1 の場合が白線検知(U4点灯)、 O2=0 の場合が黒線検知(U4消灯)
O3=1 の場合が白線検知(U5点灯)、 O3=0 の場合が黒線検知(U5消灯)

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

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

UCTRONICS-K0073 Raspberry Pi の GPIO番号との関係(正式)
O1・・・・GPIO 17・・・・OUTL_protect(Left)
O2・・・・GPIO 27・・・・OUTM_protect(Middle)
O3・・・・GPIO 22・・・・OUTR_protect(Right)

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」は超音波が対象物から跳ね返ってくるまでの時間から距離が分かります。トリガー(Trig)ピンに電圧をかけるとスピーカから40Hzの超音波が発信され、その音波が受信した瞬間に電圧がエコー(Echo)ピンに出力されるので、この間の時間を測定し、その値から音速を基に距離を計算します。

distance(cm) = TimeElapsed(秒) ÷ 2 X 音速(m/秒) X 100

音速は往復しているので、時間を2で割るのがポイントです。音速を340.5m/秒とすると、

distance(cm) = TimeElapsed(秒) X 17025

超音波の発信(Trigger)から 受信(Echo)までの時間数で、障害物までの距離(2 ~ 450 cm)が計算できます。

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

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

Raspberry Pi の GPIO番号との関係
Trig・・・・GPIO 8(SP1 CE0)・・・・TXD(Trig)
Echo・・・・GPIO 7(SP1 CE1)・・・・RXD(Echo)

#!/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 = 24 # トリガーはGPIO 8
GPIO_ECHO = 26 # エコーはGPIO 7
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]を押す)
測定を停止します

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

Raspberry Pi の GPIO番号との関係
Trig・・・・GPIO 8・・・・SP1 CE0
Echo・・・・GPIO 10・・・・SP1 MOSI

Raspberry Pi の GPIO番号との関係
Trig・・・・GPIO 14・・・・TXD(Trig)
Echo・・・・GPIO 15・・・・RXD(Echo)

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

# HIGH or LOWの時計測
def pulseIn(PIN, start=1, end=0):
    if start==0:
        end = 1
        t_start = 0
        t_end = 0
    # ECHO_PINがHIGHである時間を計測
    while GPIO.input(PIN) == end:
        t_start = time.time()
        
    while GPIO.input(PIN) == start:
        t_end = time.time()
    return t_end - t_start

# 距離計測
def calc_distance(TRIG_PIN, ECHO_PIN, num, v=34000): 
    for i in range(num):
        # TRIGピンを0.3[s]だけLOW
        GPIO.output(TRIG_PIN, GPIO.LOW)
        time.sleep(0.3)
        # TRIGピンを0.00001[s]だけ出力(超音波発射)        
        GPIO.output(TRIG_PIN, True)
        time.sleep(0.00001)
        GPIO.output(TRIG_PIN, False)
        # HIGHの時間計測
        t = pulseIn(ECHO_PIN)
        # 距離[cm] = 音速[cm/s] * 時間[s]/2
        distance = v * t/2
        print(distance, "cm")
    # ピン設定解除
    GPIO.cleanup()

# TRIGとECHOのGPIO番号   
TRIG_PIN = 14
ECHO_PIN = 15
# ピン番号をGPIOで指定
GPIO.setmode(GPIO.BCM)
# TRIG_PINを出力, ECHO_PINを入力
GPIO.setup(TRIG_PIN,GPIO.OUT)
GPIO.setup(ECHO_PIN,GPIO.IN)
GPIO.setwarnings(False)

# 距離計測(TRIGピン番号, ECHO_PIN番号, 計測回数, 音速[cm/s])
calc_distance(TRIG_PIN, ECHO_PIN, 10, 34000)

①出力ピン(GPIO)で超音波を出力
(トリガ端子を10μs以上Highにすると40kHzのパルスを8回送信)
②入力ピン(GPIO)で超音波を受信
(エコー端子がHIGHになってからLOWに変化するまでの時間=超音波が送信されてから受信するまでの時間[s]を計測)
③ 以下の式で時間から距離を求めます。

距離[cm] = (0.034) × (②で求めた時間[s]÷2)
音速=340[m/s] = 34000[cm/s]

## 実行結果

サンプルプログラムの実行結果です。

19.2134566134 cm
19.1412345674 cm
18.7612345667 cm
18.7345677832 cm

今回は音速を34000[cm/s]に固定して計算しています。
音速は気温などにも影響されるので、計測精度を上げるにはこれらの影響を考慮する必要があります。

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

■ DC MOTOR(DCモータ) と前後輪タイヤとの関係

DCモータは電池につなげると軸が回転します。DCモータの制御には通常、モータドライバを使います。DCモータには2本の制御線があります。制御線の状態を切り替えることで「正転」、「反転」、「停止」、「ブレーキ」になります。PWMを使えばモータの回転速度を制御できます。回転速度は0~100の範囲で指定します。

M2+,M2ー・・・・左後輪
M2GNDとM2+で → 前進する , M2+とM2GNDで → 後退する
M1+,M1ー・・・・右後輪
M1GNDとM1+で → 前進する , M1+とM1GNDで → 後退する
M4+,M4ー・・・・右前輪
M4GNDとM4+で → 後退する , M4+とM4GNDで → 前進する
M3+,M3ー・・・・左前輪
M3GNDとM3+で → 後退する , M3+とM3GNDで → 前進する

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

UCTRONICS-K0073 Raspberry Pi の GPIO番号との関係(正式)
PWM1・・・・GPIO 5
PWM2・・・・GPIO 6
PWM3・・・・GPIO 13
PWM4・・・・GPIO 19
DIR_LATCH(MOTOR LATCH)・・・・GPIO 21
DIR_CLK(MOTOR CLK)・・・・GPIO 20
DIR_SER(MOTOR DATA)・・・・GPIO 16

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

ブラウザで、「K0073 MOTORLATCH MOTORCLK MOTORDATA 」で検索します。

https://www.raspberrypi.org/forums/viewtopic.php?t=16118

タイトル:「Driving Arduino motor shield from Pi – Raspberry Pi Forums」から取得できます。

和訳:PiからArduinoモーターシールドを駆動

(※※以降が重要ページです)

https://raspberrypi.stackexchange.com/questions/49522/how-to-use-arduino-motor-shield-with-raspberry-pi が参考になりました。

タイトル:「How to use Arduino Motor Shield with Raspberry Pi?」から取得できます。

和訳:Raspberry Pi でArduinoモーターシールドを使用する方法

https://raspberrypi.stackexchange.com/questions/49522/how-to-use-arduino-motor-shield-with-raspberry-pi のページの中で、

https://github.com/lipoja/AMSpi が参考になりました。

※※K0073のMOTORLATCHとMOTORCLKとMOTORDATAの関係が理解出来ず!

※※これ以上は断念!

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

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