2025年7月24日木曜日

python ロボットカー

amazonでosoyoo ラズパイ用のロボットカーを購入した。

https://osoyoo.com/2023/03/30/osoyoo-v4-0-robotic-car-for-raspberry-pi-introduction-model2020005500/

 ハードウェア

Raspberry Pi 3 Model B Plus Rev 1.3
OS:Debian GNU/Linux 12 (bookworm)
PWM HAT V1.0
model X motor driver module
CSI camera
Tracking sensor module
Ultrasonic sensor

他にもマイクロSDカードや2000mAh 18650充電池など、ラズパイさえあれば使用可能なキットになっている。

 

組み立て

 小学4年の子供と一緒に組み立て。公式の作成動画を見ながら割と簡単に組み立ては完了。

 

 目標

アンドロイド端末から、カメラを見ながらラジコン操作。 pythonで。


目次

1.モーター制御(前進)

2.モーター制御(後進、旋回) 

 

 

ロボットカー DCモーター操作 その1

チュートリアル通りに組み立てを完了させます。 
 

【配線図】

 

(画像:https://osoyoo.com/2023/03/09/raspberry-pi-robot-car-v4-0-lesson-1-basic-installation-and-movement/)

 

osoyoo model X モータードライバー(L298N)
IN1 = 23  #Left motor direction pin Board16
IN2 = 24  #Left motor direction pin Board18
IN3 = 27  #Right motor direction pin Board13
IN4 = 22  #Right motor direction pin Board15
ENA = 0  #Left motor speed PCA9685 port 0
ENB = 1  #Right motor speed PCA9685 port 1

ENA、ENBとはenablePINでPWM制御のためにある。既にosoyooPWMHAT(PCA9685)に接続しているため、併せてPWM制御も行う。


 RPi.GPIO

ラズパイのGPIOピンを制御するためのpythonライブラリ。
使い方(例)
①インポート
$ import RPi.GPIO as GPIO  # as GPIO とするのが一般的なよう。
②GPIOモードの設定
ピン番号の解釈の指定 BCM と BOARD がある。
$ GPIO.setmode(GPIO.BCM) BCMが多い?
③ピンの設定
各ピンを入力か出力かを設定する。
$ GPIO.setup(17, GPIO.OUT) #ピン17を出力に設定
$ GPIO.setup(22, GPIO.IN) #ピン22を入力に設定
④出力
 出力ピン(③でGPIO.OUTに設定したピン)にHIGH(3.3V)かLOW(0V)を設定。
⑤入力
 入力ピンの状態を読み取る
 $ input_value = GPIO.input(22) #ピン22の状態を読み取り
 if input_value == GPIO.HIGH:
     print("Button is pressed")

⑥ピンのクリーンアップ
 スクリプトの最後に、GPIOピンの状態をリセットする。
 $ GPIO.cleanup()


PWM制御

ラズパイにはGPIOピンが少ないため、I2CでPWM制御が可能なPWMドライバを使用することが多いようです。

今回はOSOYOO PWM HAT v1.0(PCA9685)を使用します。

 osoyoo PWM HAT(PCA9685)を使用する場合は、
①ライブラリのインポート:adafruit_pca9685
②PCA9685の初期化
③PWM周波数の設定
④DCモーター制御

 

前進

2秒間前進して止まるためのプログラム 
 
mtr.py備考
import time
import board
import busio
from adafruit_pca9685 import PCA9685
import RPi.GPIO as GPIO

i2c = busio.I2C(board.SCL, board.SDA)
pwm = PCA9685(i2c)
pwm.frequency = 50

IN1 = 23  
IN2 = 24  
IN3 = 27  
IN4 = 22  
ENA = 0  
ENB = 1  

GPIO.setmode(GPIO.BCM)
GPIO.setup(IN1, GPIO.OUT)   
GPIO.setup(IN2, GPIO.OUT) 
GPIO.setup(IN3, GPIO.OUT)   
GPIO.setup(IN4, GPIO.OUT)

def motor_speed(speed):
    duty_cycle = int(speed * 65535)
    pwm.channels[ENA].duty_cycle = duty_cycle
    pwm.channels[ENB].duty_cycle = duty_cycle

def car_stop():
    GPIO.output(IN1, GPIO.LOW)
    GPIO.output(IN2, GPIO.LOW)
    GPIO.output(IN3, GPIO.LOW)
    GPIO.output(IN4, GPIO.LOW)
    motor_speed(0)

def car_forward():
    GPIO.output(IN1, GPIO.HIGH)
    GPIO.output(IN2, GPIO.LOW)
    GPIO.output(IN3, GPIO.LOW)
    GPIO.output(IN4, GPIO.HIGH)
    motor_speed(0.5)

def car_backward():
    GPIO.output(IN1, GPIO.LOW)
    GPIO.output(IN2, GPIO.HIGH)
    GPIO.output(IN3, GPIO.HIGH)
    GPIO.output(IN4, GPIO.LOW)
    motor_speed(0.5)

def car_right_turn():
    GPIO.output(IN1, GPIO.HIGH)
    GPIO.output(IN2, GPIO.LOW)
    GPIO.output(IN3, GPIO.HIGH)
    GPIO.output(IN4, GPIO.LOW)
    motor_speed(0.5)

def car_left_turn():
    GPIO.output(IN1, GPIO.LOW)
    GPIO.output(IN2, GPIO.HIGH)
    GPIO.output(IN3, GPIO.LOW)
    GPIO.output(IN4, GPIO.HIGH)
    motor_speed(0.5) 



def main():
    try:
        car_forward()
        time.sleep(2)
    except KeyboardInterrupt:
        pass
    finally:
        car_stop()

main()
GPIO.cleanup()
time.sleep(2)






I2Cオブジェクトの作成



#Left motor direction pin
#Left motor direction pin
#Right motor direction pin
#Right motor direction pin
#Left motor PCA9685 port0 
#Right motor PCA9685 port1 

GPIO設定






speed
 0(停止)~1(全速)










































ctrl + "c"




main関数の実行
GPIOピンの解放