LoginSignup
3
1

More than 3 years have passed since last update.

ラジコンカーをPWM制御して走行させる

Last updated at Posted at 2019-04-25

概要

RaspberryPiのDCモータをPWM制御することでラジコンカーを動かします。今回はMacからRaspberryPiにSSHでリモート接続し手元のキーボードから操作できるようにしています。コースを以下のように作って実際に走らせてみました。
course.png

PWM制御とは

PWM制御とは、スイッチのオンとオフのスイッチングを高速で行い、擬似的に出力電圧を制御するというものです。出力電圧を制御することによってラジコンカーを右や左方向に曲がる動作を行うことができます。例えば左のDCモータの電圧出力を右のDCモータの出力より大きくすれば、右に曲がることができます。詳しい説明は他の方のサイトをご覧ください。私はこちらのサイトを参考にさせて頂きました。
https://dotstud.io/docs/pulse-width-modulation/

環境

  • Raspberry Pi 3B raspbian 9.4
  • Python 3.5.3

アーキテクチャ

architecture1.png

KeyBoard操作

Key 動作
前進
右に少し移動
左に少し移動
後退
r 右回転
l 左回転
return 停止
q 終了

ソースコード

main.py
# import curses and time and GPIO
import curses
import time
import RPi.GPIO as GPIO


def go_straight(rightDC, leftDC):

    GPIO.output(Lpin1, True)
    GPIO.output(Lpin2, False)
    GPIO.output(Rpin1, True)
    GPIO.output(Rpin2, False)

    pwmL.ChangeDutyCycle(leftDC)
    pwmR.ChangeDutyCycle(rightDC)

def go_back(rightDC, leftDC):

    GPIO.output(Lpin1, False)
    GPIO.output(Lpin2, True)
    GPIO.output(Rpin1, False)
    GPIO.output(Rpin2, True)

    pwmL.ChangeDutyCycle(leftDC)
    pwmR.ChangeDutyCycle(rightDC)

def turn_left(rightDC, leftDC):

    GPIO.output(Lpin1, True)
    GPIO.output(Lpin2, False)
    GPIO.output(Rpin1, True)
    GPIO.output(Rpin2, False)

    pwmL.ChangeDutyCycle(leftDC)
    pwmR.ChangeDutyCycle(rightDC)

def turn_right(rightDC, leftDC):

    GPIO.output(Lpin1, True)
    GPIO.output(Lpin2, False)
    GPIO.output(Rpin1, True)
    GPIO.output(Rpin2, False)

    pwmL.ChangeDutyCycle(leftDC)
    pwmR.ChangeDutyCycle(rightDC)

def rotation_right():

    GPIO.output(Lpin1, True)
    GPIO.output(Lpin2, False)
    GPIO.output(Rpin1, False)
    GPIO.output(Rpin2, True)

    pwmL.ChangeDutyCycle(70)
    pwmR.ChangeDutyCycle(70)

def rotation_left():

    GPIO.output(Lpin1, False)
    GPIO.output(Lpin2, True)
    GPIO.output(Rpin1, True)
    GPIO.output(Rpin2, False)

    pwmL.ChangeDutyCycle(70)
    pwmR.ChangeDutyCycle(70)

def stop():

    GPIO.output(Lpin1, False)
    GPIO.output(Lpin2, False)
    GPIO.output(Rpin1, False)
    GPIO.output(Rpin2, False)

#set GPIO numbering mode and define output pins
Lpin1 = 16
Lpin2 = 18
Lpin3 = 33
Rpin1 = 15
Rpin2 = 13
Rpin3 = 12
leftDC  = 60
rightDC = 60

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(Lpin1,GPIO.OUT)
GPIO.setup(Lpin2,GPIO.OUT)
GPIO.setup(Lpin3,GPIO.OUT)
GPIO.setup(Rpin1,GPIO.OUT)
GPIO.setup(Rpin2,GPIO.OUT)
GPIO.setup(Rpin3,GPIO.OUT)

pwmL = GPIO.PWM(Lpin3, 100)
pwmL.start(0)
pwmR = GPIO.PWM(Rpin3, 100)
pwmR.start(0)

pwmR.ChangeDutyCycle(0)
pwmL.ChangeDutyCycle(0)

# Get the curses window, turn off echoing of keyboard to screen, turn on
# instant (no waiting) key response, and use special values for cursor keys
screen = curses.initscr()
curses.noecho()
curses.cbreak()
screen.keypad(True)

try:
    while True:
        char = screen.getch()
        if char == ord('q'):
            break

        elif char == curses.KEY_UP:
            leftDC  = 60
            rightDC = 60
            go_straight(leftDC, rightDC)

        elif char == curses.KEY_DOWN:
            leftDC  = 50
            rightDC = 50
            go_back(leftDC, rightDC)

        elif char == curses.KEY_RIGHT:
            leftDC  = leftDC  + 10
            rightDC = rightDC - 10

            if leftDC >= 100:
                leftDC = 100

            if rightDC <= 30:
                rightDC = 30

            turn_right(leftDC, rightDC)

        elif char == curses.KEY_LEFT:
            leftDC  = leftDC  - 10
            rightDC = rightDC + 10

            if leftDC <= 30:
                leftDC = 30

            if rightDC >= 100:
                rightDC = 100

            turn_right(leftDC, rightDC)

        elif char == ord('l'):
            rotation_left()
            leftDC  = 60
            rightDC = 60

        elif char == ord('r'):
            rotation_right()
            leftDC  = 60
            rightDC = 60

        # return
        elif char == 10:
            stop()
            leftDC  = 60
            rightDC = 60

finally:

    # Close down curses properly, inc turn echo back on!
    curses.nocbreak(); screen.keypad(0); curses.echo()
    curses.endwin()
    GPIO.cleanup()

結果

https://youtu.be/b4VyaNFIfI8
rCar2.png

最後に

このコースも自動で走らせてみたいですね。

参考

https://www.youtube.com/watch?v=j6mglfhWZrQ&t=243s

追記

ブログの方でも紹介しています。
こちらもぜひよろしくお願いします。
ラジコンカーをPWM制御して走らせる - Revel Tech Blog

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1