概要
RaspberryPiのDCモータをPWM制御することでラジコンカーを動かします。今回はMacからRaspberryPiにSSHでリモート接続し手元のキーボードから操作できるようにしています。コースを以下のように作って実際に走らせてみました。
PWM制御とは
PWM制御とは、スイッチのオンとオフのスイッチングを高速で行い、擬似的に出力電圧を制御するというものです。出力電圧を制御することによってラジコンカーを右や左方向に曲がる動作を行うことができます。例えば左のDCモータの電圧出力を右のDCモータの出力より大きくすれば、右に曲がることができます。詳しい説明は他の方のサイトをご覧ください。私はこちらのサイトを参考にさせて頂きました。
https://dotstud.io/docs/pulse-width-modulation/
環境
- Raspberry Pi 3B raspbian 9.4
- Python 3.5.3
アーキテクチャ

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://www.youtube.com/watch?v=j6mglfhWZrQ&t=243s
追記
ブログの方でも紹介しています。
こちらもぜひよろしくお願いします。
ラジコンカーをPWM制御して走らせる - Revel Tech Blog