DC모터?
때문에 일반적인 모터가 역회전 하기 위해선 수작업으로 전류의 방향을 바꾸어주거나 해당 역할을 수행하는 모듈이 있어야 한다. 이를 모터 드라이버 라고 칭한다.
해당 RC카에는 좌측의 1개 우측의 1개로 총 2개의 모터 드라이버(TB6612)가 탑재되어 있다.
control PIN
A channel
B channel
1. 좌측 모터 드라이버를 이용하여 좌츠 바퀴를 회전 시켜보자 (motor.py)
import RPi.GPIO as gpio
import time
PWMA = 18
AIN1 = 22
AIN2 = 27
gpio.setmode(gpio.BCM)
gpio.setup(PWMA, gpio.OUT)
gpio.setup(AIN1, gpio.OUT)
gpio.setup(AIN2, gpio.OUT)
L_Motor = gpio.PWM(PWMA, 500) # PWM 주파수 설정
L_Motor.start(0)
try:
while True:
# 동작부
gpio.output(AIN1, 0) # AIN1가 HIGH이면 전진, AIN2가 HIGH이면 후진, 둘다 HIGH하면 과부화 온다.
gpio.output(AIN2, 1) # gpio.HIGH == 0, LOW == 1
L_Motor.ChangeDutyCycle(50) # pwm 동작 백분율 100이면 100%이다.
time.sleep(0.5)
# 정지부
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_Motor.ChangeDutyCycle(0)
time.sleep(0.5)
except KeyboardInterrupt:
pass
gpio.cleanup()
L_Motor.stop()
일반적인 LED 모듈 출력 (펄스 100%)
from IPython.display import YouTubeVideo
YouTubeVideo('BdIGOH-fQjI', 300, 200)
PWM 기능으로 출력을 20%까지 떨어트린 LED모듈 (펄스 20%)
from IPython.display import YouTubeVideo
YouTubeVideo('bgrV0uwUQ9A', 300, 200)
이제 우리는 이 신호를 일정한 규격(주파수 / hz)으로 나눌 것이다.
- 본래 주파수란 1초 동안 음파의 떨림의 횟수를 뜻하지만
- 지금은 1초 동안 켜짐과 꺼짐을 감지하는 행동을 반복하는 횟수로 생각하면 좋다.
이제 이 500개의 등분 들의 켜짐과 꺼짐의 비율을 설정해 줄 것이다
DutyCycle
2. 속도 변화 예제 (motor2.py)
import RPi.GPIO as gpio
import time
PWMA = 18
AIN1 = 22
AIN2 = 27
gpio.setmode(gpio.BCM)
gpio.setup(PWMA, gpio.OUT)
gpio.setup(AIN1, gpio.OUT)
gpio.setup(AIN2, gpio.OUT)
L_Motor = gpio.PWM(PWMA, 500) # 각 모듈마다 허용된 주파수가 정해져 있다 (정해진 주파수를 초과해서 on/off를 반복하면 상식적으로 과부화가 올 것이다.)
L_Motor.start(0)
try:
while True:
# 동작부
gpio.output(AIN1, 0) # gpio.HIGH
gpio.output(AIN2, 1) # gpio.LOW
time.sleep(0.5)
gpio.output(AIN1, 0) # gpio.HIGH
gpio.output(AIN2, 1) # gpio.LOW
L_Motor.ChangeDutyCycle(50) # 50%로 하강
time.sleep(0.5)
# 정지부
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_Motor.ChangeDutyCycle(0)
time.sleep(0.5)
# 동작부
gpio.output(AIN1, 0) # gpio.HIGH
gpio.output(AIN2, 1) # gpio.LOW
L_Motor.ChangeDutyCycle(100) # pwm 동작 백분율 100이면 100%이다.
time.sleep(0.5)
gpio.output(AIN1, 0) # gpio.HIGH
gpio.output(AIN2, 1) # gpio.LOW
L_Motor.ChangeDutyCycle(70) # 70%로 하강
time.sleep(0.5)
# 정지부
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_Motor.ChangeDutyCycle(0)
time.sleep(0.5)
except KeyboardInterrupt:
pass
gpio.cleanup()
L_Motor.stop()
3. 방향전환 예제 (motor3.py)
import RPi.GPIO as gpio
import time
PWMA = 18 # 좌측 모터 드라이브
AIN1 = 22 # 정방향
AIN2 = 27 # 역방향
gpio.setmode(gpio.BCM)
gpio.setup(PWMA, gpio.OUT)
gpio.setup(AIN1, gpio.OUT)
gpio.setup(AIN2, gpio.OUT)
L_Motor = gpio.PWM(PWMA, 500)
L_Motor.start(0) # 시작 주파수 0 == LOW
try:
while True:
gpio.output(AIN1, 0) # 정방향 HIGH
gpio.output(AIN2, 1) # 역방향 LOW
L_Motor.ChangeDutyCycle(50)
time.sleep(0.5)
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_Motor.ChangeDutyCycle(0)
time.sleep(0.5)
gpio.output(AIN1, 1)
gpio.output(AIN2, 0)
L_Motor.ChangeDutyCycle(50)
time.sleep(0.5)
gpio.output(AIN1, 1)
gpio.output(AIN2, 0)
L_Motor.ChangeDutyCycle(0)
time.sleep(0.5)
except KeyboardInterrupt:
pass
gpio.cleanup()
L_Motor.stop()
1단계. 뼈대 제작하기 (motor4-1.py)
import RPi.GPIO as gpio
import time
# SW1 = 5
# SW2 = 6
# SW3 = 13
# SW4 = 19
sw = [5,6,13,19]
gpio.setmode(gpio.BCM)
# SWITCH setup
for i in sw:
gpio.setup(i, gpio.IN, pull_up_down=gpio.PUD_DOWN)
try:
while True:
if gpio.input(sw[0]) == gpio.HIGH:
print("go")
elif gpio.input(sw[1]) == gpio.HIGH:
print("right")
elif gpio.input(sw[2]) == gpio.HIGH:
print("left")
elif gpio.input(sw[3]) == gpio.HIGH:
print("back")
else:
print("stop")
time.sleep(0.1)
except KeyboardInterrupt:
pass
gpio.cleanup()
2단계. 전진후진 기능 구현 (motor4-2.py)
import RPi.GPIO as gpio
import time
gpio.setmode(gpio.BCM)
SW1 = 5
SW2 = 6
SW3 = 13
SW4 = 19
PWMA = 18
AIN1 = 22
AIN2 = 27
PWMB = 23
BIN1 = 25
BIN2 = 24
sw = [5,6,13,19]
driveA = [18, 22, 27]
driveB = [23, 25, 24]
# SWITCH setup
for i in sw:
# 스위치의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.IN, pull_up_down=gpio.PUD_DOWN)
# drive setup
for i in driveA:
# 드라이브의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.OUT)
for i in driveB:
# 드라이브의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.OUT)
# 모터 드라이브 PWM 설정
L_M = gpio.PWM(PWMA, 500)
L_M.start(0)
R_M = gpio.PWM(PWMB, 500)
R_M.start(0)
try:
while True:
if gpio.input(sw[0]) == gpio.HIGH:
print("go")
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_M.ChangeDutyCycle(50)
gpio.output(BIN1, 0)
gpio.output(BIN2, 1)
R_M.ChangeDutyCycle(50)
elif gpio.input(sw[1]) == gpio.HIGH:
print("right")
elif gpio.input(sw[2]) == gpio.HIGH:
print("left")
elif gpio.input(sw[3]) == gpio.HIGH:
print("back")
gpio.output(AIN1, 1)
gpio.output(AIN2, 0)
L_M.ChangeDutyCycle(50)
gpio.output(BIN1, 1)
gpio.output(BIN2, 0)
R_M.ChangeDutyCycle(50)
else:
print("stop")
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_M.ChangeDutyCycle(0)
gpio.output(BIN1, 0)
gpio.output(BIN2, 1)
R_M.ChangeDutyCycle(0)
time.sleep(0.1)
except KeyboardInterrupt:
pass
gpio.cleanup()
3단계 좌회전 우회전 기능 구현화 (motor4-3.py)
import RPi.GPIO as gpio
import time
gpio.setmode(gpio.BCM)
SW1 = 5
SW2 = 6
SW3 = 13
SW4 = 19
PWMA = 18
AIN1 = 22
AIN2 = 27
PWMB = 23
BIN1 = 25
BIN2 = 24
sw = [5,6,13,19]
driveA = [18, 22, 27]
driveB = [23, 25, 24]
# SWITCH setup
for i in sw:
# 스위치의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.IN, pull_up_down=gpio.PUD_DOWN)
# drive setup
for i in driveA:
# 드라이브의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.OUT)
for i in driveB:
# 드라이브의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.OUT)
# 모터 드라이브 PWM 설정
L_M = gpio.PWM(PWMA, 500)
L_M.start(0)
R_M = gpio.PWM(PWMB, 500)
R_M.start(0)
try:
while True:
if gpio.input(sw[0]) == gpio.HIGH:
print("go")
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_M.ChangeDutyCycle(50)
gpio.output(BIN1, 0)
gpio.output(BIN2, 1)
R_M.ChangeDutyCycle(50)
elif gpio.input(sw[1]) == gpio.HIGH:
print("right")
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_M.ChangeDutyCycle(50)
gpio.output(BIN1, 1)
gpio.output(BIN2, 0)
R_M.ChangeDutyCycle(50)
elif gpio.input(sw[2]) == gpio.HIGH:
print("left")
gpio.output(AIN1, 1)
gpio.output(AIN2, 0)
L_M.ChangeDutyCycle(50)
gpio.output(BIN1, 0)
gpio.output(BIN2, 1)
R_M.ChangeDutyCycle(50)
elif gpio.input(sw[3]) == gpio.HIGH:
print("back")
gpio.output(AIN1, 1)
gpio.output(AIN2, 0)
L_M.ChangeDutyCycle(50)
gpio.output(BIN1, 1)
gpio.output(BIN2, 0)
R_M.ChangeDutyCycle(50)
else:
print("stop")
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_M.ChangeDutyCycle(0)
gpio.output(BIN1, 0)
gpio.output(BIN2, 1)
R_M.ChangeDutyCycle(0)
time.sleep(0.1)
except KeyboardInterrupt:
pass
gpio.cleanup()
4단계. 함수 모듈화 (motor4-4.py)
import RPi.GPIO as gpio
import time
gpio.setmode(gpio.BCM)
SW1 = 5
SW2 = 6
SW3 = 13
SW4 = 19
PWMA = 18
AIN1 = 22
AIN2 = 27
PWMB = 23
BIN1 = 25
BIN2 = 24
sw = [5,6,13,19]
driveA = [18, 22, 27]
driveB = [23, 25, 24]
# SWITCH setup
for i in sw:
# 스위치의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.IN, pull_up_down=gpio.PUD_DOWN)
# drive setup
for i in driveA:
# 드라이브의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.OUT)
for i in driveB:
# 드라이브의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.OUT)
# 모터 드라이브 PWM 설정
L_M = gpio.PWM(PWMA, 500)
L_M.start(0)
R_M = gpio.PWM(PWMB, 500)
R_M.start(0)
def forward(speed):
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_M.ChangeDutyCycle(speed)
gpio.output(BIN1, 0)
gpio.output(BIN2, 1)
R_M.ChangeDutyCycle(speed)
def backward(speed):
gpio.output(AIN1, 1)
gpio.output(AIN2, 0)
L_M.ChangeDutyCycle(speed)
gpio.output(BIN1, 1)
gpio.output(BIN2, 0)
R_M.ChangeDutyCycle(speed)
def right(speed):
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_M.ChangeDutyCycle(speed)
gpio.output(BIN1, 1)
gpio.output(BIN2, 0)
R_M.ChangeDutyCycle(speed)
def left(speed):
gpio.output(AIN1, 1)
gpio.output(AIN2, 0)
L_M.ChangeDutyCycle(speed)
gpio.output(BIN1, 0)
gpio.output(BIN2, 1)
R_M.ChangeDutyCycle(speed)
def stop():
gpio.output(AIN1, 0)
gpio.output(AIN2, 1)
L_M.ChangeDutyCycle(0)
gpio.output(BIN1, 0)
gpio.output(BIN2, 1)
R_M.ChangeDutyCycle(0)
try:
while True:
if gpio.input(sw[0]) == gpio.HIGH:
print("go")
forward(50)
elif gpio.input(sw[1]) == gpio.HIGH:
print("right")
right(50)
elif gpio.input(sw[2]) == gpio.HIGH:
print("left")
left(50)
elif gpio.input(sw[3]) == gpio.HIGH:
print("back")
backward(50)
else:
print("stop")
stop()
time.sleep(0.1)
except KeyboardInterrupt:
pass
gpio.cleanup()
5단계. gpio 인터럽트 함수 (아직)
6단계. 통합 함수 (motor4-6.py)
import RPi.GPIO as gpio
import time
gpio.setmode(gpio.BCM)
SW1 = 5
SW2 = 6
SW3 = 13
SW4 = 19
PWMA = 18
AIN1 = 22
AIN2 = 27
PWMB = 23
BIN1 = 25
BIN2 = 24
sw = [5,6,13,19]
driveA = [18, 22, 27]
driveB = [23, 25, 24]
# SWITCH setup
for i in sw:
# 스위치의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.IN, pull_up_down=gpio.PUD_DOWN)
# drive setup
for i in driveA:
# 드라이브의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.OUT)
for i in driveB:
# 드라이브의 모든 setup 설정이 같기 때문에 반복문으로 진행 가능
gpio.setup(i, gpio.OUT)
# 모터 드라이브 PWM 설정
L_M = gpio.PWM(PWMA, 500)
L_M.start(0)
R_M = gpio.PWM(PWMB, 500)
R_M.start(0)
def motor(speed, A, B):
gpio.output(AIN1, A)
if A <= 0:
A2 = 1
else:
A2 = 0
gpio.output(AIN2, A2)
L_M.ChangeDutyCycle(speed)
gpio.output(BIN1, B)
if B <= 0:
B2 = 1
else:
B2 = 0
gpio.output(BIN2, B2)
R_M.ChangeDutyCycle(speed)
try:
while True:
if gpio.input(sw[0]) == gpio.HIGH:
print("go")
motor(50, 0, 0)
elif gpio.input(sw[1]) == gpio.HIGH:
print("right")
motor(50, 0, 1)
elif gpio.input(sw[2]) == gpio.HIGH:
print("left")
motor(50, 1, 0)
elif gpio.input(sw[3]) == gpio.HIGH:
print("back")
motor(50, 1, 1)
else:
print("stop")
motor(0, 0, 0)
time.sleep(0.1)
except KeyboardInterrupt:
pass
gpio.cleanup()